Skip to content
Snippets Groups Projects
Commit fe74b961 authored by fima's avatar fima :beers:
Browse files

Merge branch 'load_nifti_files' into 'main'

Implemented nifti loader + possibility of accepting os.PathLike objects in qim3d.io.load()

See merge request !27
parents 4528c316 e2a425b2
No related branches found
No related tags found
1 merge request!27Implemented nifti loader + possibility of accepting os.PathLike objects in qim3d.io.load()
...@@ -4,11 +4,12 @@ import os ...@@ -4,11 +4,12 @@ import os
import difflib import difflib
import tifffile import tifffile
import h5py import h5py
import nibabel as nib
import numpy as np import numpy as np
from pathlib import Path from pathlib import Path
import qim3d import qim3d
from qim3d.io.logger import log from qim3d.io.logger import log
from qim3d.utils.internal_tools import sizeof from qim3d.utils.internal_tools import sizeof, stringify_path
from qim3d.utils.system import Memory from qim3d.utils.system import Memory
...@@ -20,7 +21,7 @@ class DataLoader: ...@@ -20,7 +21,7 @@ class DataLoader:
dataset_name (str): Specifies the name of the dataset to be loaded dataset_name (str): Specifies the name of the dataset to be loaded
(only relevant for HDF5 files) (only relevant for HDF5 files)
return_metadata (bool): Specifies if metadata is returned or not return_metadata (bool): Specifies if metadata is returned or not
(only relevant for HDF5 and TXRM/TXM/XRM files) (only relevant for HDF5, TXRM/TXM/XRM and NIfTI files)
contains (str): Specifies a part of the name that is common for the contains (str): Specifies a part of the name that is common for the
TIFF file stack to be loaded (only relevant for TIFF stacks) TIFF file stack to be loaded (only relevant for TIFF stacks)
...@@ -80,7 +81,7 @@ class DataLoader: ...@@ -80,7 +81,7 @@ class DataLoader:
Returns: Returns:
numpy.ndarray or tuple: The loaded volume as a NumPy array. numpy.ndarray or tuple: The loaded volume as a NumPy array.
If 'return_metadata' is True, returns a tuple (volume, metadata). If 'self.return_metadata' is True, returns a tuple (volume, metadata).
Raises: Raises:
ValueError: If the specified dataset_name is not found or is invalid. ValueError: If the specified dataset_name is not found or is invalid.
...@@ -214,7 +215,7 @@ class DataLoader: ...@@ -214,7 +215,7 @@ class DataLoader:
Returns: Returns:
numpy.ndarray or tuple: The loaded volume as a NumPy array. numpy.ndarray or tuple: The loaded volume as a NumPy array.
If 'return_metadata' is True, returns a tuple (volume, metadata). If 'self.return_metadata' is True, returns a tuple (volume, metadata).
Raises: Raises:
ValueError: If the dxchange library is not installed ValueError: If the dxchange library is not installed
...@@ -244,12 +245,40 @@ class DataLoader: ...@@ -244,12 +245,40 @@ class DataLoader:
else: else:
return vol return vol
def load_nifti(self,path):
"""Load a NIfTI file from the specified path.
Args:
path (str): The path to the NIfTI file.
Returns:
numpy.ndarray or tuple: The loaded volume as a NumPy array.
If 'self.return_metadata' is True, returns a tuple (volume, metadata).
"""
data = nib.load(path)
# Get image array proxy
vol = data.dataobj
if not self.virtual_stack:
vol = np.asarray(vol,dtype=data.get_data_dtype())
if self.return_metadata:
metadata = {}
for key in data.header:
metadata[key]=data.header[key]
return vol, metadata
else:
return vol
def load(self, path): def load(self, path):
""" """
Load a file or directory based on the given path. Load a file or directory based on the given path.
Args: Args:
path (str): The path to the file or directory. path (str or os.PathLike): The path to the file or directory.
Returns: Returns:
numpy.ndarray: The loaded volume as a NumPy array. numpy.ndarray: The loaded volume as a NumPy array.
...@@ -263,6 +292,8 @@ class DataLoader: ...@@ -263,6 +292,8 @@ class DataLoader:
data = loader.load("image.tif") data = loader.load("image.tif")
""" """
path = stringify_path(path)
# Load a file # Load a file
if os.path.isfile(path): if os.path.isfile(path):
# Choose the loader based on the file extension # Choose the loader based on the file extension
...@@ -272,6 +303,8 @@ class DataLoader: ...@@ -272,6 +303,8 @@ class DataLoader:
return self.load_h5(path) return self.load_h5(path)
elif path.endswith((".txrm", ".txm", ".xrm")): elif path.endswith((".txrm", ".txm", ".xrm")):
return self.load_txrm(path) return self.load_txrm(path)
elif path.endswith((".nii",".nii.gz")):
return self.load_nifti(path)
else: else:
raise ValueError("Unsupported file format") raise ValueError("Unsupported file format")
...@@ -312,7 +345,7 @@ def load( ...@@ -312,7 +345,7 @@ def load(
Load data from the specified file or directory. Load data from the specified file or directory.
Args: Args:
path (str): The path to the file or directory. path (str or os.PathLike): The path to the file or directory.
virtual_stack (bool, optional): Specifies whether to use virtual virtual_stack (bool, optional): Specifies whether to use virtual
stack when loading files. Default is False. stack when loading files. Default is False.
dataset_name (str, optional): Specifies the name of the dataset to be loaded dataset_name (str, optional): Specifies the name of the dataset to be loaded
...@@ -368,4 +401,4 @@ class ImgExamples: ...@@ -368,4 +401,4 @@ class ImgExamples:
# Generate loader for each image found # Generate loader for each image found
for idx, name in enumerate(img_names): for idx, name in enumerate(img_names):
exec(f"self.{name} = qim3d.io.load(path = str(img_paths[idx]))") exec(f"self.{name} = qim3d.io.load(path = img_paths[idx])")
...@@ -8,7 +8,7 @@ import pytest ...@@ -8,7 +8,7 @@ import pytest
vol = qim3d.examples.blobs_256x256 vol = qim3d.examples.blobs_256x256
# Ceate memory map to blobs # Ceate memory map to blobs
blobs_path = str(Path(qim3d.__file__).parents[0] / "img_examples" / "blobs_256x256.tif") blobs_path = Path(qim3d.__file__).parents[0] / "img_examples" / "blobs_256x256.tif"
vol_memmap = qim3d.io.load(blobs_path,virtual_stack=True) vol_memmap = qim3d.io.load(blobs_path,virtual_stack=True)
def test_load_shape(): def test_load_shape():
...@@ -28,9 +28,7 @@ def test_invalid_path(): ...@@ -28,9 +28,7 @@ def test_invalid_path():
def test_did_you_mean(): def test_did_you_mean():
# Remove last two characters from the path # Remove last two characters from the path
blobs_path_misspelled = blobs_path[:-2] blobs_path_misspelled = str(blobs_path)[:-2]
with pytest.raises(ValueError,match=f"Invalid path.\nDid you mean '{blobs_path}'?"): with pytest.raises(ValueError,match=f"Invalid path.\nDid you mean '{blobs_path}'?"):
qim3d.io.load(blobs_path_misspelled) qim3d.io.load(blobs_path_misspelled)
\ No newline at end of file
import qim3d import qim3d
import os import os
import re import re
from pathlib import Path
def test_mock_plot(): def test_mock_plot():
...@@ -35,3 +36,18 @@ def test_get_local_ip(): ...@@ -35,3 +36,18 @@ def test_get_local_ip():
local_ip = qim3d.utils.internal_tools.get_local_ip() local_ip = qim3d.utils.internal_tools.get_local_ip()
assert validate_ip(local_ip) == True assert validate_ip(local_ip) == True
def test_stringify_path1():
"""Test that the function converts os.PathLike objects to strings
"""
blobs_path = Path(qim3d.__file__).parents[0] / "img_examples" / "blobs_256x256.tif"
assert str(blobs_path) == qim3d.utils.internal_tools.stringify_path(blobs_path)
def test_stringify_path2():
"""Test that the function returns input unchanged if input is a string
"""
# Create test_path
test_path = os.path.join('this','path','doesnt','exist.tif')
assert test_path == qim3d.utils.internal_tools.stringify_path(test_path)
...@@ -7,6 +7,7 @@ import matplotlib.pyplot as plt ...@@ -7,6 +7,7 @@ import matplotlib.pyplot as plt
import matplotlib import matplotlib
import numpy as np import numpy as np
import socket import socket
import os
...@@ -176,3 +177,10 @@ def is_server_running(ip, port): ...@@ -176,3 +177,10 @@ def is_server_running(ip, port):
return True return True
except: except:
return False return False
def stringify_path(path):
"""Converts an os.PathLike object to a string
"""
if isinstance(path,os.PathLike):
path = path.__fspath__()
return path
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment