a b/utils/brainweb_download.py
1
from dataclasses import dataclass
2
from pathlib import Path
3
4
import numpy as np
5
import requests
6
from nibabel import load, save, Nifti1Image
7
from tqdm import tqdm
8
9
10
@dataclass
11
class Item:
12
    url: str
13
    path: str
14
    severity: str
15
16
17
def _download(url: str, data: str, fname: str):
18
    resp = requests.post(url, data=data, stream=True)
19
    total = int(resp.headers.get('content-length', 0))
20
    with open(fname, 'wb') as file, tqdm(
21
            desc=fname,
22
            total=total,
23
            unit='iB',
24
            unit_scale=True,
25
            unit_divisor=1024,
26
    ) as bar:
27
        for data in resp.iter_content(chunk_size=1024):
28
            size = file.write(data)
29
            bar.update(size)
30
31
32
def _download_and_convert(
33
        url: str, fname: Path, alias: str, name: str, institution: str,
34
        email: str, force_update: bool = False
35
):
36
    minc_fname = fname.with_suffix('.mnc.gz')
37
    fname.parent.mkdir(parents=True, exist_ok=True)
38
    if minc_fname.exists() and not force_update:
39
        print(
40
            f"Skipping {str(minc_fname)} download, "
41
            f"since it already exists."
42
        )
43
    else:
44
        _download(
45
            url=url,
46
            data=f'do_download_alias={alias}'
47
                 f'&format_value=minc'
48
                 f'&zip_value=gnuzip'
49
                 f'&who_name={name}'
50
                 f'&who_institution={institution}'
51
                 f'&who_email={email}'
52
                 f'&download_for_real=%5BStart+download%21%5D',
53
            fname=str(minc_fname)
54
        )
55
    nii_fname = fname.with_suffix('.nii.gz')
56
    if nii_fname.exists() and not force_update:
57
        print(
58
            f"Skipping conversion of {str(minc_fname)}, "
59
            f"since {str(nii_fname)} already exists."
60
        )
61
    else:
62
        try:
63
            minc = load(minc_fname)
64
            affine = np.array([[0, 0, 1, 0],
65
                               [0, 1, 0, 0],
66
                               [1, 0, 0, 0],
67
                               [0, 0, 0, 1]])
68
            out = Nifti1Image(minc.get_fdata(), affine=affine)
69
            save(out, nii_fname)
70
            print(f'Successfully converted to {str(nii_fname)}')
71
        except Exception as e:
72
            print(e)
73
74
75
def _download_data(base_dir, name, institution, email):
76
    modality = 'T2'
77
    slice_thickness = '1mm'
78
    noise_levels = ['pn0', 'pn1', 'pn3', 'pn5']
79
    intensity_non_uniformities = ['rf0', 'rf20', 'rf40']
80
    severities = [
81
        Item(
82
            url='https://brainweb.bic.mni.mcgill.ca/cgi/brainweb2',
83
            path='lesions/severe',
84
            severity='AI+msles2'
85
        ),
86
        Item(
87
            url='https://brainweb.bic.mni.mcgill.ca/cgi/brainweb1',
88
            path='normal',
89
            severity='ICBM+normal'
90
        )
91
    ]
92
93
    for item in severities:
94
        out_dir = (base_dir / item.path)
95
        for noise_level in noise_levels:
96
            for intensity_non_uniformity in intensity_non_uniformities:
97
                alias = f"{modality}+{item.severity}+{slice_thickness}+{noise_level}+{intensity_non_uniformity}"
98
                fname = out_dir / alias.replace("+", "_").lower()
99
                _download_and_convert(
100
                    url=item.url,
101
                    fname=fname,
102
                    alias=alias,
103
                    name=name,
104
                    institution=institution,
105
                    email=email
106
                )
107
108
109
def _download_labels(base_dir, name, institution, email):
110
    items = [
111
        Item(
112
            url="https://brainweb.bic.mni.mcgill.ca/cgi/brainweb1",
113
            path="normal",
114
            severity="phantom_1.0mm_normal_crisp"
115
        ),  # normal
116
        Item(
117
            url="https://brainweb.bic.mni.mcgill.ca/cgi/brainweb2",
118
            path="severe_lesions",
119
            severity="phantom_1.0mm_msles3_crisp"
120
        )  # severe
121
    ]
122
123
    gt_dir = (base_dir / 'groundtruth')
124
    for item in items:
125
        _download_and_convert(
126
            url=item.url,
127
            fname=gt_dir / item.path,
128
            alias=item.severity,
129
            name=name,
130
            institution=institution,
131
            email=email
132
        )
133
134
135
def download_brainweb_dataset(
136
        # default path for google colab example
137
        base_dir: Path = Path('/content/data/Brainweb'),
138
        name: str = "",
139
        institution: str = "",
140
        email: str = "",
141
):
142
    _download_data(base_dir, name, institution, email)
143
    _download_labels(base_dir, name, institution, email)