From f0c9b6844bb2e8e00298c895f2f65ee298f69d27 Mon Sep 17 00:00:00 2001 From: CameronTEllis Date: Fri, 27 Mar 2020 18:24:59 -0400 Subject: [PATCH 01/36] Moved the RT fmrisim generator and updated it to use resource stream --- .../utils/fmrisim_real_time_generator.py | 69 +++++-- .../utils/sim_parameters/ROI_A.nii.gz | Bin .../utils/sim_parameters/ROI_B.nii.gz | Bin .../{ => sim_parameters}/grey_matter_mask.npy | Bin .../utils/sim_parameters/sub_noise_dict.txt | 0 .../utils/sim_parameters/sub_template.nii.gz | Bin examples/utils/sim_parameters/mask.npy | Bin 153674 -> 0 bytes setup.py | 7 +- tests/utils/test_fmrisim_real_time.py | 176 ++++++++++++++++++ 9 files changed, 232 insertions(+), 20 deletions(-) rename examples/utils/fmrisim_real-time_generator.py => brainiak/utils/fmrisim_real_time_generator.py (88%) rename {examples => brainiak}/utils/sim_parameters/ROI_A.nii.gz (100%) rename {examples => brainiak}/utils/sim_parameters/ROI_B.nii.gz (100%) rename brainiak/utils/{ => sim_parameters}/grey_matter_mask.npy (100%) rename {examples => brainiak}/utils/sim_parameters/sub_noise_dict.txt (100%) rename {examples => brainiak}/utils/sim_parameters/sub_template.nii.gz (100%) delete mode 100644 examples/utils/sim_parameters/mask.npy create mode 100644 tests/utils/test_fmrisim_real_time.py diff --git a/examples/utils/fmrisim_real-time_generator.py b/brainiak/utils/fmrisim_real_time_generator.py similarity index 88% rename from examples/utils/fmrisim_real-time_generator.py rename to brainiak/utils/fmrisim_real_time_generator.py index bf7dd782d..ad7905c5a 100644 --- a/examples/utils/fmrisim_real-time_generator.py +++ b/brainiak/utils/fmrisim_real_time_generator.py @@ -165,8 +165,7 @@ def write_dicom(output_name, ds.save_as(output_name) -def generate_data(inputDir, - outputDir, +def generate_data(outputDir, data_dict): # Generate simulated fMRI data with a few parameters that might be # relevant for real time analysis @@ -194,8 +193,13 @@ def generate_data(inputDir, os.makedirs(outputDir, exist_ok=True) print('Load template of average voxel value') - templateFile = os.path.join(inputDir, 'sub_template.nii.gz') - template_nii = nibabel.load(templateFile) + + if data_dict['template_path'] is None: + template_path = resource_stream(__name__, 'sub_template.nii.gz') + else: + template_path = data_dict['template_path'] + + template_nii = nibabel.load(template_path) template = template_nii.get_data() dimensions = np.array(template.shape[0:3]) @@ -211,8 +215,14 @@ def generate_data(inputDir, # Load the noise dictionary print('Loading noise parameters') - noiseFile = os.path.join(inputDir, 'sub_noise_dict.txt') - with open(noiseFile, 'r') as f: + + # Load in the noise dict if supplied + if data_dict['noise_dict_file'] is None: + noise_dict_file = resource_stream(__name__, 'sub_noise_dict.txt') + else: + noise_dict_file = data_dict['noise_dict_file'] + + with open(noise_dict_file, 'r') as f: noise_dict = f.read() noise_dict = eval(noise_dict) noise_dict['matched'] = 0 # Increases processing time @@ -267,18 +277,26 @@ def generate_data(inputDir, outFile = os.path.join(outputDir, 'labels.npy') np.save(outFile, (stimfunc_A + (stimfunc_B * 2))) - roiA_file = os.path.join(inputDir, 'ROI_A.nii.gz') - roiB_file = os.path.join(inputDir, 'ROI_B.nii.gz') + # Load in the ROIs + if data_dict['ROI_A_file'] is None: + ROI_A_file = resource_stream(__name__, 'ROI_A.nii.gz') + else: + ROI_A_file = data_dict['ROI_A_file'] + + if data_dict['ROI_B_file'] is None: + ROI_B_file = resource_stream(__name__, 'ROI_B.nii.gz') + else: + ROI_B_file = data_dict['ROI_B_file'] # How is the signal implemented in the different ROIs - signal_A = generate_ROIs(roiA_file, + signal_A = generate_ROIs(ROI_A_file, stimfunc_A, noise, data_dict['scale_percentage'], data_dict) if data_dict['different_ROIs'] is True: - signal_B = generate_ROIs(roiB_file, + signal_B = generate_ROIs(ROI_B_file, stimfunc_B, noise, data_dict['scale_percentage'], @@ -288,13 +306,13 @@ def generate_data(inputDir, # Halve the evoked response if these effects are both expected in the same ROI if data_dict['multivariate_pattern'] is False: - signal_B = generate_ROIs(roiA_file, + signal_B = generate_ROIs(ROI_A_file, stimfunc_B, noise, data_dict['scale_percentage'] * 0.5, data_dict) else: - signal_B = generate_ROIs(roiA_file, + signal_B = generate_ROIs(ROI_A_file, stimfunc_B, noise, data_dict['scale_percentage'], @@ -335,10 +353,16 @@ def generate_data(inputDir, 'Specify input arguments. Some arguments are parameters that require ' 'an input is provided (noted by "Param"), others are flags that when ' 'provided will change according to the flag (noted by "Flag")') - argParser.add_argument('--inputDir', '-i', default=None, type=str, - help='Param. Input directory for fmrisim parameters') argParser.add_argument('--outputDir', '-o', default=None, type=str, help='Param. Output directory for simulated data') + argParser.add_argument('--ROI_A_file', default=None, type=str, + help='Param. Full path to file for cond. A ROI') + argParser.add_argument('--ROI_B_file', default=None, type=str, + help='Param. Full path to file for cond. B ROI') + argParser.add_argument('--template_path', default=None, type=str, + help='Param. Full path to file for brain template') + argParser.add_argument('--noise_dict_file', default=None, type=str, + help='Param. Full path to file setting noise params') argParser.add_argument('--numTRs', '-n', default=200, type=int, help='Param. Number of time points') argParser.add_argument('--eventDuration', '-d', default=10, type=int, @@ -360,17 +384,25 @@ def generate_data(inputDir, 'the acquisition rate') args = argParser.parse_args() - inputDir = args.inputDir + # Essential arguments outputDir = args.outputDir - if inputDir is None or outputDir is None: - print("Must specify an input and output directory using -i and -o") + if outputDir is None: + print("Must specify an output directory using -o") exit(-1) data_dict = {} ## User controlled settings + # Specify the path to the files used for defining ROIs. + data_dict['ROI_A_file'] = args.ROI_A_file + data_dict['ROI_B_file'] = args.ROI_B_file + + # Specify where the template + data_dict['template_path'] = args.template_path + data_dict['noise_dict_file'] = args.noise_dict_file + # Specify the number of time points data_dict['numTRs'] = args.numTRs @@ -407,6 +439,5 @@ def generate_data(inputDir, data_dict['burn_in'] = 6 # Run the function if running from command line - generate_data(inputDir, - outputDir, + generate_data(outputDir, data_dict) diff --git a/examples/utils/sim_parameters/ROI_A.nii.gz b/brainiak/utils/sim_parameters/ROI_A.nii.gz similarity index 100% rename from examples/utils/sim_parameters/ROI_A.nii.gz rename to brainiak/utils/sim_parameters/ROI_A.nii.gz diff --git a/examples/utils/sim_parameters/ROI_B.nii.gz b/brainiak/utils/sim_parameters/ROI_B.nii.gz similarity index 100% rename from examples/utils/sim_parameters/ROI_B.nii.gz rename to brainiak/utils/sim_parameters/ROI_B.nii.gz diff --git a/brainiak/utils/grey_matter_mask.npy b/brainiak/utils/sim_parameters/grey_matter_mask.npy similarity index 100% rename from brainiak/utils/grey_matter_mask.npy rename to brainiak/utils/sim_parameters/grey_matter_mask.npy diff --git a/examples/utils/sim_parameters/sub_noise_dict.txt b/brainiak/utils/sim_parameters/sub_noise_dict.txt similarity index 100% rename from examples/utils/sim_parameters/sub_noise_dict.txt rename to brainiak/utils/sim_parameters/sub_noise_dict.txt diff --git a/examples/utils/sim_parameters/sub_template.nii.gz b/brainiak/utils/sim_parameters/sub_template.nii.gz similarity index 100% rename from examples/utils/sim_parameters/sub_template.nii.gz rename to brainiak/utils/sim_parameters/sub_template.nii.gz diff --git a/examples/utils/sim_parameters/mask.npy b/examples/utils/sim_parameters/mask.npy deleted file mode 100644 index d3f1757fe092c97ea9ad96badaff68159b40a02a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 153674 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 RJ8(O2J8(O2JMhsC{6Cy+-KPKm diff --git a/setup.py b/setup.py index e394f6c85..b4265d14c 100644 --- a/setup.py +++ b/setup.py @@ -150,7 +150,12 @@ def finalize_options(self): ext_modules=ext_modules, cmdclass={'build_ext': BuildExt}, packages=find_packages(), - package_data={'brainiak.utils': ['grey_matter_mask.npy']}, + package_data={'brainiak.utils.sim_parameters': ['grey_matter_mask.npy', + 'ROI_A.nii.gz', + 'ROI_B.nii.gz', + 'mask.npy', + 'sub_noise_dict.txt', + 'sub_template.nii.gz']}, python_requires='>=3.5', zip_safe=False, ) diff --git a/tests/utils/test_fmrisim_real_time.py b/tests/utils/test_fmrisim_real_time.py new file mode 100644 index 000000000..1c17aa9e2 --- /dev/null +++ b/tests/utils/test_fmrisim_real_time.py @@ -0,0 +1,176 @@ +# Copyright 2016 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""fmrisim real-time generator test script + + Authors: Cameron Ellis (Princeton) 2020 +""" +import numpy as np +import math +from brainiak.utils import fmrisim_real_time_generator as gen +import pytest +from itertools import product +import os +import nibabel as nib +import time +import glob +import copy + +# Test that it crashes without inputs +with pytest.raises(TypeError): + gen.generate_data() + +# Set up the default values +outputDir = tmp_path + +data_dict = {} +data_dict['ROI_A_file'] = resource_stream(__name__, "ROI_A.nii.gz") +data_dict['ROI_B_file'] = resource_stream(__name__, "ROI_B.nii.gz") +data_dict['template_path'] = resource_stream(__name__, "sub_template.nii.gz") +data_dict['noise_dict_file'] = resource_stream(__name__, "sub_noise_dict.txt") +data_dict['numTRs'] = 30 +data_dict['event_duration'] = 2 +data_dict['scale_percentage'] = 1 +data_dict['different_ROIs'] = True +data_dict['multivariate_pattern'] = False +data_dict['save_dicom'] = False +data_dict['save_realtime'] = False +data_dict['trDuration'] = 2 +data_dict['isi'] = 4 +data_dict['burn_in'] = 6 + +# Run default test +def test_default(outputDir=outputDir, dd=data_dict): + + # Make sure you don't edit the data dict + dd = copy.deepcopy(dd) + + # Clean directory + os.system('rm -rf %s' % outputDir) + + # Run the simulation + gen.generate_data(outputDir, + dd) + + # Check that there are 32 files where there should be (30 plus label and + # mask) + assert len(os.listdir(outputDir)) == 32, "Incorrect file number" + + # Check that the data is the right shape + input_template = nib.load(dd['template_path']) + input_shape = input_template.shape + output_vol = np.load(outputDir + 'rt_000.npy') + output_shape = output_vol.shape + assert input_shape == output_shape, 'Output shape is incorrect' + + # Check the labels have the correct count + labels = np.load(outputDir + 'labels.npy') + + assert np.sum(labels > 0) == 9, 'Incorrect number of events' + + +def test_signal_size(outputDir=outputDir, dd=data_dict): + + # Make sure you don't edit the data dict + dd = copy.deepcopy(dd) + + # Change it to only use ROI A + dd['different_ROIs'] = False + + # Make the signal large + dd['scale_percentage'] = 100 + + # Clean directory + os.system('rm -rf %s' % outputDir) + + # Run the simulation + gen.generate_data(outputDir, + dd) + + # Load in the ROI masks + ROI_A = nib.load(dd['ROI_A_file']).get_data() + ROI_B = nib.load(dd['ROI_B_file']).get_data() + + # Load in the data just simulated + ROI_A_mean = [] + ROI_B_mean = [] + for TR_counter in range(dd['numTRs']): + + # Load the data + vol = np.load(outputDir + 'rt_%03d.npy' % TR_counter) + + # Mask the data + ROI_A_mean += [np.mean(vol[ROI_A == 1])] + ROI_B_mean += [np.mean(vol[ROI_B == 1])] + + assert np.std(ROI_A_mean) > np.std(ROI_B_mean), 'Signal not scaling' + + +# Run default test +def test_save_dicoms_realtime(outputDir=outputDir, dd=data_dict): + + # Make sure you don't edit the data dict + dd = copy.deepcopy(dd) + + # Clean directory + os.system('rm -rf %s' % outputDir) + + dd['save_dicom'] = True + dd['save_realtime'] = True + + start_time = time.time() + + # Run the simulation + gen.generate_data(outputDir, + dd) + + end_time = time.time() + + # Check it took 2s per TR + assert (end_time - start_time) > 60, 'Realtime ran fast' + + # Check correct file number + assert len(glob.glob(outputDir + '*.dcm')) == 30, "Incorrect dicom file num" + + +def test_multivariate(outputDir=outputDir, dd=data_dict): + + # Make sure you don't edit the data dict + dd = copy.deepcopy(dd) + + dd['multivariate_pattern'] = True + dd['different_ROIs'] = False + + # Make the signal large + dd['scale_percentage'] = 100 + + # Clean directory + os.system('rm -rf %s' % outputDir) + + # Run the simulation + gen.generate_data(outputDir, + dd) + + # Load in the ROI masks + ROI_A = nib.load(dd['ROI_A_file']).get_data() + ROI_B = nib.load(dd['ROI_B_file']).get_data() + + # Test this volume + vol = np.load(outputDir + 'rt_007.npy') + + ROI_A_std = np.std(vol[ROI_A == 1]) + ROI_B_std = np.std(vol[ROI_B == 1]) + + assert ROI_A_std > ROI_B_std, 'Multivariate test not making variable signal' + From b9f11aed775fb37c3ee1777620ec8847251bdcfd Mon Sep 17 00:00:00 2001 From: CameronTEllis Date: Sat, 28 Mar 2020 12:23:40 -0400 Subject: [PATCH 02/36] PEP8 issues --- brainiak/utils/fmrisim_real_time_generator.py | 161 ++++++++++-------- 1 file changed, 89 insertions(+), 72 deletions(-) diff --git a/brainiak/utils/fmrisim_real_time_generator.py b/brainiak/utils/fmrisim_real_time_generator.py index ad7905c5a..d0e5959b3 100644 --- a/brainiak/utils/fmrisim_real_time_generator.py +++ b/brainiak/utils/fmrisim_real_time_generator.py @@ -1,7 +1,7 @@ # Generate simulated fMRI data with a few parameters that might be relevant # for real time analysis # This code can be run as a function in python or from the command line: -# python fmrisim_real-time_generator --inputDir fmrisim_files/ --outputDir data/ +# python fmrisim_real-time_generator --inputDir fmrisim_files/ --outputDir data # # The input arguments are: # Required: @@ -27,27 +27,28 @@ # burn_in - How long before the first event (in seconds) import os -import glob import time -import random import argparse import datetime import nibabel # type: ignore import numpy as np # type: ignore import pydicom as dicom from brainiak.utils import fmrisim as sim # type: ignore -import sys +import logging +logger = logging.getLogger(__name__) +from pkg_resources import resource_stream + script_datetime = datetime.datetime.now() -def generate_ROIs(ROI_file, - stimfunc, - noise, - scale_percentage, - data_dict): +def _generate_ROIs(ROI_file, + stimfunc, + noise, + scale_percentage, + data_dict): # Create the signal in the ROI as specified. - print('Loading', ROI_file) + logger.info('Loading', ROI_file) nii = nibabel.load(ROI_file) ROI = nii.get_data() @@ -106,9 +107,9 @@ def generate_ROIs(ROI_file, return signal -def write_dicom(output_name, - data, - image_number=0): +def _write_dicom(output_name, + data, + image_number=0): # Write the data to a dicom file. # Dicom files are difficult to set up correctly, this file will likely # crash when trying to open it using dcm2nii. However, if it is loaded in @@ -165,6 +166,35 @@ def write_dicom(output_name, ds.save_as(output_name) +def _get_input_names(data_dict): + + # Load in the ROIs + if data_dict['ROI_A_file'] is None: + ROI_A_file = resource_stream(__name__, 'ROI_A.nii.gz') + else: + ROI_A_file = data_dict['ROI_A_file'] + + if data_dict['ROI_B_file'] is None: + ROI_B_file = resource_stream(__name__, 'ROI_B.nii.gz') + else: + ROI_B_file = data_dict['ROI_B_file'] + + # Get the path to the template + if data_dict['template_path'] is None: + template_path = resource_stream(__name__, 'sub_template.nii.gz') + else: + template_path = data_dict['template_path'] + + # Load in the noise dict if supplied + if data_dict['noise_dict_file'] is None: + noise_dict_file = resource_stream(__name__, 'sub_noise_dict.txt') + else: + noise_dict_file = data_dict['noise_dict_file'] + + # Return the paths + return ROI_A_file, ROI_B_file, template_path, noise_dict_file + + def generate_data(outputDir, data_dict): # Generate simulated fMRI data with a few parameters that might be @@ -189,22 +219,20 @@ def generate_data(outputDir, # burn_in - How long before the first event (in seconds) # If the folder doesn't exist then make it - if os.path.isdir(outputDir) is False: - os.makedirs(outputDir, exist_ok=True) + os.system('mkdir -p %s' % outputDir) - print('Load template of average voxel value') + logger.info('Load template of average voxel value') - if data_dict['template_path'] is None: - template_path = resource_stream(__name__, 'sub_template.nii.gz') - else: - template_path = data_dict['template_path'] + # Get the file names needed for loading in the data + ROI_A_file, ROI_B_file, template_path, noise_dict_file =_get_input_names( + data_dict) template_nii = nibabel.load(template_path) template = template_nii.get_data() dimensions = np.array(template.shape[0:3]) - print('Create binary mask and normalize the template range') + logger.info('Create binary mask and normalize the template range') mask, template = sim.mask_brain(volume=template, mask_self=True, ) @@ -214,13 +242,7 @@ def generate_data(outputDir, np.save(outFile, mask.astype(np.uint8)) # Load the noise dictionary - print('Loading noise parameters') - - # Load in the noise dict if supplied - if data_dict['noise_dict_file'] is None: - noise_dict_file = resource_stream(__name__, 'sub_noise_dict.txt') - else: - noise_dict_file = data_dict['noise_dict_file'] + logger.info('Loading noise parameters') with open(noise_dict_file, 'r') as f: noise_dict = f.read() @@ -230,7 +252,7 @@ def generate_data(outputDir, # Add it here for easy access data_dict['noise_dict'] = data_dict - print('Generating noise') + logger.info('Generating noise') temp_stimfunction = np.zeros((data_dict['numTRs'], 1)) noise = sim.generate_noise(dimensions=dimensions, stimfunction_tr=temp_stimfunction, @@ -277,51 +299,42 @@ def generate_data(outputDir, outFile = os.path.join(outputDir, 'labels.npy') np.save(outFile, (stimfunc_A + (stimfunc_B * 2))) - # Load in the ROIs - if data_dict['ROI_A_file'] is None: - ROI_A_file = resource_stream(__name__, 'ROI_A.nii.gz') - else: - ROI_A_file = data_dict['ROI_A_file'] - - if data_dict['ROI_B_file'] is None: - ROI_B_file = resource_stream(__name__, 'ROI_B.nii.gz') - else: - ROI_B_file = data_dict['ROI_B_file'] # How is the signal implemented in the different ROIs - signal_A = generate_ROIs(ROI_A_file, - stimfunc_A, - noise, - data_dict['scale_percentage'], - data_dict) + signal_A = _generate_ROIs(ROI_A_file, + stimfunc_A, + noise, + data_dict['scale_percentage'], + data_dict) if data_dict['different_ROIs'] is True: - signal_B = generate_ROIs(ROI_B_file, - stimfunc_B, - noise, - data_dict['scale_percentage'], - data_dict) + signal_B = _generate_ROIs(ROI_B_file, + stimfunc_B, + noise, + data_dict['scale_percentage'], + data_dict) else: - # Halve the evoked response if these effects are both expected in the same ROI + # Halve the evoked response if these effects are both expected in the + # same ROI if data_dict['multivariate_pattern'] is False: - signal_B = generate_ROIs(ROI_A_file, - stimfunc_B, - noise, - data_dict['scale_percentage'] * 0.5, - data_dict) + signal_B = _generate_ROIs(ROI_A_file, + stimfunc_B, + noise, + data_dict['scale_percentage'] * 0.5, + data_dict) else: - signal_B = generate_ROIs(ROI_A_file, - stimfunc_B, - noise, - data_dict['scale_percentage'], - data_dict) + signal_B = _generate_ROIs(ROI_A_file, + stimfunc_B, + noise, + data_dict['scale_percentage'], + data_dict) # Combine the two signal timecourses signal = signal_A + signal_B - print('Generating TRs in real time') + logger.info('Generating TRs in real time') for idx in range(data_dict['numTRs']): # Create the brain volume on this TR @@ -333,14 +346,16 @@ def generate_data(outputDir, # Store as dicom or nifti? if data_dict['save_dicom'] is True: # Save the volume as a DICOM file, with each TR as its own file - output_file = os.path.join(outputDir, 'rt_' + format(idx, '03d') + '.dcm') - write_dicom(output_file, brain_int32, idx+1) + output_file = os.path.join(outputDir, 'rt_' + format(idx, '03d') + + '.dcm') + _write_dicom(output_file, brain_int32, idx+1) else: # Save the volume as a numpy file, with each TR as its own file - output_file = os.path.join(outputDir, 'rt_' + format(idx, '03d') + '.npy') + output_file = os.path.join(outputDir, 'rt_' + format(idx, '03d') + + '.npy') np.save(output_file, brain_int32) - print("Generate {}".format(output_file)) + logger.info("Generate {}".format(output_file)) # Sleep until next TR if data_dict['save_realtime'] == 1: @@ -362,7 +377,8 @@ def generate_data(outputDir, argParser.add_argument('--template_path', default=None, type=str, help='Param. Full path to file for brain template') argParser.add_argument('--noise_dict_file', default=None, type=str, - help='Param. Full path to file setting noise params') + help='Param. Full path to file setting noise ' + 'params') argParser.add_argument('--numTRs', '-n', default=200, type=int, help='Param. Number of time points') argParser.add_argument('--eventDuration', '-d', default=10, type=int, @@ -379,21 +395,22 @@ def generate_data(outputDir, argParser.add_argument('--saveAsDicom', default=False, action='store_true', help='Flag. Output files in DICOM format rather ' 'than numpy') - argParser.add_argument('--saveRealtime', default=False, action='store_true', - help='Flag. Save data as if it was coming in at ' - 'the acquisition rate') + argParser.add_argument('--saveRealtime', default=False, + action='store_true', help='Flag. Save data as if ' + 'it was coming in at ' + 'the acquisition rate') args = argParser.parse_args() # Essential arguments outputDir = args.outputDir if outputDir is None: - print("Must specify an output directory using -o") + logger.info("Must specify an output directory using -o") exit(-1) data_dict = {} - ## User controlled settings + # User controlled settings # Specify the path to the files used for defining ROIs. data_dict['ROI_A_file'] = args.ROI_A_file @@ -427,7 +444,7 @@ def generate_data(outputDir, # Do you want to save the data in real time (1) or as fast as possible (0)? data_dict['save_realtime'] = args.saveRealtime - ## Default settings + # Default settings # How long does each acquisition take data_dict['trDuration'] = 2 From 34afff0205b1cb32530508cdef03384327bf8335 Mon Sep 17 00:00:00 2001 From: CameronTEllis Date: Sat, 28 Mar 2020 12:36:36 -0400 Subject: [PATCH 03/36] PEP8 issues --- brainiak/utils/fmrisim_real_time_generator.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/brainiak/utils/fmrisim_real_time_generator.py b/brainiak/utils/fmrisim_real_time_generator.py index d0e5959b3..ff3652dc6 100644 --- a/brainiak/utils/fmrisim_real_time_generator.py +++ b/brainiak/utils/fmrisim_real_time_generator.py @@ -35,12 +35,13 @@ import pydicom as dicom from brainiak.utils import fmrisim as sim # type: ignore import logging -logger = logging.getLogger(__name__) from pkg_resources import resource_stream +logger = logging.getLogger(__name__) script_datetime = datetime.datetime.now() + def _generate_ROIs(ROI_file, stimfunc, noise, @@ -224,7 +225,7 @@ def generate_data(outputDir, logger.info('Load template of average voxel value') # Get the file names needed for loading in the data - ROI_A_file, ROI_B_file, template_path, noise_dict_file =_get_input_names( + ROI_A_file, ROI_B_file, template_path, noise_dict_file = _get_input_names( data_dict) template_nii = nibabel.load(template_path) @@ -299,7 +300,6 @@ def generate_data(outputDir, outFile = os.path.join(outputDir, 'labels.npy') np.save(outFile, (stimfunc_A + (stimfunc_B * 2))) - # How is the signal implemented in the different ROIs signal_A = _generate_ROIs(ROI_A_file, stimfunc_A, From 58c07e43a2cb3bb4e3ab188db118c3e86beef9c7 Mon Sep 17 00:00:00 2001 From: CameronTEllis Date: Sat, 28 Mar 2020 13:08:03 -0400 Subject: [PATCH 04/36] PEP8 issues --- tests/utils/test_fmrisim_real_time.py | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/tests/utils/test_fmrisim_real_time.py b/tests/utils/test_fmrisim_real_time.py index 1c17aa9e2..84d208282 100644 --- a/tests/utils/test_fmrisim_real_time.py +++ b/tests/utils/test_fmrisim_real_time.py @@ -17,23 +17,19 @@ Authors: Cameron Ellis (Princeton) 2020 """ import numpy as np -import math from brainiak.utils import fmrisim_real_time_generator as gen import pytest -from itertools import product import os import nibabel as nib import time import glob import copy +from pkg_resources import resource_stream # Test that it crashes without inputs with pytest.raises(TypeError): gen.generate_data() -# Set up the default values -outputDir = tmp_path - data_dict = {} data_dict['ROI_A_file'] = resource_stream(__name__, "ROI_A.nii.gz") data_dict['ROI_B_file'] = resource_stream(__name__, "ROI_B.nii.gz") @@ -50,8 +46,9 @@ data_dict['isi'] = 4 data_dict['burn_in'] = 6 + # Run default test -def test_default(outputDir=outputDir, dd=data_dict): +def test_default(outputDir=tmp_path, dd=data_dict): # Make sure you don't edit the data dict dd = copy.deepcopy(dd) @@ -80,7 +77,7 @@ def test_default(outputDir=outputDir, dd=data_dict): assert np.sum(labels > 0) == 9, 'Incorrect number of events' -def test_signal_size(outputDir=outputDir, dd=data_dict): +def test_signal_size(outputDir=tmp_path, dd=data_dict): # Make sure you don't edit the data dict dd = copy.deepcopy(dd) @@ -118,7 +115,7 @@ def test_signal_size(outputDir=outputDir, dd=data_dict): # Run default test -def test_save_dicoms_realtime(outputDir=outputDir, dd=data_dict): +def test_save_dicoms_realtime(outputDir=tmp_path, dd=data_dict): # Make sure you don't edit the data dict dd = copy.deepcopy(dd) @@ -141,10 +138,10 @@ def test_save_dicoms_realtime(outputDir=outputDir, dd=data_dict): assert (end_time - start_time) > 60, 'Realtime ran fast' # Check correct file number - assert len(glob.glob(outputDir + '*.dcm')) == 30, "Incorrect dicom file num" + assert len(glob.glob(outputDir + '*.dcm')) == 30, "Wrong dicom file num" -def test_multivariate(outputDir=outputDir, dd=data_dict): +def test_multivariate(outputDir=tmp_path, dd=data_dict): # Make sure you don't edit the data dict dd = copy.deepcopy(dd) @@ -172,5 +169,4 @@ def test_multivariate(outputDir=outputDir, dd=data_dict): ROI_A_std = np.std(vol[ROI_A == 1]) ROI_B_std = np.std(vol[ROI_B == 1]) - assert ROI_A_std > ROI_B_std, 'Multivariate test not making variable signal' - + assert ROI_A_std > ROI_B_std, 'Multivariate not making variable signal' From 61a5b8e4f819122848e4240c7ac4dd45f11851bb Mon Sep 17 00:00:00 2001 From: CameronTEllis Date: Tue, 7 Apr 2020 17:38:00 -0400 Subject: [PATCH 05/36] Updates based on comments --- brainiak/utils/fmrisim_real_time_generator.py | 55 ++++++++++--------- tests/utils/test_fmrisim_real_time.py | 20 ++++--- 2 files changed, 41 insertions(+), 34 deletions(-) diff --git a/brainiak/utils/fmrisim_real_time_generator.py b/brainiak/utils/fmrisim_real_time_generator.py index ff3652dc6..491ad73cc 100644 --- a/brainiak/utils/fmrisim_real_time_generator.py +++ b/brainiak/utils/fmrisim_real_time_generator.py @@ -1,31 +1,32 @@ # Generate simulated fMRI data with a few parameters that might be relevant # for real time analysis -# This code can be run as a function in python or from the command line: -# python fmrisim_real-time_generator --inputDir fmrisim_files/ --outputDir data -# -# The input arguments are: -# Required: -# inputDir - Specify input data dir where the parameters for fmrisim are -# outputDir - Specify output data dir where the data should be saved -# -# Optional (can be modified by flags from the command line): -# data_dict contains: -# numTRs - Specify the number of time points -# multivariate_patterns - Is the difference between conditions univariate -# (0) or multivariate (1) -# different_ROIs - Are there different ROIs for each condition (1) or is -# it in the same ROI (0). If it is the same ROI and you are using univariate -# differences, the second condition will have a smaller evoked response than -# the other. -# event_duration - How long, in seconds, is each event -# scale_percentage - What is the percent signal change -# trDuration - How many seconds per volume -# save_dicom - Do you want to save data as a dicom (1) or numpy (0) -# save_realtime - Do you want to save the data in real time (1) or as -# fast as possible (0)? -# isi - What is the time between each event (in seconds) -# burn_in - How long before the first event (in seconds) - +""" +This code can be run as a function in python or from the command line: +python fmrisim_real-time_generator --inputDir fmrisim_files/ --outputDir data + +The input arguments are: +Required: +inputDir - Specify input data dir where the parameters for fmrisim are +outputDir - Specify output data dir where the data should be saved + +Optional (can be modified by flags from the command line): +data_dict contains: + numTRs - Specify the number of time points + multivariate_patterns - Is the difference between conditions univariate + (0) or multivariate (1) + different_ROIs - Are there different ROIs for each condition (1) or is +it in the same ROI (0). If it is the same ROI and you are using univariate +differences, the second condition will have a smaller evoked response than + the other. + event_duration - How long, in seconds, is each event + scale_percentage - What is the percent signal change + trDuration - How many seconds per volume + save_dicom - Do you want to save data as a dicom (1) or numpy (0) + save_realtime - Do you want to save the data in real time (1) or as +fast as possible (0)? + isi - What is the time between each event (in seconds) + burn_in - How long before the first event (in seconds) +""" import os import time import argparse @@ -37,6 +38,8 @@ import logging from pkg_resources import resource_stream +__all__ = ["generate_data"] + logger = logging.getLogger(__name__) script_datetime = datetime.datetime.now() diff --git a/tests/utils/test_fmrisim_real_time.py b/tests/utils/test_fmrisim_real_time.py index 84d208282..4f47e86d1 100644 --- a/tests/utils/test_fmrisim_real_time.py +++ b/tests/utils/test_fmrisim_real_time.py @@ -31,10 +31,14 @@ gen.generate_data() data_dict = {} -data_dict['ROI_A_file'] = resource_stream(__name__, "ROI_A.nii.gz") -data_dict['ROI_B_file'] = resource_stream(__name__, "ROI_B.nii.gz") -data_dict['template_path'] = resource_stream(__name__, "sub_template.nii.gz") -data_dict['noise_dict_file'] = resource_stream(__name__, "sub_noise_dict.txt") +data_dict['ROI_A_file'] = resource_stream( + fmrisim_real_time_generator.__name__, "ROI_A.nii.gz") +data_dict['ROI_B_file'] = resource_stream( + fmrisim_real_time_generator.__name__, "ROI_B.nii.gz") +data_dict['template_path'] = resource_stream( + fmrisim_real_time_generator.__name__, "sub_template.nii.gz") +data_dict['noise_dict_file'] = resource_stream( + fmrisim_real_time_generator.__name__, "sub_noise_dict.txt") data_dict['numTRs'] = 30 data_dict['event_duration'] = 2 data_dict['scale_percentage'] = 1 @@ -48,7 +52,7 @@ # Run default test -def test_default(outputDir=tmp_path, dd=data_dict): +def test_default(tmp_path, dd=data_dict): # Make sure you don't edit the data dict dd = copy.deepcopy(dd) @@ -77,7 +81,7 @@ def test_default(outputDir=tmp_path, dd=data_dict): assert np.sum(labels > 0) == 9, 'Incorrect number of events' -def test_signal_size(outputDir=tmp_path, dd=data_dict): +def test_signal_size(tmp_path, dd=data_dict): # Make sure you don't edit the data dict dd = copy.deepcopy(dd) @@ -115,7 +119,7 @@ def test_signal_size(outputDir=tmp_path, dd=data_dict): # Run default test -def test_save_dicoms_realtime(outputDir=tmp_path, dd=data_dict): +def test_save_dicoms_realtime(tmp_path, dd=data_dict): # Make sure you don't edit the data dict dd = copy.deepcopy(dd) @@ -141,7 +145,7 @@ def test_save_dicoms_realtime(outputDir=tmp_path, dd=data_dict): assert len(glob.glob(outputDir + '*.dcm')) == 30, "Wrong dicom file num" -def test_multivariate(outputDir=tmp_path, dd=data_dict): +def test_multivariate(tmp_path, dd=data_dict): # Make sure you don't edit the data dict dd = copy.deepcopy(dd) From eb5fcee0c54ad10e56fd288db6f6acaefa0e12dd Mon Sep 17 00:00:00 2001 From: CameronTEllis Date: Tue, 7 Apr 2020 17:40:49 -0400 Subject: [PATCH 06/36] Does not delete contents of tmp_path when function is called --- tests/utils/test_fmrisim_real_time.py | 30 ++++++++------------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/tests/utils/test_fmrisim_real_time.py b/tests/utils/test_fmrisim_real_time.py index 4f47e86d1..6f2948bac 100644 --- a/tests/utils/test_fmrisim_real_time.py +++ b/tests/utils/test_fmrisim_real_time.py @@ -57,16 +57,13 @@ def test_default(tmp_path, dd=data_dict): # Make sure you don't edit the data dict dd = copy.deepcopy(dd) - # Clean directory - os.system('rm -rf %s' % outputDir) - # Run the simulation - gen.generate_data(outputDir, + gen.generate_data(tmp_path, dd) # Check that there are 32 files where there should be (30 plus label and # mask) - assert len(os.listdir(outputDir)) == 32, "Incorrect file number" + assert len(os.listdir(tmp_path)) == 32, "Incorrect file number" # Check that the data is the right shape input_template = nib.load(dd['template_path']) @@ -76,7 +73,7 @@ def test_default(tmp_path, dd=data_dict): assert input_shape == output_shape, 'Output shape is incorrect' # Check the labels have the correct count - labels = np.load(outputDir + 'labels.npy') + labels = np.load(tmp_path + 'labels.npy') assert np.sum(labels > 0) == 9, 'Incorrect number of events' @@ -92,11 +89,8 @@ def test_signal_size(tmp_path, dd=data_dict): # Make the signal large dd['scale_percentage'] = 100 - # Clean directory - os.system('rm -rf %s' % outputDir) - # Run the simulation - gen.generate_data(outputDir, + gen.generate_data(tmp_path, dd) # Load in the ROI masks @@ -109,7 +103,7 @@ def test_signal_size(tmp_path, dd=data_dict): for TR_counter in range(dd['numTRs']): # Load the data - vol = np.load(outputDir + 'rt_%03d.npy' % TR_counter) + vol = np.load(tmp_path + 'rt_%03d.npy' % TR_counter) # Mask the data ROI_A_mean += [np.mean(vol[ROI_A == 1])] @@ -124,16 +118,13 @@ def test_save_dicoms_realtime(tmp_path, dd=data_dict): # Make sure you don't edit the data dict dd = copy.deepcopy(dd) - # Clean directory - os.system('rm -rf %s' % outputDir) - dd['save_dicom'] = True dd['save_realtime'] = True start_time = time.time() # Run the simulation - gen.generate_data(outputDir, + gen.generate_data(tmp_path, dd) end_time = time.time() @@ -142,7 +133,7 @@ def test_save_dicoms_realtime(tmp_path, dd=data_dict): assert (end_time - start_time) > 60, 'Realtime ran fast' # Check correct file number - assert len(glob.glob(outputDir + '*.dcm')) == 30, "Wrong dicom file num" + assert len(glob.glob(tmp_path + '*.dcm')) == 30, "Wrong dicom file num" def test_multivariate(tmp_path, dd=data_dict): @@ -156,11 +147,8 @@ def test_multivariate(tmp_path, dd=data_dict): # Make the signal large dd['scale_percentage'] = 100 - # Clean directory - os.system('rm -rf %s' % outputDir) - # Run the simulation - gen.generate_data(outputDir, + gen.generate_data(tmp_path, dd) # Load in the ROI masks @@ -168,7 +156,7 @@ def test_multivariate(tmp_path, dd=data_dict): ROI_B = nib.load(dd['ROI_B_file']).get_data() # Test this volume - vol = np.load(outputDir + 'rt_007.npy') + vol = np.load(tmp_path + 'rt_007.npy') ROI_A_std = np.std(vol[ROI_A == 1]) ROI_B_std = np.std(vol[ROI_B == 1]) From 156798ab5c68b83ba913acc54aef6c7e979f2bba Mon Sep 17 00:00:00 2001 From: CameronTEllis Date: Tue, 7 Apr 2020 18:38:10 -0400 Subject: [PATCH 07/36] fixed the resource stream path --- brainiak/utils/fmrisim.py | 4 +++- tests/utils/test_fmrisim_real_time.py | 10 +++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/brainiak/utils/fmrisim.py b/brainiak/utils/fmrisim.py index af3857feb..bbcdd46de 100644 --- a/brainiak/utils/fmrisim.py +++ b/brainiak/utils/fmrisim.py @@ -2217,7 +2217,9 @@ def mask_brain(volume, if mask_self is True: mask_raw = volume elif template_name is None: - mask_raw = np.load(resource_stream(__name__, "grey_matter_mask.npy")) + mask_raw = np.load(resource_stream( + fmrisim_real_time_generator.__name__, + "sim_parameters/grey_matter_mask.npy")) else: mask_raw = np.load(template_name) diff --git a/tests/utils/test_fmrisim_real_time.py b/tests/utils/test_fmrisim_real_time.py index 6f2948bac..eccca4c8e 100644 --- a/tests/utils/test_fmrisim_real_time.py +++ b/tests/utils/test_fmrisim_real_time.py @@ -32,13 +32,13 @@ data_dict = {} data_dict['ROI_A_file'] = resource_stream( - fmrisim_real_time_generator.__name__, "ROI_A.nii.gz") + fmrisim_real_time_generator.__name__, "sim_parameters/ROI_A.nii.gz") data_dict['ROI_B_file'] = resource_stream( - fmrisim_real_time_generator.__name__, "ROI_B.nii.gz") + fmrisim_real_time_generator.__name__, "sim_parameters/ROI_B.nii.gz") data_dict['template_path'] = resource_stream( - fmrisim_real_time_generator.__name__, "sub_template.nii.gz") + fmrisim_real_time_generator.__name__, "sim_parameters/sub_template.nii.gz") data_dict['noise_dict_file'] = resource_stream( - fmrisim_real_time_generator.__name__, "sub_noise_dict.txt") + fmrisim_real_time_generator.__name__, "sim_parameters/sub_noise_dict.txt") data_dict['numTRs'] = 30 data_dict['event_duration'] = 2 data_dict['scale_percentage'] = 1 @@ -68,7 +68,7 @@ def test_default(tmp_path, dd=data_dict): # Check that the data is the right shape input_template = nib.load(dd['template_path']) input_shape = input_template.shape - output_vol = np.load(outputDir + 'rt_000.npy') + output_vol = np.load(tmp_path + 'rt_000.npy') output_shape = output_vol.shape assert input_shape == output_shape, 'Output shape is incorrect' From dc15451c5eb93f5d6807f4e63209e4c4f759bbdd Mon Sep 17 00:00:00 2001 From: CameronTEllis Date: Tue, 7 Apr 2020 18:48:39 -0400 Subject: [PATCH 08/36] fixed the resource stream path --- brainiak/utils/fmrisim.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/brainiak/utils/fmrisim.py b/brainiak/utils/fmrisim.py index bbcdd46de..32fd9ed49 100644 --- a/brainiak/utils/fmrisim.py +++ b/brainiak/utils/fmrisim.py @@ -2217,9 +2217,9 @@ def mask_brain(volume, if mask_self is True: mask_raw = volume elif template_name is None: - mask_raw = np.load(resource_stream( - fmrisim_real_time_generator.__name__, - "sim_parameters/grey_matter_mask.npy")) + mask_name = resource_stream(__name__, + "sim_parameters/grey_matter_mask.npy") + mask_raw = np.load(mask_name) else: mask_raw = np.load(template_name) From 0edc66b5130d574d6be56a1a506beabdfec98d72 Mon Sep 17 00:00:00 2001 From: CameronTEllis Date: Tue, 7 Apr 2020 18:55:32 -0400 Subject: [PATCH 09/36] pep8 error --- brainiak/utils/fmrisim.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/brainiak/utils/fmrisim.py b/brainiak/utils/fmrisim.py index 32fd9ed49..e4d5cb8e1 100644 --- a/brainiak/utils/fmrisim.py +++ b/brainiak/utils/fmrisim.py @@ -2217,8 +2217,8 @@ def mask_brain(volume, if mask_self is True: mask_raw = volume elif template_name is None: - mask_name = resource_stream(__name__, - "sim_parameters/grey_matter_mask.npy") + mask_name = resource_stream(__name__, + "sim_parameters/grey_matter_mask.npy") mask_raw = np.load(mask_name) else: mask_raw = np.load(template_name) From 330f4de4e660db280d11f802198667f7286c7c14 Mon Sep 17 00:00:00 2001 From: CameronTEllis Date: Tue, 7 Apr 2020 19:10:02 -0400 Subject: [PATCH 10/36] pep8 error --- brainiak/utils/fmrisim.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/brainiak/utils/fmrisim.py b/brainiak/utils/fmrisim.py index e4d5cb8e1..e5a69a752 100644 --- a/brainiak/utils/fmrisim.py +++ b/brainiak/utils/fmrisim.py @@ -2217,9 +2217,8 @@ def mask_brain(volume, if mask_self is True: mask_raw = volume elif template_name is None: - mask_name = resource_stream(__name__, - "sim_parameters/grey_matter_mask.npy") - mask_raw = np.load(mask_name) + fname = resource_stream(__name__, "sim_parameters/grey_matter_mask.npy") + mask_raw = np.load(fname) else: mask_raw = np.load(template_name) From 6e502a1b5d5f60c3632ebdf60f144c886e608627 Mon Sep 17 00:00:00 2001 From: CameronTEllis Date: Tue, 7 Apr 2020 19:18:40 -0400 Subject: [PATCH 11/36] pep8 error --- brainiak/utils/fmrisim.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/brainiak/utils/fmrisim.py b/brainiak/utils/fmrisim.py index e5a69a752..a079abd6b 100644 --- a/brainiak/utils/fmrisim.py +++ b/brainiak/utils/fmrisim.py @@ -2217,8 +2217,8 @@ def mask_brain(volume, if mask_self is True: mask_raw = volume elif template_name is None: - fname = resource_stream(__name__, "sim_parameters/grey_matter_mask.npy") - mask_raw = np.load(fname) + mfn = resource_stream(__name__, "sim_parameters/grey_matter_mask.npy") + mask_raw = np.load(mfn) else: mask_raw = np.load(template_name) From 33e73e3adc3add502afca06301f8f52f0ae18819 Mon Sep 17 00:00:00 2001 From: CameronTEllis Date: Tue, 7 Apr 2020 19:31:57 -0400 Subject: [PATCH 12/36] Wrong function call --- tests/utils/test_fmrisim_real_time.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/tests/utils/test_fmrisim_real_time.py b/tests/utils/test_fmrisim_real_time.py index eccca4c8e..f195f8e14 100644 --- a/tests/utils/test_fmrisim_real_time.py +++ b/tests/utils/test_fmrisim_real_time.py @@ -31,14 +31,16 @@ gen.generate_data() data_dict = {} -data_dict['ROI_A_file'] = resource_stream( - fmrisim_real_time_generator.__name__, "sim_parameters/ROI_A.nii.gz") -data_dict['ROI_B_file'] = resource_stream( - fmrisim_real_time_generator.__name__, "sim_parameters/ROI_B.nii.gz") -data_dict['template_path'] = resource_stream( - fmrisim_real_time_generator.__name__, "sim_parameters/sub_template.nii.gz") -data_dict['noise_dict_file'] = resource_stream( - fmrisim_real_time_generator.__name__, "sim_parameters/sub_noise_dict.txt") +data_dict['ROI_A_file'] = resource_stream(gen.__name__, + "sim_parameters/ROI_A.nii.gz") +data_dict['ROI_B_file'] = resource_stream(gen.__name__, + "sim_parameters/ROI_B.nii.gz") +template_path = resource_stream(gen.__name__, + "sim_parameters/sub_template.nii.gz") +data_dict['template_path'] = template_path +noise_dict_file = resource_stream(gen.__name__, + "sim_parameters/sub_noise_dict.txt") +data_dict['noise_dict_file'] = noise_dict_file data_dict['numTRs'] = 30 data_dict['event_duration'] = 2 data_dict['scale_percentage'] = 1 From 6ba226c2c55c23ce91fe71e19fbc1a29a7c7fce3 Mon Sep 17 00:00:00 2001 From: CameronTEllis Date: Tue, 7 Apr 2020 19:45:51 -0400 Subject: [PATCH 13/36] Wrong function call --- tests/utils/test_fmrisim_real_time.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/utils/test_fmrisim_real_time.py b/tests/utils/test_fmrisim_real_time.py index f195f8e14..2a5e1b675 100644 --- a/tests/utils/test_fmrisim_real_time.py +++ b/tests/utils/test_fmrisim_real_time.py @@ -35,7 +35,7 @@ "sim_parameters/ROI_A.nii.gz") data_dict['ROI_B_file'] = resource_stream(gen.__name__, "sim_parameters/ROI_B.nii.gz") -template_path = resource_stream(gen.__name__, +template_path = resource_stream(gen.__name__, "sim_parameters/sub_template.nii.gz") data_dict['template_path'] = template_path noise_dict_file = resource_stream(gen.__name__, From 1b30e9e26137f94e41dc45862b9e980f80e55506 Mon Sep 17 00:00:00 2001 From: CameronTEllis Date: Wed, 8 Apr 2020 15:19:29 -0400 Subject: [PATCH 14/36] Fix the test for run-checks --- tests/utils/test_fmrisim_real_time.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/utils/test_fmrisim_real_time.py b/tests/utils/test_fmrisim_real_time.py index 2a5e1b675..21923c2ae 100644 --- a/tests/utils/test_fmrisim_real_time.py +++ b/tests/utils/test_fmrisim_real_time.py @@ -25,12 +25,13 @@ import glob import copy from pkg_resources import resource_stream +from typing import Dict # Test that it crashes without inputs with pytest.raises(TypeError): - gen.generate_data() + gen.generate_data() # type: ignore -data_dict = {} +data_dict: Dict = {} data_dict['ROI_A_file'] = resource_stream(gen.__name__, "sim_parameters/ROI_A.nii.gz") data_dict['ROI_B_file'] = resource_stream(gen.__name__, From a8f655b3f1e62abc663b31148c5d423e7ff84d13 Mon Sep 17 00:00:00 2001 From: CameronTEllis Date: Wed, 8 Apr 2020 15:34:23 -0400 Subject: [PATCH 15/36] Add pydicom to the list of software --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index b4265d14c..49ba99957 100644 --- a/setup.py +++ b/setup.py @@ -139,6 +139,7 @@ def finalize_options(self): 'nibabel', 'joblib', 'wheel', # See https://github.com/astropy/astropy-helpers/issues/501 + 'pydicom', ], author='Princeton Neuroscience Institute and Intel Corporation', author_email='mihai.capota@intel.com', From 571913799e5947962396c2c4044e073f7fb34023 Mon Sep 17 00:00:00 2001 From: CameronTEllis Date: Wed, 8 Apr 2020 16:43:26 -0400 Subject: [PATCH 16/36] Remove the deep copy that protects the dictionary across function calls --- tests/utils/test_fmrisim_real_time.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/tests/utils/test_fmrisim_real_time.py b/tests/utils/test_fmrisim_real_time.py index 21923c2ae..cce5eaa87 100644 --- a/tests/utils/test_fmrisim_real_time.py +++ b/tests/utils/test_fmrisim_real_time.py @@ -83,9 +83,6 @@ def test_default(tmp_path, dd=data_dict): def test_signal_size(tmp_path, dd=data_dict): - # Make sure you don't edit the data dict - dd = copy.deepcopy(dd) - # Change it to only use ROI A dd['different_ROIs'] = False @@ -118,9 +115,6 @@ def test_signal_size(tmp_path, dd=data_dict): # Run default test def test_save_dicoms_realtime(tmp_path, dd=data_dict): - # Make sure you don't edit the data dict - dd = copy.deepcopy(dd) - dd['save_dicom'] = True dd['save_realtime'] = True @@ -141,9 +135,6 @@ def test_save_dicoms_realtime(tmp_path, dd=data_dict): def test_multivariate(tmp_path, dd=data_dict): - # Make sure you don't edit the data dict - dd = copy.deepcopy(dd) - dd['multivariate_pattern'] = True dd['different_ROIs'] = False From 7da52c8be036462418a02825cb5cc03268ee2fd7 Mon Sep 17 00:00:00 2001 From: CameronTEllis Date: Wed, 8 Apr 2020 16:55:32 -0400 Subject: [PATCH 17/36] Remove the deep copy that protects the dictionary across function calls --- tests/utils/test_fmrisim_real_time.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/utils/test_fmrisim_real_time.py b/tests/utils/test_fmrisim_real_time.py index cce5eaa87..f843e26da 100644 --- a/tests/utils/test_fmrisim_real_time.py +++ b/tests/utils/test_fmrisim_real_time.py @@ -57,9 +57,6 @@ # Run default test def test_default(tmp_path, dd=data_dict): - # Make sure you don't edit the data dict - dd = copy.deepcopy(dd) - # Run the simulation gen.generate_data(tmp_path, dd) From 3edd15f0a0f0abf108a2eb205e4e48a166842a0d Mon Sep 17 00:00:00 2001 From: CameronTEllis Date: Wed, 8 Apr 2020 17:00:46 -0400 Subject: [PATCH 18/36] Remove the deep copy that protects the dictionary across function calls --- tests/utils/test_fmrisim_real_time.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/utils/test_fmrisim_real_time.py b/tests/utils/test_fmrisim_real_time.py index f843e26da..c7aa7b049 100644 --- a/tests/utils/test_fmrisim_real_time.py +++ b/tests/utils/test_fmrisim_real_time.py @@ -23,7 +23,6 @@ import nibabel as nib import time import glob -import copy from pkg_resources import resource_stream from typing import Dict From e925a4c66db10884c1136bd1d182c51f15d3e8f9 Mon Sep 17 00:00:00 2001 From: CameronTEllis Date: Wed, 15 Apr 2020 19:15:03 -0400 Subject: [PATCH 19/36] Resource stream updates --- brainiak/utils/fmrisim_real_time_generator.py | 28 ++++++++++++++----- tests/utils/test_fmrisim_real_time.py | 26 +++++++++-------- 2 files changed, 35 insertions(+), 19 deletions(-) diff --git a/brainiak/utils/fmrisim_real_time_generator.py b/brainiak/utils/fmrisim_real_time_generator.py index 491ad73cc..e0755ae8e 100644 --- a/brainiak/utils/fmrisim_real_time_generator.py +++ b/brainiak/utils/fmrisim_real_time_generator.py @@ -37,6 +37,8 @@ from brainiak.utils import fmrisim as sim # type: ignore import logging from pkg_resources import resource_stream +from nib.nifti1.Nifti1Image import from_bytes as from_bytes +import gzip __all__ = ["generate_data"] @@ -54,8 +56,12 @@ def _generate_ROIs(ROI_file, logger.info('Loading', ROI_file) - nii = nibabel.load(ROI_file) - ROI = nii.get_data() + # Load in the template data (it may already be loaded if doing a test) + if np.prod(ROI_file.shape) < 1000: + nii = nibabel.load(ROI_file) + ROI = nii.get_data() + else: + ROI = ROI_file # Find all the indices that contain signal idx_list = np.where(ROI == 1) @@ -174,18 +180,22 @@ def _get_input_names(data_dict): # Load in the ROIs if data_dict['ROI_A_file'] is None: - ROI_A_file = resource_stream(__name__, 'ROI_A.nii.gz') + vol = resource_stream(__name__, "sim_parameters/ROI_A.nii.gz").read() + ROI_A_file = from_bytes(gzip.decompress(vol)) else: ROI_A_file = data_dict['ROI_A_file'] if data_dict['ROI_B_file'] is None: - ROI_B_file = resource_stream(__name__, 'ROI_B.nii.gz') + vol = resource_stream(__name__, "sim_parameters/ROI_B.nii.gz").read() + ROI_B_file = from_bytes(gzip.decompress(vol)) else: ROI_B_file = data_dict['ROI_B_file'] # Get the path to the template if data_dict['template_path'] is None: - template_path = resource_stream(__name__, 'sub_template.nii.gz') + vol = resource_stream(__name__, + "sim_parameters/sub_template.nii.gz").read() + template_path = from_bytes(gzip.decompress(vol)) else: template_path = data_dict['template_path'] @@ -231,8 +241,12 @@ def generate_data(outputDir, ROI_A_file, ROI_B_file, template_path, noise_dict_file = _get_input_names( data_dict) - template_nii = nibabel.load(template_path) - template = template_nii.get_data() + # Load in the template data (it may already be loaded if doing a test) + if np.prod(template_path.shape) < 1000: + template_nii = nibabel.load(template_path) + template = template_nii.get_data() + else: + template = template_path dimensions = np.array(template.shape[0:3]) diff --git a/tests/utils/test_fmrisim_real_time.py b/tests/utils/test_fmrisim_real_time.py index c7aa7b049..4f6d0a886 100644 --- a/tests/utils/test_fmrisim_real_time.py +++ b/tests/utils/test_fmrisim_real_time.py @@ -25,19 +25,21 @@ import glob from pkg_resources import resource_stream from typing import Dict +from nib.nifti1.Nifti1Image import from_bytes as from_bytes +import gzip # Test that it crashes without inputs with pytest.raises(TypeError): gen.generate_data() # type: ignore data_dict: Dict = {} -data_dict['ROI_A_file'] = resource_stream(gen.__name__, - "sim_parameters/ROI_A.nii.gz") -data_dict['ROI_B_file'] = resource_stream(gen.__name__, - "sim_parameters/ROI_B.nii.gz") -template_path = resource_stream(gen.__name__, - "sim_parameters/sub_template.nii.gz") -data_dict['template_path'] = template_path +vol = resource_stream(gen.__name__, "sim_parameters/ROI_A.nii.gz").read() +data_dict['ROI_A_file'] = from_bytes(gzip.decompress(vol)) +vol = resource_stream(gen.__name__, "sim_parameters/ROI_B.nii.gz").read() +data_dict['ROI_B_file'] = from_bytes(gzip.decompress(vol)) +vol = resource_stream(gen.__name__, + "sim_parameters/sub_template.nii.gz").read() +data_dict['template_path'] = from_bytes(gzip.decompress(vol)) noise_dict_file = resource_stream(gen.__name__, "sim_parameters/sub_noise_dict.txt") data_dict['noise_dict_file'] = noise_dict_file @@ -65,7 +67,7 @@ def test_default(tmp_path, dd=data_dict): assert len(os.listdir(tmp_path)) == 32, "Incorrect file number" # Check that the data is the right shape - input_template = nib.load(dd['template_path']) + input_template = dd['template_path'] input_shape = input_template.shape output_vol = np.load(tmp_path + 'rt_000.npy') output_shape = output_vol.shape @@ -90,8 +92,8 @@ def test_signal_size(tmp_path, dd=data_dict): dd) # Load in the ROI masks - ROI_A = nib.load(dd['ROI_A_file']).get_data() - ROI_B = nib.load(dd['ROI_B_file']).get_data() + ROI_A = dd['ROI_A_file'] + ROI_B = dd['ROI_B_file'] # Load in the data just simulated ROI_A_mean = [] @@ -142,8 +144,8 @@ def test_multivariate(tmp_path, dd=data_dict): dd) # Load in the ROI masks - ROI_A = nib.load(dd['ROI_A_file']).get_data() - ROI_B = nib.load(dd['ROI_B_file']).get_data() + ROI_A = dd['ROI_A_file'] + ROI_B = dd['ROI_B_file'] # Test this volume vol = np.load(tmp_path + 'rt_007.npy') From bb3e67d2157ce594e4aece0c2fe46834d6fa68d3 Mon Sep 17 00:00:00 2001 From: CameronTEllis Date: Wed, 15 Apr 2020 19:29:23 -0400 Subject: [PATCH 20/36] Resource stream updates --- tests/utils/test_fmrisim_real_time.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/utils/test_fmrisim_real_time.py b/tests/utils/test_fmrisim_real_time.py index 4f6d0a886..44f35f5ce 100644 --- a/tests/utils/test_fmrisim_real_time.py +++ b/tests/utils/test_fmrisim_real_time.py @@ -20,7 +20,6 @@ from brainiak.utils import fmrisim_real_time_generator as gen import pytest import os -import nibabel as nib import time import glob from pkg_resources import resource_stream From e93e9f6c83d95da4a56d821f5c861a1e09fadeee Mon Sep 17 00:00:00 2001 From: CameronTEllis Date: Wed, 15 Apr 2020 19:35:00 -0400 Subject: [PATCH 21/36] Resource stream updates --- brainiak/utils/fmrisim_real_time_generator.py | 2 +- tests/utils/test_fmrisim_real_time.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/brainiak/utils/fmrisim_real_time_generator.py b/brainiak/utils/fmrisim_real_time_generator.py index e0755ae8e..1d11c6ebc 100644 --- a/brainiak/utils/fmrisim_real_time_generator.py +++ b/brainiak/utils/fmrisim_real_time_generator.py @@ -37,7 +37,7 @@ from brainiak.utils import fmrisim as sim # type: ignore import logging from pkg_resources import resource_stream -from nib.nifti1.Nifti1Image import from_bytes as from_bytes +from nibabel.nifti1.Nifti1Image import from_bytes as from_bytes import gzip __all__ = ["generate_data"] diff --git a/tests/utils/test_fmrisim_real_time.py b/tests/utils/test_fmrisim_real_time.py index 44f35f5ce..080ec9f45 100644 --- a/tests/utils/test_fmrisim_real_time.py +++ b/tests/utils/test_fmrisim_real_time.py @@ -24,7 +24,7 @@ import glob from pkg_resources import resource_stream from typing import Dict -from nib.nifti1.Nifti1Image import from_bytes as from_bytes +from nibabel.nifti1.Nifti1Image import from_bytes as from_bytes import gzip # Test that it crashes without inputs From b1d67a9012d14fc2b18407016d1c30613838aa37 Mon Sep 17 00:00:00 2001 From: CameronTEllis Date: Wed, 15 Apr 2020 20:01:10 -0400 Subject: [PATCH 22/36] Resource stream updates --- brainiak/utils/fmrisim_real_time_generator.py | 8 ++++---- tests/utils/test_fmrisim_real_time.py | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/brainiak/utils/fmrisim_real_time_generator.py b/brainiak/utils/fmrisim_real_time_generator.py index 1d11c6ebc..53473bcd7 100644 --- a/brainiak/utils/fmrisim_real_time_generator.py +++ b/brainiak/utils/fmrisim_real_time_generator.py @@ -37,7 +37,7 @@ from brainiak.utils import fmrisim as sim # type: ignore import logging from pkg_resources import resource_stream -from nibabel.nifti1.Nifti1Image import from_bytes as from_bytes +from nibabel.nifti1 import Nifti1Image import gzip __all__ = ["generate_data"] @@ -181,13 +181,13 @@ def _get_input_names(data_dict): # Load in the ROIs if data_dict['ROI_A_file'] is None: vol = resource_stream(__name__, "sim_parameters/ROI_A.nii.gz").read() - ROI_A_file = from_bytes(gzip.decompress(vol)) + ROI_A_file = Nifti1Image.from_bytes(gzip.decompress(vol)) else: ROI_A_file = data_dict['ROI_A_file'] if data_dict['ROI_B_file'] is None: vol = resource_stream(__name__, "sim_parameters/ROI_B.nii.gz").read() - ROI_B_file = from_bytes(gzip.decompress(vol)) + ROI_B_file = Nifti1Image.from_bytes(gzip.decompress(vol)) else: ROI_B_file = data_dict['ROI_B_file'] @@ -195,7 +195,7 @@ def _get_input_names(data_dict): if data_dict['template_path'] is None: vol = resource_stream(__name__, "sim_parameters/sub_template.nii.gz").read() - template_path = from_bytes(gzip.decompress(vol)) + template_path = Nifti1Image.from_bytes(gzip.decompress(vol)) else: template_path = data_dict['template_path'] diff --git a/tests/utils/test_fmrisim_real_time.py b/tests/utils/test_fmrisim_real_time.py index 080ec9f45..ca154dae8 100644 --- a/tests/utils/test_fmrisim_real_time.py +++ b/tests/utils/test_fmrisim_real_time.py @@ -24,7 +24,7 @@ import glob from pkg_resources import resource_stream from typing import Dict -from nibabel.nifti1.Nifti1Image import from_bytes as from_bytes +from nibabel.nifti1 import Nifti1Image import gzip # Test that it crashes without inputs @@ -33,12 +33,12 @@ data_dict: Dict = {} vol = resource_stream(gen.__name__, "sim_parameters/ROI_A.nii.gz").read() -data_dict['ROI_A_file'] = from_bytes(gzip.decompress(vol)) +data_dict['ROI_A_file'] = Nifti1Image.from_bytes(gzip.decompress(vol)) vol = resource_stream(gen.__name__, "sim_parameters/ROI_B.nii.gz").read() -data_dict['ROI_B_file'] = from_bytes(gzip.decompress(vol)) +data_dict['ROI_B_file'] = Nifti1Image.from_bytes(gzip.decompress(vol)) vol = resource_stream(gen.__name__, "sim_parameters/sub_template.nii.gz").read() -data_dict['template_path'] = from_bytes(gzip.decompress(vol)) +data_dict['template_path'] = Nifti1Image.from_bytes(gzip.decompress(vol)) noise_dict_file = resource_stream(gen.__name__, "sim_parameters/sub_noise_dict.txt") data_dict['noise_dict_file'] = noise_dict_file From 87d358cf363857744f425c78355929b58d6015b7 Mon Sep 17 00:00:00 2001 From: CameronTEllis Date: Wed, 15 Apr 2020 20:17:18 -0400 Subject: [PATCH 23/36] Resource stream updates --- brainiak/utils/fmrisim_real_time_generator.py | 6 +++--- tests/utils/test_fmrisim_real_time.py | 9 ++++++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/brainiak/utils/fmrisim_real_time_generator.py b/brainiak/utils/fmrisim_real_time_generator.py index 53473bcd7..1df68648a 100644 --- a/brainiak/utils/fmrisim_real_time_generator.py +++ b/brainiak/utils/fmrisim_real_time_generator.py @@ -181,13 +181,13 @@ def _get_input_names(data_dict): # Load in the ROIs if data_dict['ROI_A_file'] is None: vol = resource_stream(__name__, "sim_parameters/ROI_A.nii.gz").read() - ROI_A_file = Nifti1Image.from_bytes(gzip.decompress(vol)) + ROI_A_file = Nifti1Image.from_bytes(gzip.decompress(vol)).get_data() else: ROI_A_file = data_dict['ROI_A_file'] if data_dict['ROI_B_file'] is None: vol = resource_stream(__name__, "sim_parameters/ROI_B.nii.gz").read() - ROI_B_file = Nifti1Image.from_bytes(gzip.decompress(vol)) + ROI_B_file = Nifti1Image.from_bytes(gzip.decompress(vol)).get_data() else: ROI_B_file = data_dict['ROI_B_file'] @@ -195,7 +195,7 @@ def _get_input_names(data_dict): if data_dict['template_path'] is None: vol = resource_stream(__name__, "sim_parameters/sub_template.nii.gz").read() - template_path = Nifti1Image.from_bytes(gzip.decompress(vol)) + template_path = Nifti1Image.from_bytes(gzip.decompress(vol)).get_data() else: template_path = data_dict['template_path'] diff --git a/tests/utils/test_fmrisim_real_time.py b/tests/utils/test_fmrisim_real_time.py index ca154dae8..4236fed19 100644 --- a/tests/utils/test_fmrisim_real_time.py +++ b/tests/utils/test_fmrisim_real_time.py @@ -33,12 +33,15 @@ data_dict: Dict = {} vol = resource_stream(gen.__name__, "sim_parameters/ROI_A.nii.gz").read() -data_dict['ROI_A_file'] = Nifti1Image.from_bytes(gzip.decompress(vol)) +data_dict['ROI_A_file'] = Nifti1Image.from_bytes(gzip.decompress( + vol)).get_data() vol = resource_stream(gen.__name__, "sim_parameters/ROI_B.nii.gz").read() -data_dict['ROI_B_file'] = Nifti1Image.from_bytes(gzip.decompress(vol)) +data_dict['ROI_B_file'] = Nifti1Image.from_bytes(gzip.decompress( + vol)).get_data() vol = resource_stream(gen.__name__, "sim_parameters/sub_template.nii.gz").read() -data_dict['template_path'] = Nifti1Image.from_bytes(gzip.decompress(vol)) +data_dict['template_path'] = Nifti1Image.from_bytes(gzip.decompress( + vol)).get_data() noise_dict_file = resource_stream(gen.__name__, "sim_parameters/sub_noise_dict.txt") data_dict['noise_dict_file'] = noise_dict_file From 6176a55d649fceea7628e8f01056d498996944e1 Mon Sep 17 00:00:00 2001 From: CameronTEllis Date: Sun, 19 Apr 2020 22:26:14 -0400 Subject: [PATCH 24/36] Add resource support for text files --- brainiak/utils/fmrisim_real_time_generator.py | 14 +++++++++++--- tests/utils/test_fmrisim_real_time.py | 2 +- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/brainiak/utils/fmrisim_real_time_generator.py b/brainiak/utils/fmrisim_real_time_generator.py index 1df68648a..e6e381975 100644 --- a/brainiak/utils/fmrisim_real_time_generator.py +++ b/brainiak/utils/fmrisim_real_time_generator.py @@ -201,7 +201,9 @@ def _get_input_names(data_dict): # Load in the noise dict if supplied if data_dict['noise_dict_file'] is None: - noise_dict_file = resource_stream(__name__, 'sub_noise_dict.txt') + file = resource_stream(__name__, + 'sim_parameters/sub_noise_dict.txt').read() + noise_dict_file = file else: noise_dict_file = data_dict['noise_dict_file'] @@ -262,8 +264,14 @@ def generate_data(outputDir, # Load the noise dictionary logger.info('Loading noise parameters') - with open(noise_dict_file, 'r') as f: - noise_dict = f.read() + # If this isn't a string, assume it is a resource stream file + if type(noise_dict_file) is str: + with open(noise_dict_file, 'r') as f: + noise_dict = f.read() + else: + # Read the resource stream object + noise_dict = noise_dict_file.decode() + noise_dict = eval(noise_dict) noise_dict['matched'] = 0 # Increases processing time diff --git a/tests/utils/test_fmrisim_real_time.py b/tests/utils/test_fmrisim_real_time.py index 4236fed19..7d7839002 100644 --- a/tests/utils/test_fmrisim_real_time.py +++ b/tests/utils/test_fmrisim_real_time.py @@ -43,7 +43,7 @@ data_dict['template_path'] = Nifti1Image.from_bytes(gzip.decompress( vol)).get_data() noise_dict_file = resource_stream(gen.__name__, - "sim_parameters/sub_noise_dict.txt") + "sim_parameters/sub_noise_dict.txt").read() data_dict['noise_dict_file'] = noise_dict_file data_dict['numTRs'] = 30 data_dict['event_duration'] = 2 From 8c3498d3cec35a907d4ce427b5ac73f1b7ae7cd2 Mon Sep 17 00:00:00 2001 From: CameronTEllis Date: Thu, 30 Apr 2020 14:42:45 -0400 Subject: [PATCH 25/36] Update for file name appending --- tests/utils/test_fmrisim_real_time.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/utils/test_fmrisim_real_time.py b/tests/utils/test_fmrisim_real_time.py index 7d7839002..9158ffa93 100644 --- a/tests/utils/test_fmrisim_real_time.py +++ b/tests/utils/test_fmrisim_real_time.py @@ -71,12 +71,12 @@ def test_default(tmp_path, dd=data_dict): # Check that the data is the right shape input_template = dd['template_path'] input_shape = input_template.shape - output_vol = np.load(tmp_path + 'rt_000.npy') + output_vol = np.load(tmp_path / 'rt_000.npy') output_shape = output_vol.shape assert input_shape == output_shape, 'Output shape is incorrect' # Check the labels have the correct count - labels = np.load(tmp_path + 'labels.npy') + labels = np.load(tmp_path / 'labels.npy') assert np.sum(labels > 0) == 9, 'Incorrect number of events' @@ -103,7 +103,7 @@ def test_signal_size(tmp_path, dd=data_dict): for TR_counter in range(dd['numTRs']): # Load the data - vol = np.load(tmp_path + 'rt_%03d.npy' % TR_counter) + vol = np.load(tmp_path / 'rt_%03d.npy' % TR_counter) # Mask the data ROI_A_mean += [np.mean(vol[ROI_A == 1])] @@ -130,7 +130,7 @@ def test_save_dicoms_realtime(tmp_path, dd=data_dict): assert (end_time - start_time) > 60, 'Realtime ran fast' # Check correct file number - assert len(glob.glob(tmp_path + '*.dcm')) == 30, "Wrong dicom file num" + assert len(glob.glob(tmp_path / '*.dcm')) == 30, "Wrong dicom file num" def test_multivariate(tmp_path, dd=data_dict): @@ -150,7 +150,7 @@ def test_multivariate(tmp_path, dd=data_dict): ROI_B = dd['ROI_B_file'] # Test this volume - vol = np.load(tmp_path + 'rt_007.npy') + vol = np.load(tmp_path / 'rt_007.npy') ROI_A_std = np.std(vol[ROI_A == 1]) ROI_B_std = np.std(vol[ROI_B == 1]) From 6629e5759b3309b621449136b159f816b8bdf6d4 Mon Sep 17 00:00:00 2001 From: CameronTEllis Date: Thu, 30 Apr 2020 15:13:35 -0400 Subject: [PATCH 26/36] Make posix path a string --- tests/utils/test_fmrisim_real_time.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/utils/test_fmrisim_real_time.py b/tests/utils/test_fmrisim_real_time.py index 9158ffa93..1d15be177 100644 --- a/tests/utils/test_fmrisim_real_time.py +++ b/tests/utils/test_fmrisim_real_time.py @@ -103,7 +103,8 @@ def test_signal_size(tmp_path, dd=data_dict): for TR_counter in range(dd['numTRs']): # Load the data - vol = np.load(tmp_path / 'rt_%03d.npy' % TR_counter) + vol_name = 'rt_%03d.npy' % TR_counter + vol = np.load(tmp_path / vol_name) # Mask the data ROI_A_mean += [np.mean(vol[ROI_A == 1])] @@ -130,7 +131,8 @@ def test_save_dicoms_realtime(tmp_path, dd=data_dict): assert (end_time - start_time) > 60, 'Realtime ran fast' # Check correct file number - assert len(glob.glob(tmp_path / '*.dcm')) == 30, "Wrong dicom file num" + file_path = str(tmp_path / '*.dcm') + assert len(glob.glob(file_path)) == 30, "Wrong dicom file num" def test_multivariate(tmp_path, dd=data_dict): @@ -150,7 +152,7 @@ def test_multivariate(tmp_path, dd=data_dict): ROI_B = dd['ROI_B_file'] # Test this volume - vol = np.load(tmp_path / 'rt_007.npy') + vol = np.load(str(tmp_path / 'rt_007.npy')) ROI_A_std = np.std(vol[ROI_A == 1]) ROI_B_std = np.std(vol[ROI_B == 1]) From a8bf77c6e4935ca46f0a5dccdb82875faed50e0c Mon Sep 17 00:00:00 2001 From: CameronTEllis Date: Thu, 30 Apr 2020 16:46:50 -0400 Subject: [PATCH 27/36] Reorder function calls --- tests/utils/test_fmrisim_real_time.py | 44 +++++++++++++-------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/tests/utils/test_fmrisim_real_time.py b/tests/utils/test_fmrisim_real_time.py index 1d15be177..b77d76b33 100644 --- a/tests/utils/test_fmrisim_real_time.py +++ b/tests/utils/test_fmrisim_real_time.py @@ -113,28 +113,6 @@ def test_signal_size(tmp_path, dd=data_dict): assert np.std(ROI_A_mean) > np.std(ROI_B_mean), 'Signal not scaling' -# Run default test -def test_save_dicoms_realtime(tmp_path, dd=data_dict): - - dd['save_dicom'] = True - dd['save_realtime'] = True - - start_time = time.time() - - # Run the simulation - gen.generate_data(tmp_path, - dd) - - end_time = time.time() - - # Check it took 2s per TR - assert (end_time - start_time) > 60, 'Realtime ran fast' - - # Check correct file number - file_path = str(tmp_path / '*.dcm') - assert len(glob.glob(file_path)) == 30, "Wrong dicom file num" - - def test_multivariate(tmp_path, dd=data_dict): dd['multivariate_pattern'] = True @@ -158,3 +136,25 @@ def test_multivariate(tmp_path, dd=data_dict): ROI_B_std = np.std(vol[ROI_B == 1]) assert ROI_A_std > ROI_B_std, 'Multivariate not making variable signal' + + +def test_save_dicoms_realtime(tmp_path, dd=data_dict): + + dd['save_dicom'] = True + dd['save_realtime'] = True + + start_time = time.time() + + # Run the simulation + gen.generate_data(tmp_path, + dd) + + end_time = time.time() + + # Check it took 2s per TR + assert (end_time - start_time) > 60, 'Realtime ran fast' + + # Check correct file number + file_path = str(tmp_path / '*.dcm') + assert len(glob.glob(file_path)) == 30, "Wrong dicom file num" + From 1caefe9a5d3a601eee5f2e5b85be3bc4bd1cab86 Mon Sep 17 00:00:00 2001 From: CameronTEllis Date: Thu, 30 Apr 2020 16:56:25 -0400 Subject: [PATCH 28/36] Reorder function calls --- tests/utils/test_fmrisim_real_time.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/utils/test_fmrisim_real_time.py b/tests/utils/test_fmrisim_real_time.py index b77d76b33..8dcbf46b4 100644 --- a/tests/utils/test_fmrisim_real_time.py +++ b/tests/utils/test_fmrisim_real_time.py @@ -156,5 +156,4 @@ def test_save_dicoms_realtime(tmp_path, dd=data_dict): # Check correct file number file_path = str(tmp_path / '*.dcm') - assert len(glob.glob(file_path)) == 30, "Wrong dicom file num" - + assert len(glob.glob(file_path)) == 30, "Wrong dicom file num" \ No newline at end of file From 8ff7cb22407cd0c4da87ceb6ae628a9120203126 Mon Sep 17 00:00:00 2001 From: CameronTEllis Date: Thu, 30 Apr 2020 18:59:37 -0400 Subject: [PATCH 29/36] PEP8 error --- tests/utils/test_fmrisim_real_time.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/utils/test_fmrisim_real_time.py b/tests/utils/test_fmrisim_real_time.py index 8dcbf46b4..3dcbb4031 100644 --- a/tests/utils/test_fmrisim_real_time.py +++ b/tests/utils/test_fmrisim_real_time.py @@ -156,4 +156,4 @@ def test_save_dicoms_realtime(tmp_path, dd=data_dict): # Check correct file number file_path = str(tmp_path / '*.dcm') - assert len(glob.glob(file_path)) == 30, "Wrong dicom file num" \ No newline at end of file + assert len(glob.glob(file_path)) == 30, "Wrong dicom file num" From 107e9e7e89641ab6492b0b8bb7649af5e6178473 Mon Sep 17 00:00:00 2001 From: CameronTEllis Date: Fri, 1 May 2020 21:37:22 -0400 Subject: [PATCH 30/36] Make docstring consistent with the Sphinx styles --- brainiak/utils/fmrisim_real_time_generator.py | 196 ++++++++++++++---- 1 file changed, 158 insertions(+), 38 deletions(-) diff --git a/brainiak/utils/fmrisim_real_time_generator.py b/brainiak/utils/fmrisim_real_time_generator.py index e6e381975..1a7a308c9 100644 --- a/brainiak/utils/fmrisim_real_time_generator.py +++ b/brainiak/utils/fmrisim_real_time_generator.py @@ -11,21 +11,21 @@ Optional (can be modified by flags from the command line): data_dict contains: - numTRs - Specify the number of time points - multivariate_patterns - Is the difference between conditions univariate - (0) or multivariate (1) - different_ROIs - Are there different ROIs for each condition (1) or is +numTRs - Specify the number of time points +multivariate_patterns - Is the difference between conditions univariate (0) +or multivariate (1) +different_ROIs - Are there different ROIs for each condition (1) or is it in the same ROI (0). If it is the same ROI and you are using univariate differences, the second condition will have a smaller evoked response than - the other. - event_duration - How long, in seconds, is each event - scale_percentage - What is the percent signal change - trDuration - How many seconds per volume - save_dicom - Do you want to save data as a dicom (1) or numpy (0) - save_realtime - Do you want to save the data in real time (1) or as -fast as possible (0)? - isi - What is the time between each event (in seconds) - burn_in - How long before the first event (in seconds) +the other. +event_duration - How long, in seconds, is each event +scale_percentage - What is the percent signal change +trDuration - How many seconds per volume +save_dicom - Do you want to save data as a dicom (1) or numpy (0) +save_realtime - Do you want to save the data in real time (1) or as fast as +possible (0)? +isi - What is the time between each event (in seconds) +burn_in - How long before the first event (in seconds) """ import os import time @@ -52,6 +52,55 @@ def _generate_ROIs(ROI_file, noise, scale_percentage, data_dict): + """Make signal activity for an ROI of data + Creates the specified evoked response time course, calibrated to the + expected signal change, for a given ROI + + Parameters + ---------- + + ROI_file : str + Path to the file of the ROI being loaded in + + stimfunc : 1 dimensional array + Time course of evoked response. Output from + fmrisim.generate_stimfunction + + noise : 4 dimensional array + Volume of noise generated from fmrisim.generate_noise. Although this + is needed as an input, this is only so that the percent signal change + can be calibrated. This is not combined with the signal generated. + + scale_percentage : float + What is the percent signal change for the evoked response + + data_dict : dict + A dictionary to specify the parameters used for making data, + specifying the following keys + numTRs - int - Specify the number of time points + multivariate_patterns - bool - Is the difference between conditions + univariate (0) or multivariate (1) + different_ROIs - bool - Are there different ROIs for each condition ( + 1) or is it in the same ROI (0). If it is the same ROI and you are + using univariate differences, the second condition will have a + smaller evoked response than the other. + event_duration - int - How long, in seconds, is each event + scale_percentage - float - What is the percent signal change + trDuration - float - How many seconds per volume + save_dicom - bool - Save to data as a dicom (1) or numpy (0) + save_realtime - bool - Do you want to save the data in real time (1) + or as fast as possible (0)? + isi - float - What is the time between each event (in seconds) + burn_in - int - How long before the first event (in seconds) + + Returns + ---------- + + signal : 4 dimensional array + Volume of signal in the specified ROI (noise has not yet been added) + + """ + # Create the signal in the ROI as specified. logger.info('Loading', ROI_file) @@ -120,11 +169,29 @@ def _generate_ROIs(ROI_file, def _write_dicom(output_name, data, image_number=0): - # Write the data to a dicom file. - # Dicom files are difficult to set up correctly, this file will likely - # crash when trying to open it using dcm2nii. However, if it is loaded in - # python (e.g., dicom.dcmread) then pixel_array contains the relevant - # voxel data + """Write the data to a dicom file + Saves the data for one TR to a dicom. + + Dicom files are difficult to set up correctly, this file will likely + crash when trying to open it using dcm2nii. However, if it is loaded in + python (e.g., dicom.dcmread) then pixel_array contains the relevant + voxel data + + Parameters + ---------- + + output_name : str + Output name for volume being created + + data : 3 dimensional array + Volume of data to be saved + + image_number : int + Number dicom to be saved. This is critical for setting up dicom file + header information. + + """ + # Convert data from float to in dataInts = data.astype(np.int16) @@ -177,6 +244,47 @@ def _write_dicom(output_name, def _get_input_names(data_dict): + """Get names from dict + Read in the data_dict to return the relevant file names + + Parameters + ---------- + + data_dict : dict + A dictionary to specify the parameters used for making data, + specifying the following keys + numTRs - int - Specify the number of time points + multivariate_patterns - bool - Is the difference between conditions + univariate (0) or multivariate (1) + different_ROIs - bool - Are there different ROIs for each condition ( + 1) or is it in the same ROI (0). If it is the same ROI and you are + using univariate differences, the second condition will have a + smaller evoked response than the other. + event_duration - int - How long, in seconds, is each event + scale_percentage - float - What is the percent signal change + trDuration - float - How many seconds per volume + save_dicom - bool - Save to data as a dicom (1) or numpy (0) + save_realtime - bool - Do you want to save the data in real time (1) + or as fast as possible (0)? + isi - float - What is the time between each event (in seconds) + burn_in - int - How long before the first event (in seconds) + + Returns + ---------- + + ROI_A_file : str + Path to ROI for condition A + + ROI_B_file : str + Path to ROI for condition B + + template_path : str + Path to template file for data + + noise_dict_file : str + Path to file containing parameters for noise simulation + + """ # Load in the ROIs if data_dict['ROI_A_file'] is None: @@ -213,26 +321,38 @@ def _get_input_names(data_dict): def generate_data(outputDir, data_dict): - # Generate simulated fMRI data with a few parameters that might be - # relevant for real time analysis - # inputDir - Specify input data dir where the parameters for fmrisim are - # outputDir - Specify output data dir where the data should be saved - # data_dict contains: - # numTRs - Specify the number of time points - # multivariate_patterns - Is the difference between conditions - # univariate (0) or multivariate (1) - # different_ROIs - Are there different ROIs for each condition (1) or - # is it in the same ROI (0). If it is the same ROI and you are using - # univariate differences, the second condition will have a smaller evoked - # response than the other. - # event_duration - How long, in seconds, is each event - # scale_percentage - What is the percent signal change - # trDuration - How many seconds per volume - # save_dicom - Do you want to save data as a dicom (1) or numpy (0) - # save_realtime - Do you want to save the data in real time (1) or as - # fast as possible (0)? - # isi - What is the time between each event (in seconds) - # burn_in - How long before the first event (in seconds) + """Generate simulated fMRI data + Use a few parameters that might be relevant for real time analysis + + Parameters + ---------- + + inputDir : str + Specify input data dir where the parameters for fmrisim are + + outputDir : str + Specify output data dir where the data should be saved + + data_dict : dict + A dictionary to specify the parameters used for making data, + specifying the following keys + numTRs - int - Specify the number of time points + multivariate_patterns - bool - Is the difference between conditions + univariate (0) or multivariate (1) + different_ROIs - bool - Are there different ROIs for each condition ( + 1) or is it in the same ROI (0). If it is the same ROI and you are + using univariate differences, the second condition will have a + smaller evoked response than the other. + event_duration - int - How long, in seconds, is each event + scale_percentage - float - What is the percent signal change + trDuration - float - How many seconds per volume + save_dicom - bool - Save to data as a dicom (1) or numpy (0) + save_realtime - bool - Do you want to save the data in real time (1) + or as fast as possible (0)? + isi - float - What is the time between each event (in seconds) + burn_in - int - How long before the first event (in seconds) + + """ # If the folder doesn't exist then make it os.system('mkdir -p %s' % outputDir) From a7673c1c2475561d56db611c0d620f485d6e2f51 Mon Sep 17 00:00:00 2001 From: CameronTEllis Date: Sat, 2 May 2020 14:01:10 -0400 Subject: [PATCH 31/36] Make docstring consistent with the Sphinx styles --- brainiak/utils/fmrisim_real_time_generator.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/brainiak/utils/fmrisim_real_time_generator.py b/brainiak/utils/fmrisim_real_time_generator.py index 1a7a308c9..b2fa23f6a 100644 --- a/brainiak/utils/fmrisim_real_time_generator.py +++ b/brainiak/utils/fmrisim_real_time_generator.py @@ -192,7 +192,6 @@ def _write_dicom(output_name, """ - # Convert data from float to in dataInts = data.astype(np.int16) @@ -352,7 +351,7 @@ def generate_data(outputDir, isi - float - What is the time between each event (in seconds) burn_in - int - How long before the first event (in seconds) - """ + """ # If the folder doesn't exist then make it os.system('mkdir -p %s' % outputDir) From 14a63e03eb7820c7ec3fca2951715f1ceef3336a Mon Sep 17 00:00:00 2001 From: CameronTEllis Date: Mon, 4 May 2020 14:26:59 -0400 Subject: [PATCH 32/36] Update for python 3.5, improved arg parser and fixed a big with default inputs --- brainiak/utils/fmrisim_real_time_generator.py | 45 ++++++++++--------- tests/utils/test_fmrisim_real_time.py | 2 +- 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/brainiak/utils/fmrisim_real_time_generator.py b/brainiak/utils/fmrisim_real_time_generator.py index b2fa23f6a..7e7daee3b 100644 --- a/brainiak/utils/fmrisim_real_time_generator.py +++ b/brainiak/utils/fmrisim_real_time_generator.py @@ -106,7 +106,7 @@ def _generate_ROIs(ROI_file, logger.info('Loading', ROI_file) # Load in the template data (it may already be loaded if doing a test) - if np.prod(ROI_file.shape) < 1000: + if isinstance(ROI_file, str): nii = nibabel.load(ROI_file) ROI = nii.get_data() else: @@ -363,7 +363,7 @@ def generate_data(outputDir, data_dict) # Load in the template data (it may already be loaded if doing a test) - if np.prod(template_path.shape) < 1000: + if isinstance(template_path, str): template_nii = nibabel.load(template_path) template = template_nii.get_data() else: @@ -512,41 +512,42 @@ def generate_data(outputDir, 'Specify input arguments. Some arguments are parameters that require ' 'an input is provided (noted by "Param"), others are flags that when ' 'provided will change according to the flag (noted by "Flag")') - argParser.add_argument('--outputDir', '-o', default=None, type=str, + argParser.add_argument('--output-dir', '-o', default=None, type=str, help='Param. Output directory for simulated data') - argParser.add_argument('--ROI_A_file', default=None, type=str, + argParser.add_argument('--ROI-A-file', default=None, type=str, help='Param. Full path to file for cond. A ROI') - argParser.add_argument('--ROI_B_file', default=None, type=str, + argParser.add_argument('--ROI-B-file', default=None, type=str, help='Param. Full path to file for cond. B ROI') - argParser.add_argument('--template_path', default=None, type=str, + argParser.add_argument('--template-path', default=None, type=str, help='Param. Full path to file for brain template') - argParser.add_argument('--noise_dict_file', default=None, type=str, + argParser.add_argument('--noise-dict-file', default=None, type=str, help='Param. Full path to file setting noise ' 'params') argParser.add_argument('--numTRs', '-n', default=200, type=int, help='Param. Number of time points') - argParser.add_argument('--eventDuration', '-d', default=10, type=int, + argParser.add_argument('--event-duration', '-d', default=10, type=int, help='Param. Number of seconds per event') - argParser.add_argument('--signalScale', '-s', default=0.5, type=float, + argParser.add_argument('--scale_percentage', '-s', default=0.5, type=float, help='Param. Percent signal change') - argParser.add_argument('--useMultivariate', '-m', default=False, + argParser.add_argument('--multivariate-pattern', '-m', default=False, action='store_true', help='Flag. Signal is different between conditions ' 'in a multivariate, versus univariate, way') - argParser.add_argument('--useDifferentROIs', '-r', default=False, + argParser.add_argument('--different-ROIs', '-r', default=False, action='store_true', help='Flag. Use different ' 'ROIs for each condition') - argParser.add_argument('--saveAsDicom', default=False, action='store_true', - help='Flag. Output files in DICOM format rather ' - 'than numpy') - argParser.add_argument('--saveRealtime', default=False, + argParser.add_argument('--save-dicom', default=False, + action='store_true', help='Flag. Output files in ' + 'DICOM format rather ' + 'than numpy') + argParser.add_argument('--save-realtime', default=False, action='store_true', help='Flag. Save data as if ' 'it was coming in at ' 'the acquisition rate') args = argParser.parse_args() # Essential arguments - outputDir = args.outputDir + outputDir = args.output_dir if outputDir is None: logger.info("Must specify an output directory using -o") @@ -568,25 +569,25 @@ def generate_data(outputDir, data_dict['numTRs'] = args.numTRs # How long is each event/block you are modelling (assumes 6s rest between) - data_dict['event_duration'] = float(args.eventDuration) + data_dict['event_duration'] = float(args.event_duration) # What is the percent signal change being simulated - data_dict['scale_percentage'] = args.signalScale + data_dict['scale_percentage'] = args.scale_percentage # Are there different ROIs for each condition (True) or is it in the same # ROI (False). # If it is the same ROI and you are using univariate differences, # the second condition will have a smaller evoked response than the other. - data_dict['different_ROIs'] = args.useDifferentROIs + data_dict['different_ROIs'] = args.different_ROIs # Is this a multivariate pattern (1) or a univariate pattern - data_dict['multivariate_pattern'] = args.useMultivariate + data_dict['multivariate_pattern'] = args.multivariate_pattern # Do you want to save data as a dicom (True) or numpy (False) - data_dict['save_dicom'] = args.saveAsDicom + data_dict['save_dicom'] = args.save_dicom # Do you want to save the data in real time (1) or as fast as possible (0)? - data_dict['save_realtime'] = args.saveRealtime + data_dict['save_realtime'] = args.save_realtime # Default settings diff --git a/tests/utils/test_fmrisim_real_time.py b/tests/utils/test_fmrisim_real_time.py index 3dcbb4031..cfc936408 100644 --- a/tests/utils/test_fmrisim_real_time.py +++ b/tests/utils/test_fmrisim_real_time.py @@ -31,7 +31,7 @@ with pytest.raises(TypeError): gen.generate_data() # type: ignore -data_dict: Dict = {} +data_dict = {} # type: Dict vol = resource_stream(gen.__name__, "sim_parameters/ROI_A.nii.gz").read() data_dict['ROI_A_file'] = Nifti1Image.from_bytes(gzip.decompress( vol)).get_data() From 4e3a07c8b01e9aef536c6d50158105c0a1623ae7 Mon Sep 17 00:00:00 2001 From: CameronTEllis Date: Mon, 4 May 2020 14:58:43 -0400 Subject: [PATCH 33/36] Fixed underscore --- brainiak/utils/fmrisim_real_time_generator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/brainiak/utils/fmrisim_real_time_generator.py b/brainiak/utils/fmrisim_real_time_generator.py index 7e7daee3b..c3b20912a 100644 --- a/brainiak/utils/fmrisim_real_time_generator.py +++ b/brainiak/utils/fmrisim_real_time_generator.py @@ -527,7 +527,7 @@ def generate_data(outputDir, help='Param. Number of time points') argParser.add_argument('--event-duration', '-d', default=10, type=int, help='Param. Number of seconds per event') - argParser.add_argument('--scale_percentage', '-s', default=0.5, type=float, + argParser.add_argument('--scale-percentage', '-s', default=0.5, type=float, help='Param. Percent signal change') argParser.add_argument('--multivariate-pattern', '-m', default=False, action='store_true', From a129015962c313be50bbdb4e76c74b05ee375ee2 Mon Sep 17 00:00:00 2001 From: CameronTEllis Date: Mon, 4 May 2020 14:59:07 -0400 Subject: [PATCH 34/36] Make python 3.5 compatible for the path --- tests/utils/test_fmrisim_real_time.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/utils/test_fmrisim_real_time.py b/tests/utils/test_fmrisim_real_time.py index cfc936408..9011b02f1 100644 --- a/tests/utils/test_fmrisim_real_time.py +++ b/tests/utils/test_fmrisim_real_time.py @@ -61,7 +61,7 @@ def test_default(tmp_path, dd=data_dict): # Run the simulation - gen.generate_data(tmp_path, + gen.generate_data(str(tmp_path), dd) # Check that there are 32 files where there should be (30 plus label and @@ -90,7 +90,7 @@ def test_signal_size(tmp_path, dd=data_dict): dd['scale_percentage'] = 100 # Run the simulation - gen.generate_data(tmp_path, + gen.generate_data(str(tmp_path), dd) # Load in the ROI masks @@ -122,7 +122,7 @@ def test_multivariate(tmp_path, dd=data_dict): dd['scale_percentage'] = 100 # Run the simulation - gen.generate_data(tmp_path, + gen.generate_data(str(tmp_path), dd) # Load in the ROI masks @@ -146,7 +146,7 @@ def test_save_dicoms_realtime(tmp_path, dd=data_dict): start_time = time.time() # Run the simulation - gen.generate_data(tmp_path, + gen.generate_data(str(tmp_path), dd) end_time = time.time() From 2a039c7d61daa4ce67e217ee577021eb6b690b8d Mon Sep 17 00:00:00 2001 From: CameronTEllis Date: Mon, 4 May 2020 15:12:43 -0400 Subject: [PATCH 35/36] Make python 3.5 compatible for the path --- tests/utils/test_fmrisim_real_time.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/utils/test_fmrisim_real_time.py b/tests/utils/test_fmrisim_real_time.py index 9011b02f1..f348a2931 100644 --- a/tests/utils/test_fmrisim_real_time.py +++ b/tests/utils/test_fmrisim_real_time.py @@ -66,7 +66,7 @@ def test_default(tmp_path, dd=data_dict): # Check that there are 32 files where there should be (30 plus label and # mask) - assert len(os.listdir(tmp_path)) == 32, "Incorrect file number" + assert len(os.listdir(str(tmp_path))) == 32, "Incorrect file number" # Check that the data is the right shape input_template = dd['template_path'] From 533412920b32022d5d792cca2a07d37f9ef773ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mihai=20Capot=C4=83?= Date: Tue, 5 May 2020 12:06:58 -0700 Subject: [PATCH 36/36] dev: Use setuptools include_package_data --- setup.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/setup.py b/setup.py index 49ba99957..a466c348d 100644 --- a/setup.py +++ b/setup.py @@ -151,12 +151,7 @@ def finalize_options(self): ext_modules=ext_modules, cmdclass={'build_ext': BuildExt}, packages=find_packages(), - package_data={'brainiak.utils.sim_parameters': ['grey_matter_mask.npy', - 'ROI_A.nii.gz', - 'ROI_B.nii.gz', - 'mask.npy', - 'sub_noise_dict.txt', - 'sub_template.nii.gz']}, + include_package_data=True, python_requires='>=3.5', zip_safe=False, )