-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add update for dseg/rtstruct [WIP] (#99)
@LennyN95 PR'ing early for feedback --------- Signed-off-by: Suraj <[email protected]>
- Loading branch information
Showing
12 changed files
with
246 additions
and
125 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,22 +1,34 @@ | ||
general: | ||
data_base_dir: /app/data | ||
version: 1.0 | ||
description: FMCIB pipeline starting from DICOM files and centroids in json files or slicer exports named by their SeriesInstanceUID | ||
description: Run fmcib radiomics pipeline on dicom data | ||
|
||
execute: | ||
- DicomImporter | ||
- FileImporter | ||
- DsegExtractor | ||
- NiftiConverter | ||
- CentroidExtractor | ||
- FMCIBRunner | ||
- DataOrganizer | ||
|
||
modules: | ||
DicomImporter: | ||
source_dir: input_data | ||
import_dir: sorted_data | ||
sort_data: true | ||
merge: true | ||
meta: | ||
mod: '%Modality' | ||
desc: '%SeriesDescription' | ||
|
||
FileImporter: | ||
instance_id: sid | ||
meta: type=fmcibcoordinates | ||
type: json | ||
# roi can be specified manually but will otherwise extracted form the dicomseg via the meta.json | ||
# DsegExtractor: | ||
# roi: | ||
# - LIVER | ||
# - LIVER+NEOPLASM_MALIGNANT_PRIMARY | ||
|
||
DataOrganizer: | ||
targets: | ||
- json:type=fmcibfeatures-->[i:sid]/features.json | ||
- csv-->[i:sid]/features.csv | ||
# - nifit:mod=seg:origin=dicomseg-->[i:sid]/masks/[basename] | ||
# - nifti-->[i:sid]/nifti/[d:mod]/[basename] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
general: | ||
data_base_dir: /app/data | ||
version: 1.0 | ||
description: FMCIB pipeline starting from DICOM files and centroids in json files or slicer exports named by their SeriesInstanceUID | ||
|
||
execute: | ||
- DicomImporter | ||
- FileImporter | ||
- NiftiConverter | ||
- FMCIBRunner | ||
- DataOrganizer | ||
|
||
modules: | ||
|
||
FileImporter: | ||
instance_id: sid | ||
meta: type=fmcibcoordinates | ||
type: json | ||
|
||
DataOrganizer: | ||
targets: | ||
- csv-->[i:sid]/features.csv |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
general: | ||
data_base_dir: /app/data | ||
version: 1.0 | ||
description: "FMCIB pipeline starting from a nii.gz file image and a binary mask of the GTV." | ||
|
||
execute: | ||
- FileStructureImporter | ||
- CentroidExtractor | ||
- FMCIBRunner | ||
- DataOrganizer | ||
|
||
modules: | ||
FileStructureImporter: | ||
structures: | ||
- $patientID/CT.nii.gz@instance@nifti:mod=ct | ||
- $patientID/masks/GTV.nii.gz@nifti:mod=seg | ||
import_id: patientID | ||
|
||
DataOrganizer: | ||
targets: | ||
- csv-->[i:patientID]/features.csv |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
general: | ||
data_base_dir: /app/data | ||
version: 1.0 | ||
description: run pyradiomics pipeline on dicom data | ||
|
||
execute: | ||
- DicomImporter | ||
- RTStructExtractor | ||
- NiftiConverter | ||
- CentroidExtractor | ||
- FMCIBRunner | ||
- DataOrganizer | ||
|
||
modules: | ||
DicomImporter: | ||
source_dir: input_data | ||
import_dir: sorted_data | ||
sort_data: true | ||
merge: true | ||
meta: | ||
mod: '%Modality' | ||
desc: '%SeriesDescription' | ||
|
||
# roi can be specified manually but will otherwise extracted form the rtstruct segemnetation names | ||
# RTStructExtractor: | ||
# roi: | ||
# - LIVER | ||
# - LIVER+NEOPLASM_MALIGNANT_PRIMARY | ||
|
||
DataOrganizer: | ||
targets: | ||
- csv-->[i:sid]/features.csv | ||
# - nifti-->[i:sid]/nifti/[d:mod]/[basename] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
[model.deployment] | ||
test = "https://zenodo.org/record/13785615/files/fmcib_radiomics.test.zip" | ||
test = "https://zenodo.org/records/14205464/files/test.zip" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,43 +1,58 @@ | ||
""" | ||
--------------------------------------------------------- | ||
Author: Leonard Nürnberg | ||
Email: [email protected] | ||
Author: Leonard Nürnberg, Suraj Pai | ||
Email: [email protected], [email protected] | ||
Date: 06.03.2024 | ||
--------------------------------------------------------- | ||
""" | ||
|
||
import json, jsonschema | ||
from mhubio.core import Instance, InstanceData, IO, Module | ||
from mhubio.core import Instance, InstanceData, InstanceDataCollection, IO, Module | ||
import SimpleITK as sitk | ||
import numpy as np | ||
|
||
class CentroidExtractor(Module): | ||
|
||
@IO.Instance() | ||
@IO.Input('in_mask', 'nrrd:mod=seg', the='Tumor segmentation mask for the input NRRD file.') | ||
@IO.Output('centroids_json', 'centroids.json', "json:type=fmcibcoordinates", the='JSON file containing 3D coordinates of the centroid of the input mask.') | ||
def task(self, instance: Instance, in_mask: InstanceData, centroids_json: InstanceData) -> None: | ||
|
||
# read the input mask | ||
mask = sitk.ReadImage(in_mask.abspath) | ||
|
||
# get the center of massk from the mask via ITK | ||
label_shape_filter = sitk.LabelShapeStatisticsImageFilter() | ||
label_shape_filter.Execute(mask) | ||
try: | ||
centroid = label_shape_filter.GetCentroid(255) | ||
except: | ||
centroid = label_shape_filter.GetCentroid(1) | ||
|
||
# extract x, y, and z coordinates from the centroid | ||
x, y, z = centroid | ||
|
||
# set up the coordinate dictionary | ||
coordinate_dict = { | ||
"coordX": x, | ||
"coordY": y, | ||
"coordZ": z, | ||
} | ||
|
||
# write the coordinate dictionary to a json file | ||
with open(centroids_json.abspath, "w") as f: | ||
json.dump(coordinate_dict, f) | ||
@IO.Inputs('in_masks', 'nrrd|nifti:mod=seg', the='Tumor segmentation masks for the input NRRD files') | ||
@IO.Outputs('centroid_jsons', '[filename].json', "json:type=fmcibcoordinates", data='in_masks', the='JSON file containing 3D coordinates of the centroid of the input mask.') | ||
def task(self, instance: Instance, in_masks: InstanceDataCollection, centroid_jsons: InstanceDataCollection) -> None: | ||
for i, in_mask in enumerate(in_masks): | ||
seg_rois = in_mask.type.meta['roi'].split(',') | ||
mask = sitk.ReadImage(in_mask.abspath) | ||
mask_array = sitk.GetArrayFromImage(mask) | ||
unique_values = np.unique(mask_array) | ||
print(f"Unique values: {unique_values}") | ||
label_shape_filter = sitk.LabelShapeStatisticsImageFilter() | ||
seg_roi_coordinates = [] | ||
|
||
for channel_id, seg_roi in enumerate(seg_rois): | ||
# Check if the label exists in the mask | ||
label = channel_id + 1 | ||
if label not in unique_values: | ||
print(f"Warning: Label {label} (ROI: {seg_roi}) not found in the mask. Skipping.") | ||
continue | ||
|
||
# Calculate centroid if the label exists | ||
label_shape_filter.Execute(mask) | ||
try: | ||
centroid = label_shape_filter.GetCentroid(label) | ||
# Extract x, y, and z coordinates from the centroid | ||
x, y, z = centroid | ||
|
||
# Set up the coordinate dictionary | ||
coordinate_dict = { | ||
"Mhub ROI": seg_roi, | ||
"coordX": x, | ||
"coordY": y, | ||
"coordZ": z, | ||
} | ||
|
||
seg_roi_coordinates.append(coordinate_dict) | ||
except Exception as e: | ||
print(f"Error processing label {label} (ROI: {seg_roi}): {e}") | ||
|
||
centroid_json = centroid_jsons.get(i) | ||
# Write the coordinate dictionary to a json file | ||
with open(centroid_json.abspath, "w") as f: | ||
json.dump(seg_roi_coordinates, f) |
Oops, something went wrong.