convert
pacsanini.convert
#
The convert module provides utility methods that can be used
to convert raw DICOM data to DICOM files.
agestr2years(age_str)
#
Convert an Age String into a int where the age unit is
in years. Expected formats are: nnnD, nnnW, nnnM, nnnY.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
age_str |
str |
A DICOM Age String value. |
required |
Exceptions:
| Type | Description |
|---|---|
ValueError |
A ValueError is raised if the age_str is not a valid Age String. |
Returns:
| Type | Description |
|---|---|
int |
The number of years as an int. |
Source code in pacsanini/convert.py
def agestr2years(age_str: str) -> int:
"""Convert an Age String into a int where the age unit is
in years. Expected formats are: nnnD, nnnW, nnnM, nnnY.
Notes
-----
The return value may not yield precise results as the following
assumptions are made: there are 365 days in a year, there are 52
weeks in a year, and there are 12 months in a year.
Parameters
----------
age_str : str
A DICOM Age String value.
Returns
-------
int
The number of years as an int.
Raises
------
ValueError
A ValueError is raised if the age_str is not a valid
Age String.
"""
if not age_str or len(age_str) != 4:
raise ValueError(
f"Expected the age string to be in the 'nnn[DWMY]' format. Obtained: {age_str}"
)
age_unit = age_str[-1].upper()
if age_unit not in "DWMY":
raise ValueError(
f"Expected the age string unit to be one of 'D', 'W', 'M', 'Y'. Obtained: {age_unit}"
)
age_value = age_str[:3]
if age_unit == "D":
return int(age_value) // 365
elif age_unit == "W":
return int(age_value) // 52
elif age_unit == "M":
return int(age_value) // 12
else:
return int(age_value)
datetime2str(date_time, use_time=False)
#
Convert a datetime object to a DICOM compliant date(time) string.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
date_time |
datetime |
The datetime object to convert ot a DICOM string. |
required |
use_time |
bool |
If False, the default, don't add the time component in the return value. Note that this has no impact if the datetime component has an existing time component. |
False |
Returns:
| Type | Description |
|---|---|
str |
The datetime object as a DICOM string. |
Source code in pacsanini/convert.py
def datetime2str(date_time: datetime, use_time: bool = False) -> str:
"""Convert a datetime object to a DICOM compliant date(time) string.
Parameters
----------
date_time : datetime
The datetime object to convert ot a DICOM string.
use_time : bool
If False, the default, don't add the time component in the
return value. Note that this has no impact if the datetime
component has an existing time component.
Returns
-------
str
The datetime object as a DICOM string.
"""
omit_time = (
date_time.hour == 0
and date_time.minute == 0
and date_time.second == 0
and date_time.microsecond == 0
)
if use_time or not omit_time:
if date_time.tzinfo is not None:
return date_time.strftime("%Y%m%d%H%M%S.%f%z")
return date_time.strftime("%Y%m%d%H%M%S.%f")
return date_time.strftime("%Y%m%d")
dcm2dict(dcm, include_pixels=False)
#
Return the JSON-compatiable dict representation of a DICOM file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dcm |
Union[pydicom.dataset.Dataset, bytes, str] |
The DICOM Dataset, bytes, or file path to convert to use in order to produce the JSON dict. |
required |
include_pixels |
bool |
If True, include the pixel array in the generated dict. The default is False. |
False |
Returns:
| Type | Description |
|---|---|
Dict[str, dict] |
A JSON-compatible dict representation of the DICOM. |
Source code in pacsanini/convert.py
def dcm2dict(
dcm: Union[Dataset, bytes, str], include_pixels: bool = False
) -> Dict[str, dict]:
"""Return the JSON-compatiable dict representation of a DICOM file.
Parameters
----------
dcm : Union[Dataset, bytes, str]
The DICOM Dataset, bytes, or file path to convert to use in order
to produce the JSON dict.
include_pixels : bool
If True, include the pixel array in the generated dict. The default
is False.
Returns
-------
Dict[str, dict]
A JSON-compatible dict representation of the DICOM.
"""
if isinstance(dcm, (bytes, str)):
dcm = dcmread(dcm, stop_before_pixels=not include_pixels)
if not include_pixels:
dcm.PixelData = None
def tag2name(dcm: Dataset, tag: str) -> str:
name = dcm[tag].name.replace("[", "").replace("]", "")
name = "".join(char.capitalize() for char in name.split(" "))
return name
def dict2nameddict(dcm: Dataset, seq_dict: Dict[str, dict]):
for key, value in seq_dict.items():
value["Name"] = tag2name(dcm, key)
if value["vr"] == "SQ" and len(value["Value"]):
value["Value"][0] = dict2nameddict(dcm[key][0], value["Value"][0])
return seq_dict
dcm_dict = dcm.to_json_dict()
for key, value in dcm_dict.items():
value["Name"] = tag2name(dcm, key)
if value["vr"] == "SQ" and len(value["Value"]):
value["Value"][0] = dict2nameddict(dcm[key][0], value["Value"][0])
return dcm_dict
dict2dcm(dcm_dict)
#
Convert a dictionary containing DICOM tag metadata to a DICOM Dataset.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dcm_dict |
Dict[str, dict] |
A dictionary containg DICOM tag metadata that you want to convert to a Dataset. |
required |
Returns:
| Type | Description |
|---|---|
Dataset |
The DICOM Dataset. |
Source code in pacsanini/convert.py
def dict2dcm(dcm_dict: Dict[str, dict]) -> Dataset:
"""Convert a dictionary containing DICOM tag metadata to a DICOM Dataset.
Parameters
----------
dcm_dict : Dict[str, dict]
A dictionary containg DICOM tag metadata that you want to
convert to a Dataset.
Returns
-------
Dataset
The DICOM Dataset.
"""
for values in dcm_dict.values():
values.pop("Name", None)
return Dataset.from_json(json.dumps(dcm_dict))
str2datetime(dcm_date)
#
Parse a date in DICOM string format and return
a datetime object.
Strings can come in the following formats: YYYYMMDD (date), or YYYYMMDDHHMMSS.FFFFFF&ZZXX (datetime) -as specified by the DICOM standard.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dcm_date |
str |
A date(time) in DICOM string format. |
required |
Exceptions:
| Type | Description |
|---|---|
ValueError |
A ValueError is raised if the dcm_date parameter does not conform to any DICOM date(time) format. |
Returns:
| Type | Description |
|---|---|
datetime |
A datetime corresponding to the DICOM string value. |
Source code in pacsanini/convert.py
def str2datetime(dcm_date: str) -> datetime:
"""Parse a date in DICOM string format and return
a datetime object.
Strings can come in the following formats:
YYYYMMDD (date), or YYYYMMDDHHMMSS.FFFFFF&ZZXX
(datetime) -as specified by the DICOM standard.
Parameters
----------
dcm_date : str
A date(time) in DICOM string format.
Returns
-------
datetime
A datetime corresponding to the DICOM string
value.
Raises
------
ValueError
A ValueError is raised if the dcm_date parameter
does not conform to any DICOM date(time) format.
"""
fmt = "%Y%m%d"
try:
return datetime.strptime(dcm_date, fmt)
except ValueError:
fmt += "%H%M%S.%f"
try:
return datetime.strptime(dcm_date, fmt)
except ValueError:
fmt += "%z"
return datetime.strptime(dcm_date, fmt)
str2timedelta(dcm_time)
#
Parse a time in DICOM string value and return a
timedelta object.
Time strings in DICOM format are formatted in the following way: HHMMSS.FFFFFF. The only mandatory component in DICOM time strings is the hour component.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dcm_time |
str |
A time value in DICOM string format. |
required |
Exceptions:
| Type | Description |
|---|---|
ValueError |
A ValueError is raised if the dcm_time parameter does not conform to the DICOM time format. |
Returns:
| Type | Description |
|---|---|
timedelta |
The DICOM time value as a timedelta object. |
Source code in pacsanini/convert.py
def str2timedelta(dcm_time: str) -> timedelta:
"""Parse a time in DICOM string value and return a
timedelta object.
Time strings in DICOM format are formatted in the
following way: HHMMSS.FFFFFF. The only mandatory
component in DICOM time strings is the hour component.
Parameters
----------
dcm_time : str
A time value in DICOM string format.
Returns
-------
timedelta
The DICOM time value as a timedelta object.
Raises
------
ValueError
A ValueError is raised if the dcm_time parameter
does not conform to the DICOM time format.
"""
m = re.fullmatch(
r"(\d\d)(?:(\d\d)(?:(\d\d)(?:\.(\d{1,6}))?)?)?", dcm_time, flags=re.ASCII
)
if m is None:
raise ValueError(f"Invalid DICOM time string: '{dcm_time}'")
time_vals = {"hours": int(m.group(1))}
if m.group(2) is not None:
time_vals["minutes"] = int(m.group(2))
if m.group(3) is not None:
time_vals["seconds"] = int(m.group(3))
if m.group(4) is not None:
time_vals["microseconds"] = int(m.group(4).ljust(6, "0"))
return timedelta(**time_vals)
timedelta2str(time_delta)
#
Convert a timedelta object to its DICOM string counterpart.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
time_delta |
timedelta |
The timedelta object to convert to string. |
required |
Returns:
| Type | Description |
|---|---|
str |
The timdelta objected represented as a DICOM time string. |
Source code in pacsanini/convert.py
def timedelta2str(time_delta: timedelta) -> str:
"""Convert a timedelta object to its DICOM string counterpart.
Parameters
----------
time_delta : timedelta
The timedelta object to convert to string.
Returns
-------
str
The timdelta objected represented as a DICOM time string.
"""
ref_date = datetime(1970, 1, 1) + time_delta
return ref_date.strftime("%H%M%S.%f")