From 7e694e3900b54084446224197bc199ea8f822bad Mon Sep 17 00:00:00 2001 From: Beliy Nikita Date: Wed, 17 Apr 2024 14:44:35 +0000 Subject: [PATCH] Minor fixes --- CHANGELOG.md | 8 ++++++++ bidsme/Modules/MRI/NIFTI.py | 2 +- bidsme/Modules/MRI/jsonNIFTI.py | 2 +- bidsme/Modules/PET/NIFTI.py | 2 +- bidsme/Modules/PET/jsonNIFTI.py | 11 ++++++++++- bidsme/Modules/_nifti_common.py | 32 ++++++++++++++++++++++++++++---- bidsme/Modules/base.py | 30 ++++++++++++++++++++++++++---- bidsme/bidsMeta/BidsTable.py | 4 ++++ 8 files changed, 79 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d8c68ad..c359f36 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) +### Fixed + - jsonNIFTI: fixed retrieval of ParticipantID, based on `dcm2niix` entry `PatientID` + - BaseModule: `series_no`/`series_id` becomes prperties with type check (int/str resp.) + +### Added + - Log entry while loading tables + - NIFTI: added support for compressed files + ## [1.6.4] - 2024-04-11 ### Fixed diff --git a/bidsme/Modules/MRI/NIFTI.py b/bidsme/Modules/MRI/NIFTI.py index 6d55b00..852a92f 100644 --- a/bidsme/Modules/MRI/NIFTI.py +++ b/bidsme/Modules/MRI/NIFTI.py @@ -52,7 +52,7 @@ class NIFTI(MRI): "PatientId", "SessionId"} - _file_extentions = [".nii", ".hdr"] + _file_extentions = [".nii", ".nii.gz", ".hdr"] def __init__(self, rec_path=""): super().__init__() diff --git a/bidsme/Modules/MRI/jsonNIFTI.py b/bidsme/Modules/MRI/jsonNIFTI.py index 7756e32..e4d5327 100644 --- a/bidsme/Modules/MRI/jsonNIFTI.py +++ b/bidsme/Modules/MRI/jsonNIFTI.py @@ -170,7 +170,7 @@ def copyRawFile(self, destination: str) -> str: return os.path.join(destination, self.currentFile(True)) def _getSubId(self) -> str: - return "" + return self.getField("PatientID", "") def _getSesId(self) -> str: return "" diff --git a/bidsme/Modules/PET/NIFTI.py b/bidsme/Modules/PET/NIFTI.py index 1d77856..cf09164 100644 --- a/bidsme/Modules/PET/NIFTI.py +++ b/bidsme/Modules/PET/NIFTI.py @@ -46,7 +46,7 @@ class NIFTI(PET): __slots__ = ["_NIFTI_CACHE", "_FILE_CACHE", "_nii_type", "_endiannes" ] - _file_extentions = [".nii", ".hdr"] + _file_extentions = [".nii", ".nii.gz", ".hdr"] __specialFields = {"AcquisitionTime", "SeriesNumber", diff --git a/bidsme/Modules/PET/jsonNIFTI.py b/bidsme/Modules/PET/jsonNIFTI.py index dc74930..2e2a46d 100644 --- a/bidsme/Modules/PET/jsonNIFTI.py +++ b/bidsme/Modules/PET/jsonNIFTI.py @@ -162,7 +162,16 @@ def copyRawFile(self, destination: str) -> str: return os.path.join(destination, self.currentFile(True)) def _getSubId(self) -> str: - return "" + tags = ["patient_id", # ecat header dump + "PatientID" # dcm2niix + ] + res = "" + for t in tags: + res = self.getField(t, "") + if res: + break + + return res def _getSesId(self) -> str: return "" diff --git a/bidsme/Modules/_nifti_common.py b/bidsme/Modules/_nifti_common.py index 948f8e6..8173f2e 100644 --- a/bidsme/Modules/_nifti_common.py +++ b/bidsme/Modules/_nifti_common.py @@ -23,11 +23,33 @@ import logging import struct +import gzip logger = logging.getLogger(__name__) +def _nii_open(path: str, mode="rb"): + """ + Returns open file stream with open or gzip.open + + Parameters: + ----------- + path: str + Path to file to open + mode: str + Mode in wich open + + Returns: + -------- + (decompressed) opened stream + """ + if path.endswith('.gz'): + return gzip.open(path, mode) + else: + return open(path, mode) + + def isValidNIFTI(file: str) -> bool: """ Returns True if given file is valid, i.e. @@ -39,8 +61,10 @@ def isValidNIFTI(file: str) -> bool: file: str path to file (must exist) """ - with open(file, 'rb') as niifile: + + with _nii_open(file, 'rb') as niifile: d = niifile.read(4) + if len(d) != 4: logger.debug('File too short') return False @@ -79,7 +103,7 @@ def getEndType(path: str) -> tuple: (str, str): tuple of endianess symbol and nifti type """ - with open(path, "rb") as niifile: + with _nii_open(path, "rb") as niifile: header_size = struct.unpack(" dict: parced header """ res = dict() - with open(path, "rb") as niifile: + with _nii_open(path, "rb") as niifile: header = niifile.read(348) diminfo = struct.unpack("c", header[39:40])[0] @@ -199,7 +223,7 @@ def parceNIFTIheader_2(path: str, endian: str) -> dict: parced header """ res = dict() - with open(path, "rb") as niifile: + with _nii_open(path, "rb") as niifile: header = niifile.read(540) res["datatype"] = struct.unpack(endian + "h", header[12:14])[0] diff --git a/bidsme/Modules/base.py b/bidsme/Modules/base.py index f336da9..182b857 100644 --- a/bidsme/Modules/base.py +++ b/bidsme/Modules/base.py @@ -68,8 +68,8 @@ class baseModule(abstract): "files", "_recPath", # series identifier - "series_id", - "series_no", + "_series_id", + "_series_no", # json meta variables "metaAuxiliary", "metaFields_req", @@ -132,8 +132,8 @@ def __init__(self): self.files = list() self._recPath = "" self.index = -1 - self.series_id = None - self.series_no = None + self._series_id = None + self._series_no = None self.attributes = dict() self.custom = dict() self.labels = OrderedDict() @@ -801,9 +801,31 @@ def resetAcqTime(self): """ self._acqTime = None + @property + def series_no(self): + return self._series_no + + @series_no.setter + def series_no(self, val): + if not isinstance(val, int): + raise ValueError("{}: series_no must be an int, {} recieved" + .format(self.currentFile(), type(val))) + self._series_no = val + def recNo(self): return self.series_no + @property + def series_id(self): + return self._series_id + + @series_id.setter + def series_id(self, val): + if not isinstance(val, str): + raise ValueError("{}: series_id must be a string, {} recieved" + .format(self.currentFile(), type(val))) + self._series_id = val + def recId(self): return self.series_id diff --git a/bidsme/bidsMeta/BidsTable.py b/bidsme/bidsMeta/BidsTable.py index 081b952..15492a8 100644 --- a/bidsme/bidsMeta/BidsTable.py +++ b/bidsme/bidsMeta/BidsTable.py @@ -131,11 +131,15 @@ def __init__(self, table: str, else: for c in mismatch: self.df[c] = None + logger.info("Loaded {} table with {} entries" + .format(self._name, len(self.df))) else: columns = self._definitions.keys() if index and index not in columns: columns = [index] + list(columns) self.df = pandas.DataFrame(columns=columns) + logger.info("Created empty {} table" + .format(self._name)) def getTablePath(self) -> str: """