Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 71 additions & 3 deletions src/highdicom/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ def __init__(
device_serial_number: str | None = None,
institution_name: str | None = None,
institutional_department_name: str | None = None,
content_date: str | datetime.date | None = None,
content_time: str | datetime.time | None = None,
series_date: str | datetime.date | None = None,
series_time: str | datetime.time | None = None,
):
"""
Parameters
Expand Down Expand Up @@ -121,6 +125,18 @@ def __init__(
institutional_department_name: Union[str, None], optional
Name of the department of the person or device that creates the
SR document instance.
content_date: str | datetime.date | None, optional
Date the content of this instance was created. If not specified,
the current date will be used.
content_time: str | datetime.time | None, optional
Time the content of this instance was created. If not specified,
the current time will be used.
series_date: str | datetime.date | None, optional
Date the series was started. This should be the same for all
instances in a series.
series_time: str | datetime.time | None, optional
Time the series was started. This should be the same for all
instances in a series.

Note
----
Expand Down Expand Up @@ -207,7 +223,11 @@ def __init__(
_check_long_string(device_serial_number)
self.DeviceSerialNumber = device_serial_number
if software_versions is not None:
_check_long_string(software_versions)
if not isinstance(software_versions, str):
for v in software_versions:
_check_long_string(v)
else:
_check_long_string(software_versions)
self.SoftwareVersions = software_versions
if institution_name is not None:
_check_long_string(institution_name)
Expand All @@ -227,11 +247,59 @@ def __init__(
)
self.InstanceNumber = instance_number

now = datetime.datetime.now()
self.InstanceCreationDate = DA(now.date())
self.InstanceCreationTime = TM(now.time())

# Content Date and Content Time are not present in all IODs
if is_attribute_in_iod('ContentDate', sop_class_uid):
self.ContentDate = DA(datetime.datetime.now().date())
if content_date is None:
if content_time is not None:
raise TypeError(
"'content_time' may not be specified without "
"'content_date'."
)
content_date = now.date()
content_date = DA(content_date)
self.ContentDate = content_date
elif content_date is not None:
raise TypeError(
f"'content_date' should not be specified for SOP Class UID: "
f"{sop_class_uid}"
)
if is_attribute_in_iod('ContentTime', sop_class_uid):
self.ContentTime = TM(datetime.datetime.now().time())
if content_time is None:
content_time = now.time()
content_time = TM(content_time)
self.ContentTime = content_time
elif content_time is not None:
raise TypeError(
f"'content_time' should not be specified for SOP Class UID: "
f"{sop_class_uid}"
)

if series_date is not None:
series_date = DA(series_date)
if content_date is not None:
if series_date > content_date:
raise ValueError(
"'series_date' must not be later than 'content_date'."
)
self.SeriesDate = series_date
if series_time is not None:
series_time = TM(series_time)
if series_date is None:
raise TypeError(
"'series_time' may not be specified without "
"'series_date'."
)
if content_time is not None:
if series_time > content_time:
raise ValueError(
"'series_time' must not be later than content time."
)
self.SeriesTime = series_time

if content_qualification is not None:
content_qualification = ContentQualificationValues(
content_qualification
Expand Down
87 changes: 87 additions & 0 deletions tests/test_base.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import datetime
import re
import pytest
import unittest
Expand Down Expand Up @@ -59,6 +60,92 @@ def test_type_3_attributes(self):
)
assert instance.SoftwareVersions is not None
assert instance.ManufacturerModelName is not None
assert hasattr(instance, 'ContentDate')
assert hasattr(instance, 'ContentTime')
assert not hasattr(instance, 'SeriesDate')
assert not hasattr(instance, 'SeriesTime')

def test_content_time_without_date(self):
msg = (
"'content_time' may not be specified without "
"'content_date'."
)
with pytest.raises(TypeError, match=msg):
SOPClass(
study_instance_uid=UID(),
series_instance_uid=UID(),
series_number=1,
sop_instance_uid=UID(),
sop_class_uid='1.2.840.10008.5.1.4.1.1.88.33',
instance_number=1,
modality='SR',
manufacturer='highdicom',
manufacturer_model_name='foo-bar',
software_versions='v1.0.0',
transfer_syntax_uid=ExplicitVRLittleEndian,
content_time=datetime.time(12, 34, 56),
)

def test_series_datetime(self):
instance = SOPClass(
study_instance_uid=UID(),
series_instance_uid=UID(),
series_number=1,
sop_instance_uid=UID(),
sop_class_uid='1.2.840.10008.5.1.4.1.1.88.33',
instance_number=1,
modality='SR',
manufacturer='highdicom',
manufacturer_model_name='foo-bar',
software_versions='v1.0.0',
transfer_syntax_uid=ExplicitVRLittleEndian,
series_date=datetime.date(2000, 12, 1),
series_time=datetime.time(12, 34, 56),
)
assert hasattr(instance, 'SeriesDate')
assert hasattr(instance, 'SeriesTime')

def test_series_date_without_time(self):
msg = (
"'series_time' may not be specified without "
"'series_date'."
)
with pytest.raises(TypeError, match=msg):
SOPClass(
study_instance_uid=UID(),
series_instance_uid=UID(),
series_number=1,
sop_instance_uid=UID(),
sop_class_uid='1.2.840.10008.5.1.4.1.1.88.33',
instance_number=1,
modality='SR',
manufacturer='highdicom',
manufacturer_model_name='foo-bar',
software_versions='v1.0.0',
transfer_syntax_uid=ExplicitVRLittleEndian,
series_time=datetime.time(12, 34, 56),
)

def test_series_date_after_content(self):
msg = (
"'series_date' must not be later than 'content_date'."
)
with pytest.raises(ValueError, match=msg):
SOPClass(
study_instance_uid=UID(),
series_instance_uid=UID(),
series_number=1,
sop_instance_uid=UID(),
sop_class_uid='1.2.840.10008.5.1.4.1.1.88.33',
instance_number=1,
modality='SR',
manufacturer='highdicom',
manufacturer_model_name='foo-bar',
software_versions='v1.0.0',
transfer_syntax_uid=ExplicitVRLittleEndian,
content_date=datetime.date(2000, 12, 1),
series_date=datetime.date(2000, 12, 2),
)

def test_big_endian(self):
with pytest.raises(ValueError):
Expand Down