Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Improvement] Add lesions option in bundle/stats module #183

Merged
merged 3 commits into from
Sep 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 54 additions & 16 deletions modules/nf-scil/bundle/stats/main.nf
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,25 @@ process BUNDLE_STATS {
'scilus/scilus:2.0.2' }"

input:
tuple val(meta), path(bundles), path(labels_map), path(metrics)
tuple val(meta), path(bundles), path(labels_map), path(metrics), path(lesions)

output:
tuple val(meta), path("*_length_stats.json") , emit: length, optional: true
tuple val(meta), path("*_endpoints_map_raw.json") , emit: endpoints_raw, optional: true
tuple val(meta), path("*_endpoints_metric_stats.json") , emit: endpoints_metric_stats, optional: true
tuple val(meta), path("*_mean_std.json") , emit: mean_std, optional: true
tuple val(meta), path("*_volume.json") , emit: volume, optional: true
tuple val(meta), path("*_streamline_count.json") , emit: streamline_count, optional: true
tuple val(meta), path("*_volume_per_label.json") , emit: volume_per_labels, optional: true
tuple val(meta), path("*_mean_std_per_point.json") , emit: mean_std_per_point, optional: true
tuple val(meta), path("*_endpoints_map_head.nii.gz") , emit: endpoints_head, optional: true
tuple val(meta), path("*_endpoints_map_tail.nii.gz") , emit: endpoints_tail, optional: true
path "versions.yml" , emit: versions
tuple val(meta), path("*_length_stats.json") , emit: length, optional: true
tuple val(meta), path("*_endpoints_map_raw.json") , emit: endpoints_raw, optional: true
tuple val(meta), path("*_endpoints_metric_stats.json") , emit: endpoints_metric_stats, optional: true
tuple val(meta), path("*_mean_std.json") , emit: mean_std, optional: true
tuple val(meta), path("*_volume.json") , emit: volume, optional: true
tuple val(meta), path("*_volume_lesions.json") , emit: volume_lesions, optional: true
tuple val(meta), path("*_streamline_count.json") , emit: streamline_count, optional: true
tuple val(meta), path("*_streamline_count_lesions.json") , emit: streamline_count_lesions, optional: true
tuple val(meta), path("*_volume_per_label.json") , emit: volume_per_labels, optional: true
tuple val(meta), path("*_volume_per_label_lesions.json") , emit: volume_per_labels_lesions, optional: true
tuple val(meta), path("*_mean_std_per_point.json") , emit: mean_std_per_point, optional: true
tuple val(meta), path("*__lesion_stats.json") , emit: lesion_stats, optional: true
tuple val(meta), path("*_endpoints_map_head.nii.gz") , emit: endpoints_head, optional: true
tuple val(meta), path("*_endpoints_map_tail.nii.gz") , emit: endpoints_tail, optional: true
tuple val(meta), path("*_lesion_map.nii.gz") , emit: lesion_map, optional: true
path "versions.yml" , emit: versions

when:
task.ext.when == null || task.ext.when
Expand All @@ -34,6 +39,8 @@ process BUNDLE_STATS {
def endpoints = task.ext.endpoints ?: ""
def mean_std = task.ext.mean_std ?: ""
def volume = task.ext.volume ?: ""
def lesions_stats = task.ext.lesions_stats ?: ""
def min_lesion_vol = task.ext.min_lesion_vol ?: ""
def streamline_count = task.ext.streamline_count ?: ""
def volume_per_labels = task.ext.volume_per_labels ?: ""
def mean_std_per_point = task.ext.mean_std_per_point ?: ""
Expand All @@ -55,13 +62,13 @@ process BUNDLE_STATS {
if [[ "$endpoints" ]];
then
scil_bundle_compute_endpoints_map.py \${bundles[index]} \
\${bname}_endpoints_map_head.nii.gz \
\${bname}_endpoints_map_tail.nii.gz >\
${prefix}__\${bname}_endpoints_map_head.nii.gz \
${prefix}__\${bname}_endpoints_map_tail.nii.gz >\
${prefix}__\${bname}_endpoints_raw.json;

scil_volume_stats_in_ROI.py \${bname}_endpoints_map_head.nii.gz $normalize_weights\
scil_volume_stats_in_ROI.py ${prefix}__\${bname}_endpoints_map_head.nii.gz $normalize_weights\
--metrics \${b_metrics} > \${bname}_head.json
scil_volume_stats_in_ROI.py \${bname}_endpoints_map_tail.nii.gz $normalize_weights\
scil_volume_stats_in_ROI.py ${prefix}__\${bname}_endpoints_map_tail.nii.gz $normalize_weights\
--metrics \${b_metrics} > \${bname}_tail.json;

fi
Expand All @@ -76,6 +83,14 @@ process BUNDLE_STATS {
then
scil_bundle_shape_measures.py \${bundles[index]} > \${bname}_volume_stat.json

if [[ "$lesions_stats" ]];
then
scil_lesions_info.py $lesions \${bname}_volume_lesions_stat.json \
--bundle \${bundles[index]} --out_lesion_stats ${prefix}__lesion_stats.json \
--out_streamlines_stats \${bname}_streamline_count_lesions_stat.json \
--min_lesion_vol $min_lesion_vol -f
fi

elif [[ "$streamline_count" ]];
then
scil_tractogram_count_streamlines.py \${bundles[index]} > \${bname}_streamlines.json
Expand All @@ -85,6 +100,14 @@ process BUNDLE_STATS {
then
scil_bundle_volume_per_label.py \${label_map[index]} \$bname --sort_keys >\
\${bname}_volume_label.json

if [[ "$lesions_stats" ]];
then
scil_analyse_lesions_load.py $lesions \${bname}_volume_per_label_lesions_stat.json \
--bundle_labels_map \${label_map[index]} \
--out_lesion_atlas "${prefix}__\${bname}_lesion_map.nii.gz" \
--min_lesion_vol $min_lesion_vol
fi
fi

if [[ "$mean_std_per_point" ]];
Expand Down Expand Up @@ -125,6 +148,15 @@ process BUNDLE_STATS {
then
scil_json_merge_entries.py *_volume_stat.json ${prefix}_volume.json --no_list --add_parent_key ${prefix}

if [[ "$lesions_stats" ]];
then
scil_json_merge_entries.py *_volume_lesions_stat.json ${prefix}_volume_lesions.json --no_list --add_parent_key ${prefix}
scil_json_merge_entries.py *_streamline_count_lesions_stat.json ${prefix}_streamline_count_lesions.json \
--no_list --add_parent_key ${prefix}
scil_merge_json.py ${prefix}__lesion_stats.json ${prefix}__lesion_stats.json \
--remove_parent_key --add_parent_key ${prefix} -f
fi

#Bundle_Streamline_Count
elif [[ "$streamline_count" ]];
then
Expand All @@ -137,6 +169,12 @@ process BUNDLE_STATS {
then
scil_json_merge_entries.py *_volume_label.json ${prefix}_volume_per_label.json --no_list \
--add_parent_key ${prefix}

if [[ "$lesions_stats" ]];
then
scil_json_merge_entries.py *_volume_per_label_lesions_stat.json ${prefix}_volume_per_label_lesions.json \
--no_list --add_parent_key ${prefix}
fi
fi

#Bundle_Mean_Std_Per_Point
Expand Down
30 changes: 30 additions & 0 deletions modules/nf-scil/bundle/stats/meta.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@ input:
The metrics has to follow a specific naming convention.
pattern: "*_{bundle_name}_{metric_name}.nii.gz"

- lesions:
type: file
description: Nifti lesion volume to compute statistics on. The lesion mask must be a binary mask.
pattern: "*.nii.gz"

output:
- meta:
type: map
Expand Down Expand Up @@ -108,21 +113,41 @@ output:
description: Evaluate basic measurements of bundle(s).
pattern: "*__volume.json"

- volume_lesions:
type: file
description: Compute bundle volume in each lesions in mm3.
pattern: "*__volume_lesion.json"

- streamline_count:
type: file
description: Return the number of streamlines in a tractogram.
pattern: "*__streamline_count.json"

- streamline_count_lesions:
type: file
description: Return the number of streamlines in each lesions.
pattern: "*__streamline_count_lesions.json"

- volume_per_labels:
type: file
description: Compute bundle volume per label in mm3. This script supports anisotropic voxels resolution. Volume is estimated by counting the number of voxel occupied by each label and multiplying it by the volume of a single voxel.
pattern: "*__volume_per_label.json"

- volume_per_labels_lesions:
type: file
description: Compute bundle volume per label in each lesions in mm3.
pattern: "*__volume_per_label_lesions.json"

- mean_std_per_point:
type: file
description: Average the metric values of all voxels occupied by the bundle per label.
pattern: "*__mean_std_per_point.json"

- lesion_stats:
type: file
description: File of the lesion-wise volume measure.
pattern: "*_lesion_stats.json"

- endpoints_head:
type: file
description: Endpoint head map of bundle. The endpoint head map is simply a count of the number of streamlines that start in each voxel.
Expand All @@ -133,6 +158,11 @@ output:
description: Endpoint tail map of bundle. The endpoint tail map is simply a count of the number of streamlines that end in each voxel.
pattern: "*.nii.gz"

- lesion_map:
type: file
description: Nifti files of labelized lesion(s) map for each bundles.
pattern: "*.nii.gz"

- versions:
type: file
description: File containing software versions
Expand Down
34 changes: 27 additions & 7 deletions modules/nf-scil/bundle/stats/tests/main.nf.test
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,7 @@ nextflow_process {
}

test("bundle - stats") {

config "./nextflow.config"

when {
process {
"""
Expand All @@ -36,12 +34,12 @@ nextflow_process {
[ id:'test', single_end:false ], // meta map
file("\${test_data_directory}/IFGWM.trk"),
file("\${test_data_directory}/IFGWM_labels_map.nii.gz"),
file("\${test_data_directory}/mni_masked.nii.gz")
file("\${test_data_directory}/mni_masked.nii.gz"),
[]
]}
"""
}
}

then {
assertAll(
{ assert process.success },
Expand All @@ -51,9 +49,7 @@ nextflow_process {
}

test("bundle - stats - light") {

config "./nextflow_light.config"

when {
process {
"""
Expand All @@ -62,12 +58,36 @@ nextflow_process {
[ id:'test', single_end:false ], // meta map
file("\${test_data_directory}/IFGWM{,_color}.trk"),
file("\${test_data_directory}/IFGWM{_labels_map,}.nii.gz"),
file("\${test_data_directory}/mni_masked.nii.gz")
file("\${test_data_directory}/mni_masked.nii.gz"),
[]
]}
"""
}
}
then {
assertAll(
{ assert process.success },
{ assert snapshot(process.out).match() }
)
}
}

test("bundle - stats - lesions") {
config "./nextflow_lesions.config"
when {
process {
"""
input[0] = LOAD_DATA.out.test_data_directory.map{
test_data_directory -> [
[ id:'test', single_end:false ], // meta map
file("\${test_data_directory}/IFGWM.trk",),
file("\${test_data_directory}/IFGWM_labels_map.nii.gz"),
file("\${test_data_directory}/mni_masked.nii.gz"),
file("\${test_data_directory}/IFGWM.nii.gz")
]}
"""
}
}
then {
assertAll(
{ assert process.success },
Expand Down
Loading
Loading