Skip to content

Commit

Permalink
Merge pull request #11 from ZviBaratz/version_bump
Browse files Browse the repository at this point in the history
Version bump
  • Loading branch information
ZviBaratz committed Dec 17, 2020
2 parents c6c56a4 + 743fd8f commit 6c20d07
Show file tree
Hide file tree
Showing 11 changed files with 243 additions and 139 deletions.
89 changes: 58 additions & 31 deletions dicom_parser/header.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,29 @@
from dicom_parser.utils.format_header_df import format_header_df
from dicom_parser.utils.private_tags import PRIVATE_TAGS
from dicom_parser.utils.read_file import read_file
from dicom_parser.utils.sequence_detector.sequence_detector import SequenceDetector
from dicom_parser.utils.sequence_detector.sequence_detector import (
SequenceDetector,
)
from dicom_parser.utils.value_representation import ValueRepresentation
from dicom_parser.utils.vr_to_data_element import get_data_element_class
from pathlib import Path
from pydicom.dataelem import DataElement as PydicomDataElement
from pydicom.dataset import FileDataset
from types import GeneratorType
from typing import Any, Union


class Header:
"""
Facilitates access to DICOM_ header information from pydicom_'s FileDataset_.
Facilitates access to DICOM_ header information from pydicom_'s
FileDataset_.
.. _DICOM: https://www.dicomstandard.org/
.. _pydicom: https://github.com/pydicom/pydicom
.. _FileDataset: https://github.com/pydicom/pydicom/blob/master/pydicom/dataset.py
.. _DICOM:
https://www.dicomstandard.org/
.. _pydicom:
https://github.com/pydicom/pydicom
.. _FileDataset:
https://github.com/pydicom/pydicom/blob/master/pydicom/dataset.py
"""

Expand All @@ -34,19 +43,22 @@ class Header:
DATAFRAME_COLUMNS = "Tag", "Keyword", "VR", "VM", "Value"
DATAFRAME_INDEX = "Tag"

def __init__(self, raw, sequence_detector=SequenceDetector):
def __init__(
self,
raw: Union[FileDataset, str, Path],
sequence_detector=SequenceDetector,
):
"""
Header is meant to be initialized with a pydicom_ FileDataset_
representing a single image's header, or a string representing
the path to a dicom image file, or a :class:`~pathlib.Path` instance.
Parameters
----------
raw : pydicom.dataset.FileDataset / path string or pathlib.Path instance
DICOM_ image header information or path.
parser : type
An object with a public `parse()` method that may be used to parse
data elements, by default Parser.
raw : Union[pydicom.dataset.FileDataset, str, pathlib.Path]
DICOM_ image header information or path
sequence_detector : SequenceDetector
A utility class to automatically detect sequences
.. _pydicom: https://github.com/pydicom/pydicom
.. _FileDataset: https://github.com/pydicom/pydicom/blob/master/pydicom/dataset.py
Expand All @@ -60,7 +72,7 @@ def __init__(self, raw, sequence_detector=SequenceDetector):
self.detected_sequence = self.detect_sequence()
self._as_dict = None

def __getitem__(self, key):
def __getitem__(self, key) -> Any:
"""
Provide dictionary like indexing-operator functionality.
Expand All @@ -71,15 +83,17 @@ def __getitem__(self, key):
Returns
-------
[type]
Any
Parsed header information of the given key or keys
"""

return self.get(key, missing_ok=False)

def __str__(self) -> str:
base = self.to_dataframe(exclude=ValueRepresentation.SQ, private=False)
sequences = self.get_data_elements(value_representation=ValueRepresentation.SQ)
sequences = self.get_data_elements(
value_representation=ValueRepresentation.SQ
)
privates = self.to_dataframe(private=True)
sequences_string = ""
if sequences:
Expand All @@ -90,7 +104,9 @@ def __str__(self) -> str:
)
privates_string = "\n\nPrivate Data Elements\n=====================\n"
privates_string = (
privates_string + format_header_df(privates) if not privates.empty else ""
privates_string + format_header_df(privates)
if not privates.empty
else ""
)
return format_header_df(base) + sequences_string + privates_string

Expand All @@ -112,7 +128,9 @@ def detect_sequence(self) -> str:
sequence_identifiers = self.sequence_identifiers.get(modality)
sequence_identifying_values = self.get(sequence_identifiers)
try:
return self.sequence_detector.detect(modality, sequence_identifying_values)
return self.sequence_detector.detect(
modality, sequence_identifying_values
)
except NotImplementedError:
pass

Expand All @@ -139,7 +157,9 @@ def get_raw_element_by_keyword(self, keyword: str) -> PydicomDataElement:
value = self.raw.data_element(keyword)
if isinstance(value, PydicomDataElement):
return value
raise KeyError(f"The keyword: '{keyword}' does not exist in the header!")
raise KeyError(
f"The keyword: '{keyword}' does not exist in the header!"
)

def get_raw_element_by_tag(self, tag: tuple) -> PydicomDataElement:
"""
Expand Down Expand Up @@ -225,9 +245,13 @@ def get_data_elements(
exclusions = isinstance(exclude, (ValueRepresentation, list, tuple))
for data_element in self.data_elements:
if isinstance(value_representation, ValueRepresentation):
matching_vr = data_element.VALUE_REPRESENTATION == value_representation
matching_vr = (
data_element.VALUE_REPRESENTATION == value_representation
)
elif isinstance(value_representation, (list, tuple)):
matching_vr = data_element.VALUE_REPRESENTATION in value_representation
matching_vr = (
data_element.VALUE_REPRESENTATION in value_representation
)
filtered = filter_by_vr and not matching_vr
if isinstance(exclude, ValueRepresentation):
excluded_vr = data_element.VALUE_REPRESENTATION == exclude
Expand Down Expand Up @@ -262,7 +286,7 @@ def get_raw_value(self, tag_or_keyword):
element = self.get_raw_element(tag_or_keyword)
return element.value

def get_parsed_value(self, tag_or_keyword):
def get_parsed_value(self, tag_or_keyword) -> Any:
"""
Returns the parsed value of pydicom_ data element using the this class's
parser attribute. The data element may be represented by tag or by its
Expand All @@ -277,7 +301,7 @@ def get_parsed_value(self, tag_or_keyword):
Returns
-------
type
Any
Parsed data element value
"""

Expand Down Expand Up @@ -312,24 +336,25 @@ def get(
parsed: bool = True,
missing_ok: bool = True,
as_json: bool = False,
):
) -> Any:
"""
Returns the value of a pydicom data element, selected by tag (`tuple`) or
keyword (`str`). Input may also be a `list` of such identifiers, in which
case a dictionary will be returned with the identifiers as keys and header
information as values.
Returns the value of a pydicom data element, selected by tag (`tuple`)
or keyword (`str`). Input may also be a `list` of such identifiers, in
which case a dictionary will be returned with the identifiers as keys and
header information as values.
Parameters
----------
tag_or_keyword : tuple or str, or list
Tag or keyword representing the requested data element, or a list of such.
Tag or keyword representing the requested data element, or a list
of such
parsed : bool, optional
Whether to return a parsed or raw value (the default is True, which will
return the parsed value).
Whether to return a parsed or raw value (the default is True,
which will return the parsed value)
Returns
-------
type
Any
The requested data element value (or a dict for multiple values)
"""

Expand All @@ -339,7 +364,9 @@ def get(
# Tries to find a private tags tuple if the given tag_or_keyword is a
# keyword that has been registered in the private_tags module
if isinstance(tag_or_keyword, str):
tag_or_keyword = self.get_private_tag(tag_or_keyword) or tag_or_keyword
tag_or_keyword = (
self.get_private_tag(tag_or_keyword) or tag_or_keyword
)

# Get the requested value
value = None
Expand Down
20 changes: 10 additions & 10 deletions dicom_parser/image.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""
Definition of the Image class, representing a single pair of
:class:`~dicom_parser.header.Header` and data (3D `NumPy <https://numpy.org>`_ array).
Definition of the :class:`Image` class, representing a single pair of
:class:`~dicom_parser.header.Header` and data (3D `NumPy <https://numpy.org>`_
array).
"""

Expand All @@ -12,6 +13,8 @@
from dicom_parser.utils.read_file import read_file
from dicom_parser.utils.siemens.mosaic import Mosaic
from pathlib import Path
from pydicom.dataset import FileDataset
from typing import Union


class Image:
Expand All @@ -21,7 +24,7 @@ class Image:
"""

def __init__(self, raw):
def __init__(self, raw: Union[FileDataset, str, Path]):
"""
The Image class should be initialized with either a string or a
:class:`~pathlib.Path` instance representing the path of a .dcm file.
Expand All @@ -32,11 +35,8 @@ def __init__(self, raw):
Parameters
----------
raw : str, pathlib.Path, or pydicom.FileDataset
A single DICOM image.
parser : type, optional
An object with a public `parse()` method that may be used to parse
data elements, by default Parser.
raw : Union[pydicom.dataset.FileDataset, str, pathlib.Path]
A single DICOM image
"""

self.raw = read_file(raw, read_data=True)
Expand Down Expand Up @@ -107,7 +107,7 @@ def is_fmri(self) -> bool:
Returns
-------
bool
Whether this image represents fMRI data.
Whether this image represents fMRI data
"""

return self.header.detected_sequence == "fMRI"
Expand All @@ -121,7 +121,7 @@ def data(self) -> np.ndarray:
Returns
-------
np.ndarray
Pixel data array.
Pixel data array
"""

return self.fix_data()
Expand Down

0 comments on commit 6c20d07

Please sign in to comment.