Skip to content

Commit 4e5e5fe

Browse files
committed
ENH: modified slicer3d plugin to load multi-volume datasets
Adds ability to load multiple volumes per sample or load sequence data depending on request Signed-off-by: Cavan Riley <cavan-riley@uiowa.edu>
1 parent 4a574ae commit 4e5e5fe

1 file changed

Lines changed: 51 additions & 8 deletions

File tree

plugins/slicer/MONAILabel/MONAILabel.py

Lines changed: 51 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1303,19 +1303,62 @@ def onNextSampleButton(self):
13031303
return
13041304

13051305
logging.info(sample)
1306-
image_id = sample["id"]
1306+
id = sample["id"]
13071307
image_file = sample.get("path")
1308-
image_name = sample.get("name", image_id)
1309-
node_name = sample.get("PatientID", sample.get("name", image_id))
1308+
image_name = sample.get("name", id)
1309+
node_name = sample.get("PatientID", sample.get("name", id))
13101310
checksum = sample.get("checksum")
13111311
local_exists = image_file and os.path.exists(image_file)
1312+
multichannel: bool = bool(sample.get("multichannel", False))
1313+
multi_file: bool = bool(sample.get("multi_file", False))
13121314

13131315
logging.info(f"Check if file exists/shared locally: {image_file} => {local_exists}")
13141316
if local_exists:
1315-
self._volumeNode = slicer.util.loadVolume(image_file)
1316-
self._volumeNode.SetName(node_name)
1317+
if multichannel:
1318+
# For 4D multichannel images, NOTE: slicer does not like 4D nifti images
1319+
# from https://github.com/Project-MONAI/MONAILabel/issues/241#issuecomment-1497788857
1320+
volumeSequenceNode = slicer.util.loadSequence(image_file)
1321+
volumeSequenceNode.SetName(node_name)
1322+
# Get a volume node
1323+
browserNode = slicer.modules.sequences.logic().GetFirstBrowserNodeForSequenceNode(
1324+
volumeSequenceNode
1325+
)
1326+
browserNode.SetOverwriteProxyName(
1327+
None, True
1328+
) # set the proxy node name based on the sequence node name
1329+
self._volumeNode = browserNode.GetProxyNode(volumeSequenceNode)
1330+
else:
1331+
if not multi_file:
1332+
self._volumeNode = slicer.util.loadVolume(image_file)
1333+
self._volumeNode.SetName(node_name)
1334+
else: # in the case the underlying dataset is multi_file, we load all the images in the directory
1335+
dir_path = image_file
1336+
if not os.path.isdir(dir_path):
1337+
raise ValueError(f"multi_file=True but path is not a directory: {dir_path}")
1338+
1339+
# get valid image paths
1340+
entries = sorted(os.listdir(dir_path))
1341+
image_paths = []
1342+
for name in entries:
1343+
full_path = os.path.join(dir_path, name)
1344+
if os.path.isfile(full_path) and name.lower().endswith((".nii", ".nii.gz", ".nrrd")):
1345+
image_paths.append(full_path)
1346+
1347+
if not image_paths:
1348+
raise ValueError(f"No loadable modality files found in: {dir_path}")
1349+
1350+
nodes = []
1351+
for image in image_paths:
1352+
image_base_name = os.path.basename(image)
1353+
node = slicer.util.loadVolume(image)
1354+
if node is None:
1355+
raise RuntimeError(f"Failed to load modality volume: {image}")
1356+
node.SetName(image_base_name)
1357+
nodes.append(node)
1358+
1359+
self._volumeNode = nodes[0]
13171360
else:
1318-
download_uri = f"{self.serverUrl()}/datastore/image?image={quote_plus(image_id)}"
1361+
download_uri = f"{self.serverUrl()}/datastore/image?image={quote_plus(id)}"
13191362
logging.info(download_uri)
13201363

13211364
sampleDataLogic = SampleData.SampleDataLogic()
@@ -1326,7 +1369,7 @@ def onNextSampleButton(self):
13261369
if slicer.util.settingsValue("MONAILabel/originalLabel", True, converter=slicer.util.toBool):
13271370
try:
13281371
datastore = self.logic.datastore()
1329-
label_info = datastore["objects"][image_id]["labels"]["original"]["info"]
1372+
label_info = datastore["objects"][id]["labels"]["original"]["info"]
13301373
labels = label_info.get("params", {}).get("label_names", {})
13311374

13321375
if labels:
@@ -1338,7 +1381,7 @@ def onNextSampleButton(self):
13381381
labels = self.logic.info().get("labels")
13391382

13401383
# ext = datastore['objects'][image_id]['labels']['original']['ext']
1341-
maskFile = self.logic.download_label(image_id, "original")
1384+
maskFile = self.logic.download_label(id, "original")
13421385
self.updateSegmentationMask(maskFile, list(labels))
13431386
print("Original label uploaded! ")
13441387

0 commit comments

Comments
 (0)