def test_API_type_checking(): _, bids_path, _ = get_temp_hardi() with pytest.raises( TypeError, match="bids_path must be a string"): api.AFQ(2) with pytest.raises( TypeError, match="custom_tractography_bids_filters must be" + " either a dict or None"): api.AFQ( bids_path, custom_tractography_bids_filters=["dwi"]) with pytest.raises( TypeError, match=("brain_mask must be None or a mask defined" " in `AFQ.definitions.mask`")): api.AFQ( bids_path, brain_mask="not a brain mask") with pytest.raises( TypeError, match="viz_backend must contain either 'fury' or 'plotly'"): api.AFQ(bids_path, viz_backend="matplotlib") with pytest.raises( TypeError, match="bundle_info must be None, a list of strings, or a dict"): api.AFQ(bids_path, bundle_info=[2, 3])
def test_AFQ_custom_subject_reg(): """ Test custom subject registration using AFQ object """ # make first temproary directory to generate b0 _, bids_path, sub_path = get_temp_hardi() bundle_names = ["SLF", "ARC", "CST", "FP"] b0_file = api.AFQ(bids_path, dmriprep='vistasoft', bundle_info=bundle_names).get_b0()[0] # make a different temporary directly to test this custom file in _, bids_path, sub_path = get_temp_hardi() os.rename(b0_file, op.join(sub_path, "sub-01_ses-01_customb0.nii.gz")) my_afq = api.AFQ(bids_path, dmriprep='vistasoft', bundle_info=bundle_names, reg_template="mni_T2", reg_subject={ "suffix": "customb0", "scope": "vistasoft" }) my_afq.export_rois()
def test_AFQ_anisotropic(): """ Test if API can run using anisotropic registration with a specific selection of b vals """ _, bids_path, _ = get_temp_hardi() myafq = api.AFQ(bids_path=bids_path, dmriprep='vistasoft', min_bval=1990, max_bval=2010, b0_threshold=50, reg_template="mni_T1", reg_subject="power_map") row = myafq.data_frame.iloc[0] _, gtab, _ = myafq._get_data_gtab(row) # check the b0s mask is correct b0s_mask = np.zeros(160, dtype=bool) b0s_mask[0:10] = True npt.assert_equal(gtab.b0s_mask, b0s_mask) # check that only b values in the b val range passed bvals_in_range = \ np.logical_and((gtab.bvals > 1990), (gtab.bvals < 2010)) bvals_in_range_or_0 = \ np.logical_or(bvals_in_range, gtab.b0s_mask) npt.assert_equal(bvals_in_range_or_0, np.ones(160, dtype=bool)) # check that the apm map was made myafq.set_mapping() assert op.exists( op.join(myafq.data_frame['results_dir'][0], 'sub-01_ses-01_dwi_model-CSD_APM.nii.gz'))
def test_AFQ_pft(): """ Test pft interface for AFQ """ _, bids_path, sub_path = get_temp_hardi() bundle_names = ["SLF", "ARC", "CST", "FP"] f_pve_csf, f_pve_gm, f_pve_wm = get_fnames('stanford_pve_maps') os.rename(f_pve_wm, op.join(sub_path, "sub-01_ses-01_WMprobseg.nii.gz")) os.rename(f_pve_gm, op.join(sub_path, "sub-01_ses-01_GMprobseg.nii.gz")) os.rename(f_pve_csf, op.join(sub_path, "sub-01_ses-01_CSFprobseg.nii.gz")) stop_mask = PFTMask(MaskFile("WMprobseg"), MaskFile("GMprobseg"), MaskFile("CSFprobseg")) my_afq = api.AFQ(bids_path, dmriprep='vistasoft', bundle_info=bundle_names, tracking_params={ "stop_mask": stop_mask, "stop_threshold": "CMC", "tracker": "pft" }) my_afq.get_streamlines()
def test_AFQ_fury(): _, bids_path, _ = get_temp_hardi() myafq = api.AFQ(bids_path=bids_path, dmriprep='vistasoft', viz_backend="fury") myafq.viz_bundles()
def test_AFQ_custom_tract(): """ Test whether AFQ can use tractography from custom_tractography_bids_filters """ _, bids_path, sub_path = get_temp_hardi() afd.fetch_stanford_hardi_tractography() bundle_names = ["SLF", "ARC", "CST", "FP"] # move subsampled tractography into bids folder os.rename( op.join( op.expanduser('~'), 'AFQ_data', 'stanford_hardi_tractography', 'tractography_subsampled.trk'), op.join( sub_path, 'subsampled_tractography.trk' ) ) my_afq = api.AFQ( bids_path, dmriprep='vistasoft', bundle_info=bundle_names, custom_tractography_bids_filters={ "suffix": "tractography", "scope": "vistasoft" }) my_afq.get_streamlines()
def test_AFQ_custom_bundle_dict(): bids_path = create_dummy_bids_path(3, 1) bundle_dict = api.make_bundle_dict() my_afq = api.AFQ( bids_path, dmriprep="synthetic", bundle_info=bundle_dict)
def test_AFQ_missing_files(): tmpdir = nbtmp.InTemporaryDirectory() bids_path = tmpdir.name with pytest.raises( ValueError, match="There must be a dataset_description.json in bids_path"): api.AFQ(bids_path) afd.to_bids_description(bids_path, **{ "Name": "Missing", "Subjects": ["sub-01"] }) with pytest.raises( ValueError, match=f"No non-json files recognized by pyBIDS in {bids_path}"): api.AFQ(bids_path) subses_folder = op.join(bids_path, "derivatives", "otherDeriv", 'sub-01', 'ses-01') os.makedirs(subses_folder, exist_ok=True) afd.to_bids_description( op.join(bids_path, "derivatives", "otherDeriv"), **{ "Name": "Missing", "PipelineDescription": { "Name": "otherDeriv" } }) touch(op.join(subses_folder, "sub-01_ses-01_dwi.nii.gz")) with pytest.raises(ValueError, match="No non-json files recognized by pyBIDS" + " in the pipeline: missingPipe"): api.AFQ(bids_path, dmriprep="missingPipe") os.mkdir(op.join(bids_path, "missingPipe")) afd.to_bids_description( op.join(bids_path, "missingPipe"), **{ "Name": "Missing", "PipelineDescription": { "Name": "missingPipe" } }) with pytest.raises(ValueError, match="No non-json files recognized by pyBIDS" + " in the pipeline: missingPipe"): api.AFQ(bids_path, dmriprep="missingPipe")
def test_afq_msmt(): tmpdir = nbtmp.InTemporaryDirectory() afd.organize_cfin_data(path=tmpdir.name) myafq = api.AFQ(bids_path=op.join(tmpdir.name, 'cfin_multib'), dmriprep='dipy', tracking_params={"odf_model": "MSMT"}) npt.assert_equal( op.split(myafq.streamlines[0])[-1], "sub-01_ses-01_dwi_space-RASMM_model-MSMT_desc-det_tractography.trk")
def test_AFQ_init(): """ Test the initialization of the AFQ object """ n_subjects = 3 n_sessions = 2 preafq_path = create_dummy_preafq_path(n_subjects, n_sessions) my_afq = api.AFQ(preafq_path=preafq_path) npt.assert_equal(my_afq.data_frame.shape, (n_subjects * n_sessions, 10))
def test_AFQ_FA(): """ Test if API can run registeration with FA """ _, bids_path, _ = get_temp_hardi() myafq = api.AFQ(bids_path=bids_path, dmriprep='vistasoft', reg_template='dti_fa_template', reg_subject='dti_fa_subject') myafq.export_rois()
def test_DKI_profile(): """ Test using API to profile dki """ tmpdir = nbtmp.InTemporaryDirectory() afd.organize_cfin_data(path=tmpdir.name) myafq = api.AFQ(bids_path=op.join(tmpdir.name, 'cfin_multib'), dmriprep='dipy') myafq.get_dki_fa() myafq.get_dki_md()
def test_AFQ_no_prealign(): """ Test if API can run without prealign """ tmpdir = nbtmp.InTemporaryDirectory() afd.organize_stanford_data(path=tmpdir.name) myafq = api.AFQ(dmriprep_path=op.join(tmpdir.name, 'stanford_hardi', 'derivatives', 'dmriprep'), sub_prefix='sub', use_prealign=False) myafq.export_rois()
def test_AFQ_data(): """ Test with some actual data """ tmpdir = nbtmp.InTemporaryDirectory() afd.organize_stanford_data(path=tmpdir.name) myafq = api.AFQ(preproc_path=op.join(tmpdir.name, 'stanford_hardi'), sub_prefix='sub') npt.assert_equal(nib.load(myafq.brain_mask[0]).shape, nib.load(myafq['dwi_file'][0]).shape[:3]) npt.assert_equal(nib.load(myafq.brain_mask[0]).shape, nib.load(myafq.dti[0]).shape[:3])
def test_AFQ_no_derivs(): """ Test the initialization of the AFQ object """ bids_path = create_dummy_bids_path(1, 1) os.remove( op.join(bids_path, "derivatives", "dmriprep", "dataset_description.json")) with pytest.raises( ValueError, match=f"No non-json files recognized by pyBIDS in {bids_path}"): api.AFQ(bids_path, dmriprep="synthetic")
def test_AFQ_slr(): """ Test if API can run using slr map """ _, bids_path, _ = get_temp_hardi() myafq = api.AFQ(bids_path=bids_path, dmriprep='vistasoft', reg_subject='subject_sls', reg_template='hcp_atlas') tgram = load_tractogram(myafq.get_clean_bundles()[0], myafq.dwi_img[0]) bundles = aus.tgram_to_bundles(tgram, myafq.bundle_dict, myafq.dwi_img[0]) npt.assert_(len(bundles['CST_L']) > 0)
def test_AFQ_no_derivs(): """ Test the initialization of the AFQ object """ bids_path = create_dummy_bids_path(1, 1) os.remove( op.join(bids_path, "derivatives", "dmriprep", "dataset_description.json")) with pytest.raises( ValueError, match="`bids_path` contains no subjects in derivatives folders." + " This could be caused by derivatives folders not" + " following the BIDS format."): my_afq = api.AFQ(bids_path, dmriprep="synthetic")
def main(): parser = ArgumentParser() parser.add_argument("--run-id", "-i", default=None) parser.add_argument("--data-path", "-p", default=None) parser.add_argument("--dataset", "-d", default="stanford_hardi") parser.add_argument("--setup", "-s", action="store_true") results = parser.parse_args() if results.setup: afd.organize_stanford_data() afd.fetch_templates() afd.fetch_hcp_atlas_16_bundles() afd.fetch_hcp_atlas_80_bundles() return 0 orig_dp = op.join(afd.afq_home, results.dataset) bp = results.data_path if results.data_path else afd.afq_home dp = op.join(bp, results.dataset) if results.run_id: dp = op.join(dp, results.run_id) if dp != orig_dp: try: # Create the data directory os.makedirs(op.join(dp, 'derivatives')) # Make a symbolic link to the original os.symlink(op.join(orig_dp, 'derivatives', 'freesurfer'), op.join(dp, 'derivatives', 'freesurfer')) os.symlink(op.join(orig_dp, 'derivatives', 'vistasoft'), op.join(dp, 'derivatives', 'vistasoft')) os.symlink(op.join(orig_dp, 'dataset_description.json'), op.join(dp, 'dataset_description.json')) except FileExistsError: pass # Run AFQ myafq = api.AFQ(bids_path=dp, reg_template="mni_T2", reg_subject="b0", dmriprep='vistasoft', viz_backend='plotly_no_gif') bundle_html = myafq.viz_bundles(export=True, n_points=50) plotly.io.show(bundle_html[0]) myafq.plot_tract_profiles() fig_files = myafq.data_frame['tract_profiles_viz'][0]
def test_AFQ_init(): """ Test the initialization of the AFQ object """ for n_sessions in [1, 2, 3]: n_subjects = 3 bids_path = create_dummy_bids_path(n_subjects, n_sessions, (n_subjects != n_sessions)) my_afq = api.AFQ(bids_path, dmriprep="synthetic") if n_subjects != n_sessions: npt.assert_equal(my_afq.data_frame.shape, (n_subjects * n_sessions, 13)) else: npt.assert_equal(my_afq.data_frame.shape, (n_subjects, 13))
def test_AFQ_reco80(): """ Test API segmentation with the 80-bundle atlas """ _, bids_path, _ = get_temp_hardi() myafq = api.AFQ(bids_path=bids_path, dmriprep='vistasoft', segmentation_params={ 'seg_algo': 'reco80', 'rng': 42 }) tgram = load_tractogram(myafq.get_clean_bundles()[0], myafq.dwi_img[0]) bundles = aus.tgram_to_bundles(tgram, myafq.bundle_dict, myafq.dwi_img[0]) npt.assert_(len(bundles['CCMid']) > 0)
def afq_process_subject(subject): # define a function that each job will run # In this case, each process does a single subject import logging import s3fs # all imports must be at the top of the function # cloudknot installs the appropriate packages from pip import AFQ.data as afqd import AFQ.api as api import AFQ.definitions.mask as afm # set logging level to your choice logging.basicConfig(level=logging.INFO) log = logging.getLogger(__name__) # Download the given subject to your local machine from s3 # Can find subjects more easily if they are specified in a # BIDS participants.tsv file, even if it is sparse study_ixi = afqd.S3BIDSStudy("my_study", "my_study_bucket", "my_study_prefix", subjects=[subject], use_participants_tsv=True, anon=False) study_ixi.download("local_bids_dir", include_derivs=["pipeline_name"]) # you can optionally provide your own segmentation file # in this case, we look for a file with suffix 'seg' # in the 'pipeline_name' pipeline, # and we consider all non-zero labels to be a part of the brain brain_mask = afm.LabelledMaskFile('seg', {'scope': 'pipeline_name'}, exclusive_labels=[0]) # define the api AFQ object myafq = api.AFQ( "local_bids_dir", dmriprep="pipeline_name", brain_mask=brain_mask, viz_backend= 'plotly', # this will generate both interactive html and GIFs scalars=["dki_fa", "dki_md"]) # export_all runs the entire pipeline and creates many useful derivates myafq.export_all() # upload the results to some location on s3 myafq.upload_to_s3(s3fs.S3FileSystem(), f"my_study_bucket/my_study_prefix/derivatives/afq")
def test_AFQ_data(): """ Test if API can run without prealign """ _, bids_path, _ = get_temp_hardi() for use_prealign in [True, False]: myafq = api.AFQ(bids_path=bids_path, dmriprep='vistasoft', use_prealign=use_prealign) npt.assert_equal( nib.load(myafq.b0[0]).shape, nib.load(myafq['dwi_file'][0]).shape[:3]) npt.assert_equal( nib.load(myafq.b0[0]).shape, nib.load(myafq.dti[0]).shape[:3]) myafq.export_rois()
def test_AFQ_reco(): """ Test if API can run segmentation with recobundles """ _, bids_path, _ = get_temp_hardi() myafq = api.AFQ(bids_path=bids_path, dmriprep='vistasoft', viz_backend="plotly", segmentation_params={ 'seg_algo': 'reco', 'rng': 42 }) tgram = load_tractogram(myafq.get_clean_bundles()[0], myafq.dwi_img[0]) bundles = aus.tgram_to_bundles(tgram, myafq.bundle_dict, myafq.dwi_img[0]) npt.assert_(len(bundles['CCMid']) > 0) myafq.export_all()
def test_AFQ_data(): """ Test if API can run without prealign and with only pre-align """ _, bids_path, _ = get_temp_hardi() for mapping in [SynMap(use_prealign=False), AffMap()]: myafq = api.AFQ(bids_path=bids_path, dmriprep='vistasoft', mapping=mapping) npt.assert_equal( nib.load(myafq.b0["01"]).shape, nib.load(myafq.dwi_file["01"]).shape[:3]) npt.assert_equal( nib.load(myafq.b0["01"]).shape, nib.load(myafq.dti_params["01"]).shape[:3]) myafq.rois shutil.rmtree(op.join(bids_path, 'derivatives/afq'))
def test_AFQ_data(): """ Test if API can run without prealign and with only pre-align """ _, bids_path, _ = get_temp_hardi() for use_prealign in [0, 1, 2]: myafq = api.AFQ(bids_path=bids_path, dmriprep='vistasoft', use_prealign=use_prealign) npt.assert_equal( nib.load(myafq.b0[0]).shape, nib.load(myafq['dwi_file'][0]).shape[:3]) npt.assert_equal( nib.load(myafq.b0[0]).shape, nib.load(myafq.dti[0]).shape[:3]) myafq.export_rois() shutil.rmtree(op.join(bids_path, 'derivatives/afq'))
def test_AFQ_init(): """ Test the initialization of the AFQ object """ for n_sessions in [1, 2, 3]: n_subjects = 3 bids_path = create_dummy_bids_path(n_subjects, n_sessions, (n_subjects != n_sessions)) my_afq = api.AFQ(bids_path, dmriprep="synthetic") for subject in range(n_subjects): sub = f"0{subject+1}" if n_subjects == n_sessions: npt.assert_equal(len(my_afq.wf_dict[sub][sub]), 40) else: for session in range(n_sessions): if n_sessions == 1: sess = "None" else: sess = f"0{session+1}" npt.assert_equal(len(my_afq.wf_dict[sub][sess]), 40)
# in the ROIs of every bundle. # # We only do this to make this example faster and consume less space. tracking_params = dict(seed_mask=RoiMask(), n_seeds=10000, random_seeds=True, rng_seed=42) ########################################################################## # Initialize an AFQ object: # ------------------------- # # We specify bundle_info as the default bundles list (api.BUNDLES) plus the # callosal bundle list. This tells the AFQ object to use bundles from both # the standard and callosal templates. myafq = api.AFQ(bids_path=op.join(afd.afq_home, 'stanford_hardi'), dmriprep='vistasoft', bundle_info=api.BUNDLES + api.CALLOSUM_BUNDLES, tracking_params=tracking_params) ########################################################################## # Visualizing bundles and tract profiles: # --------------------------------------- # This would run the script and visualize the bundles using the plotly # interactive visualization, which should automatically open in a # new browser window. bundle_html = myafq.viz_bundles(export=True, n_points=50) plotly.io.show(bundle_html[0])
# compliant data. # # .. note:: # # As noted above, the Stanford HARDI data contains anatomical and # diffusion weighted imaging (dwi) data. In this example, we are interested # in the vistasoft dwi. For our dataset the `dmriprep` is optional, but # we have included it to make the initialization more explicit. # # .. note:: # # We will also be using plotly to generate an interactive visualization. # So we will specify plotly_no_gif as the visualization backend. myafq = api.AFQ(bids_path=op.join(afd.afq_home, 'stanford_hardi'), dmriprep='vistasoft', viz_backend='plotly_no_gif') ########################################################################## # Reading in DTI FA (Diffusion Tensor Imaging Fractional Anisotropy) # ------------------------------------------------------------------ # The AFQ object holds a table with file names to various data derivatives. # # For example, the file where the FA computed from DTI is stored can be # retrieved by inspecting the ``dti_fa`` property. The measures are stored # in a series, and since we only have one subject and one session we will # access the first (and only) file name from the example data. # # .. note:: # # The AFQ API computes quantities lazily. This means that DTI parameters
# --------------------- # We make this tracking_params which we will pass to the AFQ object # which specifies that we want 50,000 seeds randomly distributed # in the white matter. # # We only do this to make this example faster and consume less space. tracking_params = dict(n_seeds=50000, random_seeds=True, rng_seed=42) ########################################################################## # Initialize an AFQ object: # ------------------------- # # We specify seg_algo as reco80 in segmentation_params. This tells the AFQ # object to perform RecoBundles using the 80 bundles atlas in the # segmentation step. myafq = api.AFQ(bids_path=op.join(afd.afq_home, 'stanford_hardi'), dmriprep='vistasoft', segmentation_params={"seg_algo": "reco80"}, tracking_params=tracking_params) ########################################################################## # Visualizing bundles and tract profiles: # --------------------------------------- # This would run the script and visualize the bundles using the plotly # interactive visualization, which should automatically open in a # new browser window. bundle_html = myafq.all_bundles_figure plotly.io.show(bundle_html["01"])
2 } }) endpoint_info = { "L_OR": { "startpoint": or_rois['left_thal_MNI'], "endpoint": or_rois['left_V1_MNI'] }, "R_OR": { "startpoint": or_rois['right_thal_MNI'], "endpoint": or_rois['right_V1_MNI'] } } brain_mask = LabelledMaskFile("seg", {"scope": "freesurfer"}, exclusive_labels=[0]) my_afq = api.AFQ(bids_path=op.join(afd.afq_home, 'stanford_hardi'), brain_mask=brain_mask, tracking_params={ "n_seeds": 3, "directions": "prob", "odf_model": "CSD", "seed_mask": RoiMask() }, segmentation_params=dict(endpoint_info=endpoint_info), bundle_info=bundles) my_afq.export_all()