-
Notifications
You must be signed in to change notification settings - Fork 0
/
utils.py
96 lines (76 loc) · 3.89 KB
/
utils.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
import os
import re
from pathlib import Path
import cc3d
import numpy as np
## Variables
CONTRAST = {'t1': ['T1w'],
't2': ['T2w'],
't2s':['T2star'],
't1_t2': ['T1w', 'T2w'],
'psir': ['PSIR'],
'stir': ['STIR'],
'psir_stir': ['PSIR', 'STIR'],
't1_t2_psir_stir': ['T1w', 'T2w', 'PSIR', 'STIR']
}
## Functions
def get_img_path_from_label_path(str_path):
"""
This function does 2 things: ⚠️ Files need to be stored in a BIDS compliant dataset
- Step 1: Remove label suffix (e.g. "_labels-disc-manual"). The suffix is always between the MRI contrast and the file extension.
- Step 2: Remove derivatives path (e.g. derivatives/labels/). The first folders is always called derivatives but the second may vary (e.g. labels_soft)
:param path: absolute path to the label img. Example: /<path_to_BIDS_data>/derivatives/labels/sub-amuALT/anat/sub-amuALT_T1w_labels-disc-manual.nii.gz
:return: img path. Example: /<path_to_BIDS_data>/sub-amuALT/anat/sub-amuALT_T1w.nii.gz
Copied from https://github.com/spinalcordtoolbox/disc-labeling-hourglass
"""
# Load path
path = Path(str_path)
# Extract file extension
ext = ''.join(path.suffixes)
# Get img name
img_name = '_'.join(path.name.split('_')[:-1]) + ext
# Create a list of the directories
dir_list = str(path.parent).split('/')
# Remove "derivatives" and "labels" folders
derivatives_idx = dir_list.index('derivatives')
dir_path = '/'.join(dir_list[0:derivatives_idx] + dir_list[derivatives_idx+2:])
# Recreate img path
img_path = os.path.join(dir_path, img_name)
return img_path
def fetch_subject_and_session(filename_path):
"""
Get subject ID, session ID and filename from the input BIDS-compatible filename or file path
The function works both on absolute file path as well as filename
:param filename_path: input nifti filename (e.g., sub-001_ses-01_T1w.nii.gz) or file path
(e.g., /home/user/MRI/bids/derivatives/labels/sub-001/ses-01/anat/sub-001_ses-01_T1w.nii.gz
:return: subjectID: subject ID (e.g., sub-001)
:return: sessionID: session ID (e.g., ses-01)
:return: filename: nii filename (e.g., sub-001_ses-01_T1w.nii.gz)
Copied from https://github.com/spinalcordtoolbox/manual-correction
"""
_, filename = os.path.split(filename_path) # Get just the filename (i.e., remove the path)
subject = re.search('sub-(.*?)[_/]', filename_path) # [_/] means either underscore or slash
subjectID = subject.group(0)[:-1] if subject else "" # [:-1] removes the last underscore or slash
session = re.search('ses-(.*?)[_/]', filename_path) # [_/] means either underscore or slash
sessionID = session.group(0)[:-1] if session else "" # [:-1] removes the last underscore or slash
# REGEX explanation
# . - match any character (except newline)
# *? - match the previous element as few times as possible (zero or more times)
contrast = 'dwi' if 'dwi' in filename_path else 'anat' # Return contrast (dwi or anat)
return subjectID, sessionID, filename, contrast
def fetch_contrast(filename_path):
'''
Extract MRI contrast from a BIDS-compatible filename/filepath
The function handles images only.
:param filename_path: image file path or file name. (e.g sub-001_ses-01_T1w.nii.gz)
Copied from https://github.com/spinalcordtoolbox/disc-labeling-hourglass
'''
return filename_path.rstrip(''.join(Path(filename_path).suffixes)).split('_')[-1]
def extract_centroids_3D(arr):
'''
Extract centroids from a 3D numpy array
:param arr: 3D numpy array
'''
centroids = cc3d.statistics(cc3d.connected_components(arr))['centroids'][1:] # Remove backgroud <0>
centroids_sorted = centroids[np.argsort(centroids[:,1])] # Sort according to the vertical axis
return centroids_sorted.astype(int)