1""" 2Downloading NeuroImaging datasets: structural datasets 3 4# License: simplified BSD 5""" 6 7import warnings 8import os 9import functools 10from pathlib import Path 11 12import numpy as np 13from scipy import ndimage 14from sklearn.utils import Bunch 15 16from .utils import (_get_dataset_dir, _fetch_files, _get_dataset_descr) 17 18from ..image import new_img_like, get_data, resampling 19from .._utils import check_niimg, fill_doc 20 21_package_directory = os.path.dirname(os.path.abspath(__file__)) 22MNI152_FILE_PATH = os.path.join( 23 _package_directory, "data", 24 "mni_icbm152_t1_tal_nlin_sym_09a_converted.nii.gz") 25GM_MNI152_FILE_PATH = os.path.join( 26 _package_directory, "data", 27 "mni_icbm152_gm_tal_nlin_sym_09a_converted.nii.gz") 28WM_MNI152_FILE_PATH = os.path.join( 29 _package_directory, "data", 30 "mni_icbm152_wm_tal_nlin_sym_09a_converted.nii.gz") 31FSAVERAGE5_PATH = os.path.join(_package_directory, "data", "fsaverage5") 32 33 34# workaround for 35# https://github.com/nilearn/nilearn/pull/2738#issuecomment-869018842 36_MNI_RES_WARNING_ALREADY_SHOWN = False 37 38 39@fill_doc 40def fetch_icbm152_2009(data_dir=None, url=None, resume=True, verbose=1): 41 """Download and load the ICBM152 template (dated 2009). 42 43 For more information, see :footcite:`FONOV2011313`, 44 :footcite:`Fonov2009`, and :footcite:`Collins1999algorithm`. 45 46 Parameters 47 ---------- 48 %(data_dir)s 49 %(url)s 50 %(resume)s 51 %(verbose)s 52 53 Returns 54 ------- 55 data : sklearn.datasets.base.Bunch 56 Dictionary-like object, interest keys are: 57 58 - "t1": str, 59 Path to T1-weighted anatomical image 60 - "t2": str, 61 Path to T2-weighted anatomical image 62 - "t2_relax": str, 63 Path to anatomical image obtained with the T2 relaxometry 64 - "pd": str, 65 Path to the proton density weighted anatomical image 66 - "gm": str, 67 Path to grey matter segmented image 68 - "wm": str, 69 Path to white matter segmented image 70 - "csf": str, 71 Path to cerebrospinal fluid segmented image 72 - "eye_mask": str, 73 Path to eye mask useful to mask out part of MRI images 74 - "face_mask": str, 75 Path to face mask useful to mask out part of MRI images 76 - "mask": str, 77 Path to whole brain mask useful to mask out skull areas 78 79 See Also 80 -------- 81 nilearn.datasets.load_mni152_template: to load MNI152 T1 template. 82 83 nilearn.datasets.load_mni152_gm_template: to load MNI152 grey matter 84 template. 85 86 nilearn.datasets.load_mni152_wm_template: to load MNI152 white matter 87 template. 88 89 nilearn.datasets.load_mni152_brain_mask: to load MNI152 whole brain mask. 90 91 nilearn.datasets.load_mni152_gm_mask: to load MNI152 grey matter mask. 92 93 nilearn.datasets.load_mni152_wm_mask: to load MNI152 white matter mask. 94 95 nilearn.datasets.fetch_icbm152_brain_gm_mask: to fetch only ICBM grey 96 matter mask. 97 98 References 99 ---------- 100 .. footbibliography:: 101 102 Notes 103 ----- 104 For more information about this dataset's structure: 105 http://www.bic.mni.mcgill.ca/ServicesAtlases/ICBM152NLin2009 106 107 The original download URL is 108 http://www.bic.mni.mcgill.ca/~vfonov/icbm/2009/mni_icbm152_nlin_sym_09a_nifti.zip 109 110 """ 111 if url is None: 112 # The URL can be retrieved from the nilearn account on OSF (Open 113 # Science Framework), https://osf.io/4r3jt/quickfiles/ 114 # Clicking on the "share" button gives the root of the URL. 115 url = "https://osf.io/7pj92/download" 116 opts = {'uncompress': True} 117 118 keys = ("csf", "gm", "wm", 119 "pd", "t1", "t2", "t2_relax", 120 "eye_mask", "face_mask", "mask") 121 filenames = [(os.path.join("mni_icbm152_nlin_sym_09a", name), url, opts) 122 for name in ( 123 "mni_icbm152_csf_tal_nlin_sym_09a.nii.gz", 124 "mni_icbm152_gm_tal_nlin_sym_09a.nii.gz", 125 "mni_icbm152_wm_tal_nlin_sym_09a.nii.gz", 126 127 "mni_icbm152_pd_tal_nlin_sym_09a.nii.gz", 128 "mni_icbm152_t1_tal_nlin_sym_09a.nii.gz", 129 "mni_icbm152_t2_tal_nlin_sym_09a.nii.gz", 130 "mni_icbm152_t2_relx_tal_nlin_sym_09a.nii.gz", 131 132 "mni_icbm152_t1_tal_nlin_sym_09a_eye_mask.nii.gz", 133 "mni_icbm152_t1_tal_nlin_sym_09a_face_mask.nii.gz", 134 "mni_icbm152_t1_tal_nlin_sym_09a_mask.nii.gz")] 135 136 dataset_name = 'icbm152_2009' 137 data_dir = _get_dataset_dir(dataset_name, data_dir=data_dir, 138 verbose=verbose) 139 sub_files = _fetch_files(data_dir, filenames, resume=resume, 140 verbose=verbose) 141 142 fdescr = _get_dataset_descr(dataset_name) 143 144 params = dict([('description', fdescr)] + list(zip(keys, sub_files))) 145 return Bunch(**params) 146 147 148@functools.lru_cache(maxsize=3) 149def load_mni152_template(resolution=None): 150 """Load the MNI152 skullstripped T1 template. 151 This function takes the skullstripped, re-scaled 1mm-resolution version of 152 the MNI ICBM152 T1 template and re-samples it using a different resolution, 153 if specified. 154 155 For more information, see :footcite:`FONOV2011313`, 156 and :footcite:`Fonov2009`. 157 158 Parameters 159 ---------- 160 resolution: int, optional, Default = 2 161 If resolution is different from 1, the template is re-sampled with the 162 specified resolution. 163 164 .. versionadded:: 0.8.1 165 166 Returns 167 ------- 168 mni152_template : Nifti1Image, image representing the re-sampled 169 whole-brain template 170 171 See Also 172 -------- 173 nilearn.datasets.load_mni152_gm_template : for details about version of the 174 MNI152 grey-matter template. 175 176 nilearn.datasets.load_mni152_wm_template : for details about version of the 177 MNI152 white-matter template. 178 179 References 180 ---------- 181 .. footbibliography:: 182 183 """ 184 185 global _MNI_RES_WARNING_ALREADY_SHOWN 186 if resolution is None: 187 if not _MNI_RES_WARNING_ALREADY_SHOWN: 188 warnings.warn("Default resolution of the MNI template will change " 189 "from 2mm to 1mm in version 0.10.0", FutureWarning, 190 stacklevel=2) 191 _MNI_RES_WARNING_ALREADY_SHOWN = True 192 resolution = 2 193 194 brain_template = check_niimg(MNI152_FILE_PATH) 195 196 # Typecasting 197 brain_data = get_data(brain_template).astype("float32") 198 199 # Re-scale template from 0 to 1 200 brain_data /= brain_data.max() 201 new_brain_template = new_img_like(brain_template, brain_data) 202 203 # Resample template according to the pre-specified resolution, if different 204 # than 1 205 if resolution != 1: 206 new_brain_template = resampling.resample_img(new_brain_template, 207 np.eye(3) * resolution) 208 209 return new_brain_template 210 211 212def load_mni152_gm_template(resolution=None): 213 """Load the MNI152 grey-matter template. 214 This function takes the re-scaled 1mm-resolution version of the grey-matter 215 MNI ICBM152 template and re-samples it using a different resolution, 216 if specified. 217 218 .. versionadded:: 0.8.1 219 220 Parameters 221 ---------- 222 resolution: int, optional, Default = 2 223 If resolution is different from 1, the template is re-sampled with the 224 specified resolution. 225 226 Returns 227 ------- 228 gm_mni152_template : Nifti1Image, image representing the resampled 229 grey-matter template 230 231 See Also 232 -------- 233 nilearn.datasets.load_mni152_template : for details about version of the 234 MNI152 T1 template. 235 236 nilearn.datasets.load_mni152_wm_template : for details about version of the 237 MNI152 white-matter template. 238 239 """ 240 241 global _MNI_RES_WARNING_ALREADY_SHOWN 242 if resolution is None: 243 if not _MNI_RES_WARNING_ALREADY_SHOWN: 244 warnings.warn("Default resolution of the MNI template will change " 245 "from 2mm to 1mm in version 0.10.0", FutureWarning) 246 _MNI_RES_WARNING_ALREADY_SHOWN = True 247 resolution = 2 248 249 gm_template = check_niimg(GM_MNI152_FILE_PATH) 250 251 # Typecasting 252 gm_data = get_data(gm_template).astype("float32") 253 254 # Re-scale template from 0 to 1 255 gm_data /= gm_data.max() 256 new_gm_template = new_img_like(gm_template, gm_data) 257 258 # Resample template according to the pre-specified resolution, if different 259 # than 1 260 if resolution != 1: 261 new_gm_template = resampling.resample_img(new_gm_template, 262 np.eye(3) * resolution) 263 264 return new_gm_template 265 266 267def load_mni152_wm_template(resolution=None): 268 """Load the MNI152 white-matter template. 269 This function takes the re-scaled 1mm-resolution version of the 270 white-matter MNI ICBM152 template and re-samples it using a different 271 resolution, if specified. 272 273 .. versionadded:: 0.8.1 274 275 Parameters 276 ---------- 277 resolution: int, optional, Default = 2 278 If resolution is different from 1, the template is re-sampled with the 279 specified resolution. 280 281 Returns 282 ------- 283 wm_mni152_template : Nifti1Image, image representing the resampled 284 white-matter template 285 286 See Also 287 -------- 288 nilearn.datasets.load_mni152_template : for details about version of the 289 MNI152 T1 template. 290 291 nilearn.datasets.load_mni152_gm_template : for details about version of the 292 MNI152 grey-matter template. 293 294 """ 295 296 global _MNI_RES_WARNING_ALREADY_SHOWN 297 if resolution is None: 298 if not _MNI_RES_WARNING_ALREADY_SHOWN: 299 warnings.warn("Default resolution of the MNI template will change " 300 "from 2mm to 1mm in version 0.10.0", FutureWarning) 301 _MNI_RES_WARNING_ALREADY_SHOWN = True 302 resolution = 2 303 304 wm_template = check_niimg(WM_MNI152_FILE_PATH) 305 306 # Typecasting 307 wm_data = get_data(wm_template).astype("float32") 308 309 # Re-scale template from 0 to 1 310 wm_data /= wm_data.max() 311 new_wm_template = new_img_like(wm_template, wm_data) 312 313 # Resample template according to the pre-specified resolution, if different 314 # than 1 315 if resolution != 1: 316 new_wm_template = resampling.resample_img(new_wm_template, 317 np.eye(3) * resolution) 318 319 return new_wm_template 320 321 322def load_mni152_brain_mask(resolution=None, threshold=0.2): 323 """Load the MNI152 whole-brain mask. 324 This function takes the whole-brain MNI152 T1 template and threshold it, 325 in order to obtain the corresponding whole-brain mask. 326 327 .. versionadded:: 0.2.5 328 329 Parameters 330 ---------- 331 resolution: int, optional, Default = 2 332 If resolution is different from 1, the template loaded is first 333 re-sampled with the specified resolution. 334 335 .. versionadded:: 0.8.1 336 337 threshold : float, optional 338 Values of the MNI152 T1 template above this threshold will be included. 339 Default=0.2 340 341 Returns 342 ------- 343 mask_img : Nifti1Image, image corresponding to the whole-brain mask. 344 345 Notes 346 ----- 347 Refer to load_mni152_template function for more information about the 348 MNI152 T1 template. 349 350 See Also 351 -------- 352 nilearn.datasets.load_mni152_template : for details about version of the 353 MNI152 T1 template and related. 354 355 """ 356 357 global _MNI_RES_WARNING_ALREADY_SHOWN 358 if resolution is None: 359 if not _MNI_RES_WARNING_ALREADY_SHOWN: 360 warnings.warn("Default resolution of the MNI template will change " 361 "from 2mm to 1mm in version 0.10.0", FutureWarning) 362 _MNI_RES_WARNING_ALREADY_SHOWN = True 363 resolution = 2 364 365 # Load MNI template 366 target_img = load_mni152_template(resolution=resolution) 367 mask_voxels = (get_data(target_img) > threshold).astype("int8") 368 mask_img = new_img_like(target_img, mask_voxels) 369 370 return mask_img 371 372 373def load_mni152_gm_mask(resolution=None, threshold=0.2, n_iter=2): 374 """Load the MNI152 grey-matter mask. 375 This function takes the grey-matter MNI152 template and threshold it, in 376 order to obtain the corresponding grey-matter mask. 377 378 .. versionadded:: 0.8.1 379 380 Parameters 381 ---------- 382 resolution: int, optional, Default = 2 383 If resolution is different from 1, the template loaded is first 384 re-sampled with the specified resolution. 385 386 threshold : float, optional 387 Values of the grey-matter MNI152 template above this threshold will be 388 included. Default=0.2 389 390 n_iter: int, optional, Default = 2 391 Number of repetitions of dilation and erosion steps performed in 392 scipy.ndimage.binary_closing function. 393 394 Returns 395 ------- 396 gm_mask_img : Nifti1Image, image corresponding to the grey-matter mask. 397 398 Notes 399 ----- 400 Refer to load_mni152_gm_template function for more information about the 401 MNI152 grey-matter template. 402 403 See Also 404 -------- 405 nilearn.datasets.load_mni152_gm_template : for details about version of the 406 MNI152 grey-matter template and related. 407 408 """ 409 410 global _MNI_RES_WARNING_ALREADY_SHOWN 411 if resolution is None: 412 if not _MNI_RES_WARNING_ALREADY_SHOWN: 413 warnings.warn("Default resolution of the MNI template will change " 414 "from 2mm to 1mm in version 0.10.0", FutureWarning) 415 _MNI_RES_WARNING_ALREADY_SHOWN = True 416 resolution = 2 417 418 # Load MNI template 419 gm_target = load_mni152_gm_template(resolution=resolution) 420 gm_target_img = check_niimg(gm_target) 421 gm_target_data = get_data(gm_target_img) 422 423 gm_target_mask = (gm_target_data > threshold).astype("int8") 424 425 gm_target_mask = ndimage.binary_closing(gm_target_mask, iterations=n_iter) 426 gm_mask_img = new_img_like(gm_target_img, gm_target_mask) 427 428 return gm_mask_img 429 430 431def load_mni152_wm_mask(resolution=None, threshold=0.2, n_iter=2): 432 """Load the MNI152 white-matter mask. 433 This function takes the white-matter MNI152 template and threshold it, in 434 order to obtain the corresponding white-matter mask. 435 436 .. versionadded:: 0.8.1 437 438 Parameters 439 ---------- 440 resolution: int, optional, Default = 2 441 If resolution is different from 1, the template loaded is first 442 re-sampled with the specified resolution. 443 444 threshold : float, optional 445 Values of the white-matter MNI152 template above this threshold will be 446 included. Default=0.2 447 448 n_iter: int, optional, Default = 2 449 Number of repetitions of dilation and erosion steps performed in 450 scipy.ndimage.binary_closing function. 451 452 Returns 453 ------- 454 wm_mask_img : Nifti1Image, image corresponding to the white-matter mask. 455 456 Notes 457 ----- 458 Refer to load_mni152_gm_template function for more information about the 459 MNI152 white-matter template. 460 461 See Also 462 -------- 463 nilearn.datasets.load_mni152_wm_template : for details about version of the 464 MNI152 white-matter template and related. 465 466 """ 467 468 global _MNI_RES_WARNING_ALREADY_SHOWN 469 if resolution is None: 470 if not _MNI_RES_WARNING_ALREADY_SHOWN: 471 warnings.warn("Default resolution of the MNI template will change " 472 "from 2mm to 1mm in version 0.10.0", FutureWarning) 473 _MNI_RES_WARNING_ALREADY_SHOWN = True 474 resolution = 2 475 476 # Load MNI template 477 wm_target = load_mni152_wm_template(resolution=resolution) 478 wm_target_img = check_niimg(wm_target) 479 wm_target_data = get_data(wm_target_img) 480 481 wm_target_mask = (wm_target_data > threshold).astype("int8") 482 483 wm_target_mask = ndimage.binary_closing(wm_target_mask, iterations=n_iter) 484 wm_mask_img = new_img_like(wm_target_img, wm_target_mask) 485 486 return wm_mask_img 487 488 489@fill_doc 490def fetch_icbm152_brain_gm_mask(data_dir=None, threshold=0.2, resume=True, 491 n_iter=2, verbose=1): 492 """Downloads ICBM152 template first, then loads the 'gm' mask. 493 494 .. versionadded:: 0.2.5 495 496 Parameters 497 ---------- 498 %(data_dir)s 499 threshold : float, optional 500 Values of the ICBM152 grey-matter template above this threshold will be 501 included. Default=0.2 502 503 %(resume)s 504 n_iter: int, optional, Default = 2 505 Number of repetitions of dilation and erosion steps performed in 506 scipy.ndimage.binary_closing function. 507 508 .. versionadded:: 0.8.1 509 510 %(verbose)s 511 512 Returns 513 ------- 514 gm_mask_img : Nifti1Image, image corresponding to the brain grey matter 515 from ICBM152 template. 516 517 Notes 518 ----- 519 This function relies on ICBM152 templates where we particularly pick 520 grey matter template and threshold the template at .2 to take one fifth 521 of the values. Then, do a bit post processing such as binary closing 522 operation to more compact mask image. 523 524 .. note:: 525 It is advised to check the mask image with your own data processing. 526 527 See Also 528 -------- 529 nilearn.datasets.fetch_icbm152_2009: for details regarding the ICBM152 530 template. 531 532 nilearn.datasets.load_mni152_template: for details about version of MNI152 533 template and related. 534 535 """ 536 # Fetching ICBM152 grey matter mask image 537 icbm = fetch_icbm152_2009(data_dir=data_dir, resume=resume, 538 verbose=verbose) 539 gm = icbm['gm'] 540 gm_img = check_niimg(gm) 541 gm_data = get_data(gm_img) 542 543 # getting one fifth of the values 544 gm_mask = (gm_data > threshold).astype("int8") 545 546 gm_mask = ndimage.binary_closing(gm_mask, iterations=n_iter) 547 gm_mask_img = new_img_like(gm_img, gm_mask) 548 549 return gm_mask_img 550 551 552@fill_doc 553def fetch_oasis_vbm(n_subjects=None, dartel_version=True, data_dir=None, 554 url=None, resume=True, verbose=1): 555 """Download and load Oasis "cross-sectional MRI" dataset (416 subjects). 556 557 For more information, see :footcite:`OASISbrain`, 558 and :footcite:`Marcus2007OASIS`. 559 560 Parameters 561 ---------- 562 n_subjects : int, optional 563 The number of subjects to load. If None is given, all the 564 subjects are used. 565 566 dartel_version : boolean, optional 567 Whether or not to use data normalized with DARTEL instead of standard 568 SPM8 normalization. Default=True. 569 %(data_dir)s 570 %(url)s 571 %(resume)s 572 %(verbose)s 573 574 Returns 575 ------- 576 data : Bunch 577 Dictionary-like object, the interest attributes are : 578 579 - 'gray_matter_maps': string list 580 Paths to nifti gray matter density probability maps 581 - 'white_matter_maps' string list 582 Paths to nifti white matter density probability maps 583 - 'ext_vars': np.recarray 584 Data from the .csv file with information about selected subjects 585 - 'data_usage_agreement': string 586 Path to the .txt file containing the data usage agreement. 587 588 References 589 ---------- 590 .. footbibliography:: 591 592 Notes 593 ----- 594 In the DARTEL version, original Oasis data have been preprocessed 595 with the following steps: 596 597 1. Dimension swapping (technically required for subsequent steps) 598 2. Brain Extraction 599 3. Segmentation with SPM8 600 4. Normalization using DARTEL algorithm 601 5. Modulation 602 6. Replacement of NaN values with 0 in gray/white matter density maps. 603 7. Resampling to reduce shape and make it correspond to the shape of 604 the non-DARTEL data (fetched with dartel_version=False). 605 8. Replacement of values < 1e-4 with zeros to reduce the file size. 606 607 In the non-DARTEL version, the following steps have been performed instead: 608 609 1. Dimension swapping (technically required for subsequent steps) 610 2. Brain Extraction 611 3. Segmentation and normalization to a template with SPM8 612 4. Modulation 613 5. Replacement of NaN values with 0 in gray/white matter density maps. 614 615 An archive containing the gray and white matter density probability maps 616 for the 416 available subjects is provided. Gross outliers are removed and 617 filtered by this data fetcher (DARTEL: 13 outliers; non-DARTEL: 1 outlier) 618 Externals variates (age, gender, estimated intracranial volume, 619 years of education, socioeconomic status, dementia score) are provided 620 in a CSV file that is a copy of the original Oasis CSV file. The current 621 downloader loads the CSV file and keeps only the lines corresponding to 622 the subjects that are actually demanded. 623 624 The Open Access Structural Imaging Series (OASIS) is a project 625 dedicated to making brain imaging data openly available to the public. 626 Using data available through the OASIS project requires agreeing with 627 the Data Usage Agreement that can be found at 628 http://www.oasis-brains.org/app/template/UsageAgreement.vm 629 630 """ 631 # check number of subjects 632 if n_subjects is None: 633 n_subjects = 403 if dartel_version else 415 634 if dartel_version: # DARTEL version has 13 identified outliers 635 if n_subjects > 403: 636 warnings.warn('Only 403 subjects are available in the ' 637 'DARTEL-normalized version of the dataset. ' 638 'All of them will be used instead of the wanted %d' 639 % n_subjects) 640 n_subjects = 403 641 else: # all subjects except one are available with non-DARTEL version 642 if n_subjects > 415: 643 warnings.warn('Only 415 subjects are available in the ' 644 'non-DARTEL-normalized version of the dataset. ' 645 'All of them will be used instead of the wanted %d' 646 % n_subjects) 647 n_subjects = 415 648 if n_subjects < 1: 649 raise ValueError("Incorrect number of subjects (%d)" % n_subjects) 650 651 # pick the archive corresponding to preprocessings type 652 if url is None: 653 if dartel_version: 654 url_images = ('https://www.nitrc.org/frs/download.php/' 655 '6364/archive_dartel.tgz?i_agree=1&download_now=1') 656 else: 657 url_images = ('https://www.nitrc.org/frs/download.php/' 658 '6359/archive.tgz?i_agree=1&download_now=1') 659 # covariates and license are in separate files on NITRC 660 url_csv = ('https://www.nitrc.org/frs/download.php/' 661 '6348/oasis_cross-sectional.csv?i_agree=1&download_now=1') 662 url_dua = ('https://www.nitrc.org/frs/download.php/' 663 '6349/data_usage_agreement.txt?i_agree=1&download_now=1') 664 else: # local URL used in tests 665 url_csv = url + "/oasis_cross-sectional.csv" 666 url_dua = url + "/data_usage_agreement.txt" 667 if dartel_version: 668 url_images = url + "/archive_dartel.tgz" 669 else: 670 url_images = url + "/archive.tgz" 671 672 opts = {'uncompress': True} 673 674 # missing subjects create shifts in subjects ids 675 missing_subjects = [8, 24, 36, 48, 89, 93, 100, 118, 128, 149, 154, 676 171, 172, 175, 187, 194, 196, 215, 219, 225, 242, 677 245, 248, 251, 252, 257, 276, 297, 306, 320, 324, 678 334, 347, 360, 364, 391, 393, 412, 414, 427, 436] 679 680 if dartel_version: 681 # DARTEL produces outliers that are hidden by nilearn API 682 removed_outliers = [27, 57, 66, 83, 122, 157, 222, 269, 282, 287, 683 309, 428] 684 missing_subjects = sorted(missing_subjects + removed_outliers) 685 file_names_gm = [ 686 (os.path.join( 687 "OAS1_%04d_MR1", 688 "mwrc1OAS1_%04d_MR1_mpr_anon_fslswapdim_bet.nii.gz") 689 % (s, s), 690 url_images, opts) 691 for s in range(1, 457) if s not in missing_subjects][:n_subjects] 692 file_names_wm = [ 693 (os.path.join( 694 "OAS1_%04d_MR1", 695 "mwrc2OAS1_%04d_MR1_mpr_anon_fslswapdim_bet.nii.gz") 696 % (s, s), 697 url_images, opts) 698 for s in range(1, 457) if s not in missing_subjects] 699 else: 700 # only one gross outlier produced, hidden by nilearn API 701 removed_outliers = [390] 702 missing_subjects = sorted(missing_subjects + removed_outliers) 703 file_names_gm = [ 704 (os.path.join( 705 "OAS1_%04d_MR1", 706 "mwc1OAS1_%04d_MR1_mpr_anon_fslswapdim_bet.nii.gz") 707 % (s, s), 708 url_images, opts) 709 for s in range(1, 457) if s not in missing_subjects][:n_subjects] 710 file_names_wm = [ 711 (os.path.join( 712 "OAS1_%04d_MR1", 713 "mwc2OAS1_%04d_MR1_mpr_anon_fslswapdim_bet.nii.gz") 714 % (s, s), 715 url_images, opts) 716 for s in range(1, 457) if s not in missing_subjects] 717 file_names_extvars = [("oasis_cross-sectional.csv", url_csv, {})] 718 file_names_dua = [("data_usage_agreement.txt", url_dua, {})] 719 # restrict to user-specified number of subjects 720 file_names_gm = file_names_gm[:n_subjects] 721 file_names_wm = file_names_wm[:n_subjects] 722 723 file_names = (file_names_gm + file_names_wm + 724 file_names_extvars + file_names_dua) 725 dataset_name = 'oasis1' 726 data_dir = _get_dataset_dir(dataset_name, data_dir=data_dir, 727 verbose=verbose) 728 files = _fetch_files(data_dir, file_names, resume=resume, 729 verbose=verbose) 730 731 # Build Bunch 732 gm_maps = files[:n_subjects] 733 wm_maps = files[n_subjects:(2 * n_subjects)] 734 ext_vars_file = files[-2] 735 data_usage_agreement = files[-1] 736 737 # Keep CSV information only for selected subjects 738 csv_data = np.recfromcsv(ext_vars_file) 739 # Comparisons to recfromcsv data must be bytes. 740 actual_subjects_ids = [("OAS1" + 741 str.split(os.path.basename(x), 742 "OAS1")[1][:9]).encode() 743 for x in gm_maps] 744 subject_mask = np.asarray([subject_id in actual_subjects_ids 745 for subject_id in csv_data['id']]) 746 csv_data = csv_data[subject_mask] 747 748 fdescr = _get_dataset_descr(dataset_name) 749 750 return Bunch( 751 gray_matter_maps=gm_maps, 752 white_matter_maps=wm_maps, 753 ext_vars=csv_data, 754 data_usage_agreement=data_usage_agreement, 755 description=fdescr) 756 757 758@fill_doc 759def fetch_surf_fsaverage(mesh='fsaverage5', data_dir=None): 760 """Download a Freesurfer fsaverage surface. 761 File names are subject to change and only attribute names 762 are guaranteed to be stable across nilearn versions. 763 See :footcite:`Fischl1999neurons`. 764 765 Parameters 766 ---------- 767 mesh : str, optional 768 Which mesh to fetch. Should be one of the following values: 769 %(fsaverage_options)s 770 Default='fsaverage5'. 771 %(data_dir)s 772 773 Returns 774 ------- 775 data : sklearn.datasets.base.Bunch 776 Dictionary-like object, the interest attributes are : 777 - 'area_left': Gifti file, left hemisphere area data 778 - 'area_right': Gifti file, right hemisphere area data 779 - 'curv_left': Gifti file, left hemisphere curvature data 780 - 'curv_right': Gifti file, right hemisphere curvature data 781 - 'pial_left': Gifti file, left hemisphere pial surface mesh 782 - 'pial_right': Gifti file, right hemisphere pial surface mesh 783 - 'infl_left': Gifti file, left hemisphere inflated pial surface mesh 784 - 'infl_right': Gifti file, right hemisphere inflated pial 785 surface mesh 786 - 'sphere_left': Gifti file, left hemisphere sphere surface mesh 787 - 'sphere_right': Gifti file, right hemisphere sphere surface mesh 788 - 'sulc_left': Gifti file, left hemisphere sulcal depth data 789 - 'sulc_right': Gifti file, right hemisphere sulcal depth data 790 - 'thick_left': Gifti file, left hemisphere cortical thickness data 791 - 'thick_right': Gifti file, right hemisphere cortical thickness data 792 - 'white_left': Gifti file, left hemisphere white surface mesh 793 - 'white_right': Gifti file, right hemisphere white surface mesh 794 795 References 796 ---------- 797 .. footbibliography:: 798 799 """ 800 available_meshes = [ 801 "fsaverage3", "fsaverage4", "fsaverage5", "fsaverage5_sphere", 802 "fsaverage6", "fsaverage7", "fsaverage", 803 ] 804 805 # Call a dataset loader depending on the value of mesh 806 if ( 807 mesh == "fsaverage3" 808 or mesh == "fsaverage4" 809 or mesh == "fsaverage6" 810 or mesh == "fsaverage7" 811 or mesh == "fsaverage" 812 ): 813 # rename mesh to "fsaverage" to download it once 814 # regardless of whether mesh equals "fsaverage" or "fsaverage7" 815 if mesh == "fsaverage7": 816 mesh = "fsaverage" 817 818 return _fetch_surf_fsaverage(mesh, data_dir=data_dir) 819 elif mesh == "fsaverage5": 820 return _fetch_surf_fsaverage5() 821 elif mesh == "fsaverage5_sphere": 822 warnings.warn( 823 "mesh='fsaverage5_sphere' has been deprecated " 824 "and will be removed in v0.9.0.\n" 825 "fsaverage5 sphere coordinates can now be accessed through " 826 "attributes sphere_{left, right} using mesh='fsaverage5'" 827 ) 828 return _fetch_surf_fsaverage5() 829 else: 830 raise ValueError( 831 "'mesh' should be one of {}; {!r} was provided".format( 832 available_meshes, mesh 833 ) 834 ) 835 836 837def _fetch_surf_fsaverage5(): 838 """Helper function to ship fsaverage5 surfaces and sulcal information 839 with Nilearn. 840 841 The source of the data is coming from nitrc based on this PR #1016. 842 Manually downloaded gzipped and shipped with this function. 843 844 Shipping is done with Nilearn based on issue #1705. 845 846 """ 847 data_dir = Path(FSAVERAGE5_PATH) 848 849 data = { 850 "{}_{}".format(part, hemi): str( 851 data_dir / "{}_{}.gii.gz".format(part, hemi) 852 ) 853 for part in [ 854 "area", "curv", "infl", "pial", 855 "sphere", "sulc", "thick", "white" 856 ] 857 for hemi in ["left", "right"] 858 } 859 data["description"] = _get_dataset_descr("fsaverage5") 860 861 return Bunch(**data) 862 863 864def _fetch_surf_fsaverage(dataset_name, data_dir=None): 865 """Helper function to ship fsaverage{3,4,6,7} meshes. 866 867 These meshes can be used for visualization purposes, but also to run 868 cortical surface-based searchlight decoding. 869 870 The source of the data is downloaded from OSF. 871 """ 872 dataset_dir = _get_dataset_dir(dataset_name, data_dir=data_dir) 873 opts = {'uncompress': True} 874 875 url = { 876 "fsaverage3": "https://osf.io/asvjk/download", 877 "fsaverage4": "https://osf.io/x2j49/download", 878 "fsaverage6": "https://osf.io/um5ag/download", 879 "fsaverage": "https://osf.io/q7a5k/download", # fsaverage7 880 }[dataset_name] 881 882 # List of attributes exposed by the dataset 883 dataset_attributes = [ 884 "{}_{}".format(part, hemi) 885 for part in [ 886 "area", "curv", "infl", "pial", 887 "sphere", "sulc", "thick", "white" 888 ] 889 for hemi in ["left", "right"] 890 ] 891 892 # Note that the file names match the attribute's 893 _fetch_files( 894 dataset_dir, 895 [ 896 ("{}.gii.gz".format(attribute), url, opts) 897 for attribute in dataset_attributes 898 ] 899 ) 900 901 result = { 902 attribute: os.path.join(dataset_dir, "{}.gii.gz".format(attribute)) 903 for attribute in dataset_attributes 904 } 905 result["description"] = str(_get_dataset_descr(dataset_name)) 906 907 return Bunch(**result) 908