Skip to content

Commit df3beaf

Browse files
Add dice and jaccard to postprocessing
1 parent ed44a7e commit df3beaf

File tree

5 files changed

+88
-8
lines changed

5 files changed

+88
-8
lines changed

README.md

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,24 @@ See https://github.com/Inria-Empenn/fmri_feature_model/tree/master
1111

1212
# Describe your data
1313

14-
14+
Modify `data_desc_sample.json` to your usage
1515

1616
# Run configurations
1717

1818
- Run configurations list from `/config.csv` file.
1919
- Read data from `/data`
2020
- Write NiPype cache in `/workdir`
21-
- Write results in `/results`
21+
- Write results to `/results`
2222

2323
## Locally
2424
Change `/local/path/to/...` to your local paths
2525
``` sh
2626
docker run -u root -v "/local/path/to/data:/data" -v "/local/path/to/results:/results" -v "/local/path/to/workdir:/work" -v "/local/path/to/configs:/configs" fmri-conf-runner python -u run.py --configs "/configs/config.csv" --data /data/data_desc.json --ref /configs/config_ref.csv
2727
```
2828
## On Abaca (Inria cluster)
29+
30+
Use `run_configs.sh`
31+
2932
- Start 40 jobs in parallel.
3033
- Timeout for each job is 4h
3134
- Needs 40 configurations named CSV `config_[1..40].csv`
@@ -34,9 +37,19 @@ oarsub -S -n fmri-conf-runner ./run_configs.sh
3437
```
3538

3639
# Postprocess data
40+
- Read data from `/results`
41+
- Write results to `/results`
42+
- 'mean_result.nii' : mean statistic map
43+
- 'correlations.csv' : pairwise correlations
44+
- 'dataset.csv' :
3745
## Locally
3846
Change `/local/path/to/...` to your local paths
3947
``` sh
4048
docker run -u root -v "/local/path/to/results:/results" fmri-conf-runner python -u postprocess.py --results "/results"
4149
```
4250
## On Abaca (Inria cluster)
51+
52+
On Abaca (Inria cluster), use `postprocess.sh`
53+
``` sh
54+
oarsub -S -n postprocess ./postprocess.sh
55+
```

data_desc_hcp_motor.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"data_path" : "/home/user/fmri-feature-model/data/auditory",
3+
"input" : {
4+
"anat" : "sub-{subject_id}/anat/sub-{subject_id}_T1w.nii",
5+
"func" : "sub-{subject_id}/func/sub-{subject_id}_task-auditory_bold.nii",
6+
"events" : "sub-{subject_id}/func/sub-{subject_id}_task-auditory_events_corrected.tsv"
7+
},
8+
"result_path" : "/home/user/fmri-conf-runner/results",
9+
"work_path" : "/home/user/fmri-conf-runner/work",
10+
"task" : "auditory",
11+
"subjects" : ["01"],
12+
"slices_nb" : 64,
13+
"tr" : 7.0,
14+
"units" : "scans"
15+
}
File renamed without changes.

postprocess/correlation_service.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,55 @@ def get_correlation_coefficient(self,
5656
return corrcoef(data_1, data_2)[0][1]
5757
if method == 'spearman':
5858
return spearmanr(data_1, data_2).correlation
59+
if method == 'dice':
60+
return self.get_dice(data_1, data_2)
61+
if method == 'jaccard':
62+
return self.get_jaccard(data_1, data_2)
5963

6064
raise AttributeError(f'Wrong correlation method provided: {method}.')
6165

66+
def get_dice(self, data_1: np.ndarray, data_2: np.ndarray) -> float:
67+
"""
68+
Return the DICE score between two images data
69+
:param data_1:
70+
:param data_2:
71+
:return:
72+
"""
73+
# Binarize
74+
binary1 = data_1 > 0
75+
binary2 = data_2 > 0
76+
77+
# Compute intersection + volumes
78+
intersection = np.logical_and(binary1, binary2).sum()
79+
volume = binary1.sum() + binary2.sum()
80+
81+
# Avoid divide by 0
82+
if volume == 0:
83+
return 0.0
84+
85+
return (2. * intersection) / volume
86+
87+
def get_jaccard(self, data_1: np.ndarray, data_2: np.ndarray) -> float:
88+
"""
89+
Return the Jaccard Index between two images data
90+
:param data_1:
91+
:param data_2:
92+
:return:
93+
"""
94+
# Binarize
95+
binary1 = data_1 > 0
96+
binary2 = data_2 > 0
97+
98+
# Compute intersection + union
99+
intersection = np.logical_and(binary1, binary2).sum()
100+
union = np.logical_or(binary1, binary2).sum()
101+
102+
# Avoid division by zero
103+
if union == 0:
104+
return 0.0
105+
106+
return intersection / union
107+
62108
def mask_using_zeros(self, data_image: Nifti1Image) -> Nifti1Image:
63109
""" Mask an image by replacing NaNs with zeros.
64110

postprocess/postprocess_service.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,20 +40,26 @@ def get_all_correlations(self, path, ids: List[str]) -> pd.DataFrame:
4040
for j in range(i, n):
4141
if i == j:
4242
corr = 1.0
43+
dice = 1.0
44+
jacc = 1.0
4345
else:
4446
tgt = os.path.join(path, ids[j], '_subject_id_01', 'result.nii')
4547
corr = self.corr_srv.get_correlation_coefficient(src, tgt, 'spearman')
46-
data.append((ids[i], ids[j], corr))
48+
dice = self.corr_srv.get_correlation_coefficient(src, tgt, 'dice')
49+
jacc = self.corr_srv.get_correlation_coefficient(src, tgt, 'jaccard')
50+
data.append((ids[i], ids[j], corr, dice))
4751
if i != j:
48-
data.append((ids[j], ids[i], corr))
52+
data.append((ids[j], ids[i], corr, dice, jacc))
4953
# Add correlation from mean
5054
mean = os.path.join(path, 'mean_result.nii')
5155
corr = self.corr_srv.get_correlation_coefficient(src, mean, 'spearman')
52-
data.append((ids[i], 'mean', corr))
53-
data.append(('mean', ids[i], corr))
56+
dice = self.corr_srv.get_correlation_coefficient(src, tgt, 'dice')
57+
jacc = self.corr_srv.get_correlation_coefficient(src, tgt, 'jaccard')
58+
data.append((ids[i], 'mean', corr, dice, jacc))
59+
data.append(('mean', ids[i], corr, dice, jacc))
5460
print(f"Processed correlations for [{i+1} / {n}] result")
55-
data.append(('mean', 'mean', 1.0))
56-
dataframe = pd.DataFrame(data, columns=['source', 'target', 'correlation'])
61+
data.append(('mean', 'mean', 1.0, 1.0, 1.0))
62+
dataframe = pd.DataFrame(data, columns=['source', 'target', 'spearman', 'dice', 'jaccard'])
5763
return dataframe.sort_values(by='correlation', ascending=False)
5864

5965
def get_mean_image(self, inputs: list, batch_size: int) -> nib.Nifti1Image:

0 commit comments

Comments
 (0)