Skip to content

Commit

Permalink
Adjust default StoragePresentationContexts (#980)
Browse files Browse the repository at this point in the history
  • Loading branch information
mdebic authored Dec 22, 2024
1 parent 503a75f commit c22be4b
Show file tree
Hide file tree
Showing 10 changed files with 161 additions and 166 deletions.
10 changes: 10 additions & 0 deletions docs/changelog/v3.0.0.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.. _v3.0.0:

3.0.0
=====

The major breaking changes with the version 3.0 release are:

* Support for pydicom v3
* Changed ``StoragePresentationContexts`` to match DCMTK implementation
* Some presentation contexts were replaced
2 changes: 1 addition & 1 deletion docs/examples/storage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ single CT dataset.
Of course it's rarely the case that someone wants to store just CT images,
so you can also use the inbuilt
:attr:`~pynetdicom.presentation.StoragePresentationContexts` which contains
presentation contexts for the first 128 storage SOP Classes when setting
presentation contexts for the first 120 storage SOP Classes when setting
the requested contexts, or just add as many contexts as you need.

.. code-block:: python
Expand Down
13 changes: 7 additions & 6 deletions docs/user/ae.rst
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ Adding presentation contexts all at once:
>>> ae.requested_contexts = StoragePresentationContexts

Here :attr:`~pynetdicom.presentation.StoragePresentationContexts` is a
prebuilt list of presentation contexts containing (almost) all the Storage
Service Class' :dcm:`supported SOP Classes <part04/sect_B.5.html>`,
prebuilt list of presentation contexts containing 120 of the most commonly used Storage
Service Classes' :dcm:`supported SOP Classes <part04/sect_B.5.html>`,
and there's a :ref:`similar list<api_presentation_prebuilt>` for all
the supported service classes.
Alternatively you can build your own list of presentation contexts, either
Expand All @@ -115,12 +115,13 @@ Combining the all-at-once and one-by-one approaches:
>>> from pynetdicom import AE, StoragePresentationContexts
>>> from pynetdicom.sop_class import Verification
>>> ae = AE()
>>> ae.requested_contexts = StoragePresentationContexts[:127]
>>> ae.requested_contexts = StoragePresentationContexts
>>> ae.add_requested_context(Verification)

As the association *Requestor* you're limited to a total of 128 requested
presentation contexts, so attempting to add more than 128 contexts will raise
a :class:`ValueError` exception.
a :class:`ValueError` exception. :attr:`~pynetdicom.presentation.StoragePresentationContexts` consists of 120 of most commonly used Storage
Service Classes, therefore you are able to add 8 additional presentation contexts without rasing a :class:`ValueError` exception.

When you add presentation contexts as shown above, the following transfer
syntaxes are used by default for each context:
Expand Down Expand Up @@ -285,8 +286,8 @@ Adding presentation contexts all at once:
>>> ae.supported_contexts = StoragePresentationContexts

Here :attr:`~pynetdicom.presentation.StoragePresentationContexts` is a prebuilt
:class:`list` of presentation contexts containing (almost) all the Storage
Service Class' :dcm:`supported SOP Classes<part04/sect_B.5.html>`,
:class:`list` of presentation contexts containing 120 of the most commonly used Storage
Service Classes' :dcm:`supported SOP Classes<part04/sect_B.5.html>`,
and there's a :ref:`similar list<api_presentation_prebuilt>` for
all the supported service classes. Alternatively you can build your own list
of presentation contexts, either through creating new
Expand Down
9 changes: 5 additions & 4 deletions docs/user/association.rst
Original file line number Diff line number Diff line change
Expand Up @@ -95,15 +95,16 @@ also acting as a Storage SCP), plus a *User Identity Negotiation* item:
ae = AE()
# Contexts supported as a Storage SCP - requires Role Selection
# Note that we are limited to a maximum of 128 contexts so we
# only include 127 to make room for the QR Get context
ae.requested_contexts = StoragePresentationContexts[:127]
# Note that we are limited to a maximum of 128 contexts.
# StoragePresentationContexts includes 120, it is therefore
# possible to add 8 additional presentation contexts if needed.
ae.requested_contexts = StoragePresentationContexts
# Contexts proposed as a QR SCU
ae.add_requested_context = PatientRootQueryRetrieveInformationModelGet
# Add role selection items for the contexts we will be supporting as an SCP
negotiation_items = []
for context in StoragePresentationContexts[:127]:
for context in StoragePresentationContexts:
role = build_role(context.abstract_syntax, scp_role=True)
negotiation_items.append(role)
Expand Down
15 changes: 1 addition & 14 deletions pynetdicom/apps/getscu/getscu.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,6 @@
PatientRootQueryRetrieveInformationModelGet,
StudyRootQueryRetrieveInformationModelGet,
PatientStudyOnlyQueryRetrieveInformationModelGet,
EncapsulatedSTLStorage,
EncapsulatedOBJStorage,
EncapsulatedMTLStorage,
)


Expand Down Expand Up @@ -248,16 +245,6 @@ def main(args=None):
APP_LOGGER.exception(exc)
sys.exit(1)

# Exclude these SOP Classes
_exclusion = [
EncapsulatedSTLStorage,
EncapsulatedOBJStorage,
EncapsulatedMTLStorage,
]
store_contexts = [
cx for cx in StoragePresentationContexts if cx.abstract_syntax not in _exclusion
]

# Create application entity
# Binding to port 0 lets the OS pick an available port
ae = AE(ae_title=args.calling_aet)
Expand All @@ -270,7 +257,7 @@ def main(args=None):
ae.add_requested_context(PatientRootQueryRetrieveInformationModelGet)
ae.add_requested_context(StudyRootQueryRetrieveInformationModelGet)
ae.add_requested_context(PatientStudyOnlyQueryRetrieveInformationModelGet)
for cx in store_contexts:
for cx in StoragePresentationContexts:
ae.add_requested_context(cx.abstract_syntax)
# Add SCP/SCU Role Selection Negotiation to the extended negotiation
# We want to act as a Storage SCP
Expand Down
4 changes: 2 additions & 2 deletions pynetdicom/apps/tests/test_getscu.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,14 +111,14 @@ def handle_release(event):
assert "GETSCU" == requestor.ae_title
assert 16382 == requestor.maximum_length
assert "ANY-SCP" == requestor.primitive.called_ae_title
assert 125 == len(requestor.extended_negotiation)
assert 120 == len(requestor.extended_negotiation)
assert (1, 1) == requestor.asynchronous_operations
assert {} == requestor.sop_class_common_extended
assert {} == requestor.sop_class_extended
assert requestor.role_selection != {}
assert requestor.user_identity == None
cxs = requestor.primitive.presentation_context_definition_list
assert len(cxs) == 128
assert len(cxs) == 123
cxs = {cx.abstract_syntax: cx for cx in cxs}
assert PatientRootQueryRetrieveInformationModelGet in cxs
cx = cxs[PatientRootQueryRetrieveInformationModelGet]
Expand Down
8 changes: 4 additions & 4 deletions pynetdicom/apps/tests/test_storescu.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ def handle_release(event):
assert {} == requestor.sop_class_extended
assert requestor.user_identity == None
cxs = requestor.primitive.presentation_context_definition_list
assert len(cxs) == 128
assert len(cxs) == 120
cxs = {cx.abstract_syntax: cx for cx in cxs}
assert CTImageStorage in cxs
assert cxs[CTImageStorage].transfer_syntax == [
Expand Down Expand Up @@ -422,7 +422,7 @@ def handle_release(event):
assert events[1].event == evt.EVT_RELEASED
requestor = events[1].assoc.requestor
cxs = requestor.primitive.presentation_context_definition_list
assert len(cxs) == 128
assert len(cxs) == 120
cxs = {cx.abstract_syntax: cx for cx in cxs}
assert CTImageStorage in cxs
assert cxs[CTImageStorage].transfer_syntax == [ExplicitVRLittleEndian]
Expand Down Expand Up @@ -459,7 +459,7 @@ def handle_release(event):
requestor = events[1].assoc.requestor
cxs = requestor.primitive.presentation_context_definition_list
cxs = requestor.primitive.presentation_context_definition_list
assert len(cxs) == 128
assert len(cxs) == 120
cxs = {cx.abstract_syntax: cx for cx in cxs}
assert CTImageStorage in cxs
assert cxs[CTImageStorage].transfer_syntax == [ExplicitVRBigEndian]
Expand Down Expand Up @@ -496,7 +496,7 @@ def handle_release(event):
requestor = events[1].assoc.requestor
cxs = requestor.primitive.presentation_context_definition_list
cxs = requestor.primitive.presentation_context_definition_list
assert len(cxs) == 128
assert len(cxs) == 120
cxs = {cx.abstract_syntax: cx for cx in cxs}
assert CTImageStorage in cxs
assert cxs[CTImageStorage].transfer_syntax == [ImplicitVRLittleEndian]
Expand Down
Loading

0 comments on commit c22be4b

Please sign in to comment.