From c22be4b79a20eea0f176340629b37c6e30dd10b2 Mon Sep 17 00:00:00 2001 From: Manuel Debic Date: Sun, 22 Dec 2024 23:22:23 +0100 Subject: [PATCH] Adjust default StoragePresentationContexts (#980) --- docs/changelog/v3.0.0.rst | 10 + docs/examples/storage.rst | 2 +- docs/user/ae.rst | 13 +- docs/user/association.rst | 9 +- pynetdicom/apps/getscu/getscu.py | 15 +- pynetdicom/apps/tests/test_getscu.py | 4 +- pynetdicom/apps/tests/test_storescu.py | 8 +- pynetdicom/presentation.py | 253 ++++++++++++------------- pynetdicom/tests/test_presentation.py | 9 +- pynetdicom/tests/test_service_qr.py | 4 +- 10 files changed, 161 insertions(+), 166 deletions(-) create mode 100644 docs/changelog/v3.0.0.rst diff --git a/docs/changelog/v3.0.0.rst b/docs/changelog/v3.0.0.rst new file mode 100644 index 000000000..459ba5118 --- /dev/null +++ b/docs/changelog/v3.0.0.rst @@ -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 diff --git a/docs/examples/storage.rst b/docs/examples/storage.rst index 84c8de333..db6bc1f00 100644 --- a/docs/examples/storage.rst +++ b/docs/examples/storage.rst @@ -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 diff --git a/docs/user/ae.rst b/docs/user/ae.rst index ba9d7bc00..74dc8ece9 100644 --- a/docs/user/ae.rst +++ b/docs/user/ae.rst @@ -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 `, +prebuilt list of presentation contexts containing 120 of the most commonly used Storage +Service Classes' :dcm:`supported SOP Classes `, and there's a :ref:`similar list` for all the supported service classes. Alternatively you can build your own list of presentation contexts, either @@ -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: @@ -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`, +:class:`list` of presentation contexts containing 120 of the most commonly used Storage +Service Classes' :dcm:`supported SOP Classes`, and there's a :ref:`similar list` for all the supported service classes. Alternatively you can build your own list of presentation contexts, either through creating new diff --git a/docs/user/association.rst b/docs/user/association.rst index 42ead28a6..7a97dd875 100644 --- a/docs/user/association.rst +++ b/docs/user/association.rst @@ -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) diff --git a/pynetdicom/apps/getscu/getscu.py b/pynetdicom/apps/getscu/getscu.py index 70f7dae80..aee0f6107 100755 --- a/pynetdicom/apps/getscu/getscu.py +++ b/pynetdicom/apps/getscu/getscu.py @@ -20,9 +20,6 @@ PatientRootQueryRetrieveInformationModelGet, StudyRootQueryRetrieveInformationModelGet, PatientStudyOnlyQueryRetrieveInformationModelGet, - EncapsulatedSTLStorage, - EncapsulatedOBJStorage, - EncapsulatedMTLStorage, ) @@ -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) @@ -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 diff --git a/pynetdicom/apps/tests/test_getscu.py b/pynetdicom/apps/tests/test_getscu.py index b5b6f34d8..40aecf8ea 100644 --- a/pynetdicom/apps/tests/test_getscu.py +++ b/pynetdicom/apps/tests/test_getscu.py @@ -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] diff --git a/pynetdicom/apps/tests/test_storescu.py b/pynetdicom/apps/tests/test_storescu.py index 88b8cf8e6..bda0bd762 100644 --- a/pynetdicom/apps/tests/test_storescu.py +++ b/pynetdicom/apps/tests/test_storescu.py @@ -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 == [ @@ -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] @@ -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] @@ -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] diff --git a/pynetdicom/presentation.py b/pynetdicom/presentation.py index 0b84cfa98..fba75c7ea 100644 --- a/pynetdicom/presentation.py +++ b/pynetdicom/presentation.py @@ -1093,139 +1093,132 @@ def build_role( """Pre-built presentation contexts for :dcm:`Storage` containing all SOP Classes.""" _storage = [ - "1.2.840.10008.5.1.4.1.1.1", # ComputedRadiographyImageStorage - "1.2.840.10008.5.1.4.1.1.2", # "CTImageStorage": - "1.2.840.10008.5.1.4.1.1.2.1", # "EnhancedCTImageStorage": - "1.2.840.10008.5.1.4.1.1.3.1", # "UltrasoundMultiFrameImageStorage": - "1.2.840.10008.5.1.4.1.1.4", # "MRImageStorage": - "1.2.840.10008.5.1.4.1.1.4.1", # "EnhancedMRImageStorage": - "1.2.840.10008.5.1.4.1.1.4.2", # "MRSpectroscopyStorage": - "1.2.840.10008.5.1.4.1.1.4.3", # "EnhancedMRColorImageStorage": - "1.2.840.10008.5.1.4.1.1.6.1", # "UltrasoundImageStorage": - "1.2.840.10008.5.1.4.1.1.6.2", # "EnhancedUSVolumeStorage": - "1.2.840.10008.5.1.4.1.1.6.3", # "PhotoacousticImageStorage": - "1.2.840.10008.5.1.4.1.1.7", # "SecondaryCaptureImageStorage": - "1.2.840.10008.5.1.4.1.1.7.1", # "MultiFrameSingleBitSecondaryCaptureImageStorage": - "1.2.840.10008.5.1.4.1.1.7.2", # "MultiFrameGrayscaleByteSecondaryCaptureImageStorage": - "1.2.840.10008.5.1.4.1.1.7.3", # MultiFrameGrayscaleWordSecondaryCaptureImageStorage - "1.2.840.10008.5.1.4.1.1.7.4", # MultiFrameTrueColorSecondaryCaptureImageStorage - "1.2.840.10008.5.1.4.1.1.9.1.1", # TwelveLeadECGWaveformStorage - "1.2.840.10008.5.1.4.1.1.9.1.2", # GeneralECGWaveformStorage - "1.2.840.10008.5.1.4.1.1.9.1.3", # AmbulatoryECGWaveformStorage - "1.2.840.10008.5.1.4.1.1.9.1.4", # General32bitECGWaveformStorage - "1.2.840.10008.5.1.4.1.1.9.2.1", # HemodynamicWaveformStorage - "1.2.840.10008.5.1.4.1.1.9.3.1", # CardiacElectrophysiologyWaveformStorage - "1.2.840.10008.5.1.4.1.1.9.4.1", # BasicVoiceAudioWaveformStorage - "1.2.840.10008.5.1.4.1.1.9.4.2", # GeneralAudioWaveformStorage - "1.2.840.10008.5.1.4.1.1.9.5.1", # ArterialPulseWaveformStorage - "1.2.840.10008.5.1.4.1.1.9.6.1", # RespiratoryWaveformStorage - "1.2.840.10008.5.1.4.1.1.9.6.2", # MultichannelRespiratoryWaveformStorage - "1.2.840.10008.5.1.4.1.1.9.7.1", # RoutineScalpElectroencephalogramWaveformStorage - "1.2.840.10008.5.1.4.1.1.9.7.2", # ElectromyogramWaveformStorage - "1.2.840.10008.5.1.4.1.1.9.7.3", # ElectrooculogramWaveformStorage - "1.2.840.10008.5.1.4.1.1.9.7.4", # SleepElectroencephalogramWaveformStorage - "1.2.840.10008.5.1.4.1.1.9.8.1", # BodyPositionWaveformStorage - "1.2.840.10008.5.1.4.1.1.12.1", # XRayAngiographicImageStorage - "1.2.840.10008.5.1.4.1.1.12.1.1", # EnhancedXAImageStorage - "1.2.840.10008.5.1.4.1.1.12.2", # XRayRadiofluoroscopicImageStorage - "1.2.840.10008.5.1.4.1.1.12.2.1", # EnhancedXRFImageStorage - "1.2.840.10008.5.1.4.1.1.13.1.1", # XRay3DAngiographicImageStorage - "1.2.840.10008.5.1.4.1.1.13.1.2", # XRay3DCraniofacialImageStorage - "1.2.840.10008.5.1.4.1.1.13.1.3", # BreastTomosynthesisImageStorage - "1.2.840.10008.5.1.4.1.1.20", # NuclearMedicineImageStorage - "1.2.840.10008.5.1.4.1.1.30", # ParametricMapStorage - "1.2.840.10008.5.1.4.1.1.66", # RawDataStorage - "1.2.840.10008.5.1.4.1.1.66.1", # SpatialRegistrationStorage - "1.2.840.10008.5.1.4.1.1.66.2", # SpatialFiducialsStorage - "1.2.840.10008.5.1.4.1.1.66.3", # DeformableSpatialRegistrationStorage - "1.2.840.10008.5.1.4.1.1.66.4", # SegmentationStorage - "1.2.840.10008.5.1.4.1.1.66.5", # SurfaceSegmentationStorage - "1.2.840.10008.5.1.4.1.1.66.6", # TractographyResultsStorage - "1.2.840.10008.5.1.4.1.1.67", # RealWorldValueMappingStorage - "1.2.840.10008.5.1.4.1.1.68.1", # SurfaceScanMeshStorage - "1.2.840.10008.5.1.4.1.1.68.2", # SurfaceScanPointCloudStorage - "1.2.840.10008.5.1.4.1.1.77.1.1", # VLEndoscopicImageStorage - "1.2.840.10008.5.1.4.1.1.77.1.1.1", # VideoEndoscopicImageStorage - "1.2.840.10008.5.1.4.1.1.77.1.2", # VLMicroscopicImageStorage - "1.2.840.10008.5.1.4.1.1.77.1.2.1", # VideoMicroscopicImageStorage - "1.2.840.10008.5.1.4.1.1.77.1.3", # VLSlideCoordinatesMicroscopicImageStorage - "1.2.840.10008.5.1.4.1.1.77.1.4", # VLPhotographicImageStorage - "1.2.840.10008.5.1.4.1.1.77.1.4.1", # VideoPhotographicImageStorage - "1.2.840.10008.5.1.4.1.1.77.1.5.1", # OphthalmicPhotography8BitImageStorage - "1.2.840.10008.5.1.4.1.1.77.1.5.2", # OphthalmicPhotography16BitImageStorage - "1.2.840.10008.5.1.4.1.1.77.1.5.3", # StereometricRelationshipStorage - "1.2.840.10008.5.1.4.1.1.77.1.5.4", # OphthalmicTomographyImageStorage - "1.2.840.10008.5.1.4.1.1.77.1.5.5", # WideFieldOphthalmicPhotographyStereographicProjectionImageStorage - "1.2.840.10008.5.1.4.1.1.77.1.5.6", # WideFieldOphthalmicPhotography3DCoordinatesImageStorage - "1.2.840.10008.5.1.4.1.1.77.1.5.7", # OphthalmicOpticalCoherenceTomographyEnFaceImageStorage - "1.2.840.10008.5.1.4.1.1.77.1.5.8", # OphthlamicOpticalCoherenceTomographyBscanVolumeAnalysisStorage - "1.2.840.10008.5.1.4.1.1.77.1.6", # VLWholeSlideMicroscopyImageStorage - "1.2.840.10008.5.1.4.1.1.77.1.7", # DermoscopicPhotographyImageStorage - "1.2.840.10008.5.1.4.1.1.78.1", # LensometryMeasurementsStorage - "1.2.840.10008.5.1.4.1.1.78.2", # AutorefractionMeasurementsStorage - "1.2.840.10008.5.1.4.1.1.78.3", # KeratometryMeasurementsStorage - "1.2.840.10008.5.1.4.1.1.78.4", # SubjectiveRefractionMeasurementsStorage - "1.2.840.10008.5.1.4.1.1.78.5", # VisualAcuityMeasurementsStorage - "1.2.840.10008.5.1.4.1.1.78.6", # SpectaclePrescriptionReportStorage - "1.2.840.10008.5.1.4.1.1.78.7", # OphthalmicAxialMeasurementsStorage - "1.2.840.10008.5.1.4.1.1.78.8", # IntraocularLensCalculationsStorage - "1.2.840.10008.5.1.4.1.1.79.1", # MacularGridThicknessAndVolumeReportStorage - "1.2.840.10008.5.1.4.1.1.80.1", # OphthalmicVisualFieldStaticPerimetryMeasurementsStorage - "1.2.840.10008.5.1.4.1.1.81.1", # OphthalmicThicknessMapStorage - "1.2.840.10008.5.1.4.1.1.82.1", # CornealTopographyMapStorage - "1.2.840.10008.5.1.4.1.1.88.11", # BasicTextSRStorage - "1.2.840.10008.5.1.4.1.1.88.22", # EnhancedSRStorage - "1.2.840.10008.5.1.4.1.1.88.33", # ComprehensiveSRStorage - "1.2.840.10008.5.1.4.1.1.88.34", # Comprehensive3DSRStorage - "1.2.840.10008.5.1.4.1.1.88.35", # ExtensibleSRStorage - "1.2.840.10008.5.1.4.1.1.88.50", # MammographyCADSRStorage - "1.2.840.10008.5.1.4.1.1.88.65", # ChestCADSRStorage - "1.2.840.10008.5.1.4.1.1.88.67", # XRayRadiationDoseSRStorage - "1.2.840.10008.5.1.4.1.1.88.68", # RadiopharmaceuticalRadiationDoseSRStorage - "1.2.840.10008.5.1.4.1.1.88.69", # ColonCADSRStorage - "1.2.840.10008.5.1.4.1.1.88.70", # ImplantationPlanSRStorage - "1.2.840.10008.5.1.4.1.1.88.71", # AcquisitionContextSRStorage - "1.2.840.10008.5.1.4.1.1.88.72", # SimplifiedAdultEchoSRStorage - "1.2.840.10008.5.1.4.1.1.88.73", # PatientRadiationDoseSRStorage - "1.2.840.10008.5.1.4.1.1.88.76", # EnhancedXRayRadiationDoseSRStorage - "1.2.840.10008.5.1.4.1.1.91.1", # MicroscopyBulkSimpleAnnotationsStorage - "1.2.840.10008.5.1.4.1.1.104.1", # EncapsulatedPDFStorage - "1.2.840.10008.5.1.4.1.1.104.2", # EncapsulatedCDAStorage - "1.2.840.10008.5.1.4.1.1.104.3", # EncapsulatedSTLStorage - "1.2.840.10008.5.1.4.1.1.104.4", # EncapsulatedOBJStorage - "1.2.840.10008.5.1.4.1.1.104.5", # EncapsulatedMTLStorage - "1.2.840.10008.5.1.4.1.1.128", # PositronEmissionTomographyImageStorage - "1.2.840.10008.5.1.4.1.1.130", # EnhancedPETImageStorage - "1.2.840.10008.5.1.4.1.1.481.1", # RTImageStorage - "1.2.840.10008.5.1.4.1.1.481.2", # RTDoseStorage - "1.2.840.10008.5.1.4.1.1.481.3", # RTStructureSetStorage - "1.2.840.10008.5.1.4.1.1.481.4", # RTBeamsTreatmentRecordStorage - "1.2.840.10008.5.1.4.1.1.481.5", # RTPlanStorage - "1.2.840.10008.5.1.4.1.1.481.6", # RTBrachyTreatmentRecordStorage - "1.2.840.10008.5.1.4.1.1.481.7", # RTTreatmentSummaryRecordStorage - "1.2.840.10008.5.1.4.1.1.481.8", # RTIonPlanStorage - "1.2.840.10008.5.1.4.1.1.481.9", # RTIonBeamsTreatmentRecordStorage - "1.2.840.10008.5.1.4.1.1.481.10", # RTPhysicianIntentStorage - "1.2.840.10008.5.1.4.1.1.481.11", # RTSegmentAnnotationStorage - "1.2.840.10008.5.1.4.1.1.481.12", # RTRadiationSetStorage - "1.2.840.10008.5.1.4.1.1.481.13", # CArmPhotonElectronRadiationStorage - "1.2.840.10008.5.1.4.1.1.481.14", # TomotherapeuticRadiationStorage - "1.2.840.10008.5.1.4.1.1.481.15", # RoboticArmRadiationStorage - "1.2.840.10008.5.1.4.1.1.481.18", # TomotherapeuticRadiationRecordStorage - "1.2.840.10008.5.1.4.1.1.481.19", # CArmPhotonElectronRadiationRecordStorage - "1.2.840.10008.5.1.4.1.1.481.20", # RoboticArmRadiationRecordStorage - "1.2.840.10008.5.1.4.1.1.481.21", # RTRadiationSetDeliveryInstructionStorage - "1.2.840.10008.5.1.4.1.1.481.22", # RTTreatmentPreparationStorage - "1.2.840.10008.5.1.4.1.1.481.23", # EnhancedRTImageStorage - "1.2.840.10008.5.1.4.1.1.481.24", # EnhancedContinuousRTImageStorage - "1.2.840.10008.5.1.4.1.1.481.25", # RTPatientPositionAcquisitionInstructionStorage - "1.2.840.10008.5.1.4.34.7", # RTBeamsDeliveryInstructionStorage - "1.2.840.10008.5.1.4.34.10", # RTBrachyApplicationSetupDeliveryInstructionsStorage + "1.2.840.10008.5.1.4.1.1.9.1.3", # AmbulatoryECGWaveformStorage + "1.2.840.10008.5.1.4.1.1.9.5.1", # ArterialPulseWaveformStorage + "1.2.840.10008.5.1.4.1.1.78.2", # AutorefractionMeasurementsStorage + "1.2.840.10008.5.1.4.1.1.131", # BasicStructuredDisplayStorage + "1.2.840.10008.5.1.4.1.1.88.11", # BasicTextSRStorage + "1.2.840.10008.5.1.4.1.1.9.4.1", # BasicVoiceAudioWaveformStorage + "1.2.840.10008.5.1.4.1.1.11.4", # BlendingSoftcopyPresentationStateStorage + "1.2.840.10008.5.1.4.1.1.13.1.3", # BreastTomosynthesisImageStorage + "1.2.840.10008.5.1.4.1.1.9.3.1", # CardiacElectrophysiologyWaveformStorage + "1.2.840.10008.5.1.4.1.1.88.65", # ChestCADSRStorage + "1.2.840.10008.5.1.4.1.1.88.69", # ColonCADSRStorage + "1.2.840.10008.5.1.4.1.1.11.2", # ColorSoftcopyPresentationStateStorage + "1.2.840.10008.5.1.4.1.1.88.34", # Comprehensive3DSRStorage + "1.2.840.10008.5.1.4.1.1.88.33", # ComprehensiveSRStorage + "1.2.840.10008.5.1.4.1.1.1", # ComputedRadiographyImageStorage + "1.2.840.10008.5.1.4.1.1.2", # CTImageStorage + "1.2.840.10008.5.1.4.1.1.66.3", # DeformableSpatialRegistrationStorage + "1.2.840.10008.5.1.4.1.1.1.3", # DigitalIntraOralXRayImageStorageForPresentation + "1.2.840.10008.5.1.4.1.1.1.3.1", # DigitalIntraOralXRayImageStorageForProcessing + "1.2.840.10008.5.1.4.1.1.1.2", # DigitalMammographyXRayImageStorageForPresentation + "1.2.840.10008.5.1.4.1.1.1.2.1", # DigitalMammographyXRayImageStorageForProcessing + "1.2.840.10008.5.1.4.1.1.1.1", # DigitalXRayImageStorageForPresentation + "1.2.840.10008.5.1.4.1.1.1.1.1", # DigitalXRayImageStorageForProcessing + "1.2.840.10008.5.1.4.1.1.104.2", # EncapsulatedCDAStorage + "1.2.840.10008.5.1.4.1.1.104.1", # EncapsulatedPDFStorage + "1.2.840.10008.5.1.4.1.1.2.1", # EnhancedCTImageStorage + "1.2.840.10008.5.1.4.1.1.4.3", # EnhancedMRColorImageStorage + "1.2.840.10008.5.1.4.1.1.4.1", # EnhancedMRImageStorage + "1.2.840.10008.5.1.4.1.1.130", # EnhancedPETImageStorage + "1.2.840.10008.5.1.4.1.1.88.22", # EnhancedSRStorage + "1.2.840.10008.5.1.4.1.1.6.2", # EnhancedUSVolumeStorage + "1.2.840.10008.5.1.4.1.1.12.1.1", # EnhancedXAImageStorage + "1.2.840.10008.5.1.4.1.1.12.2.1", # EnhancedXRFImageStorage + "1.2.840.10008.5.1.4.1.1.9.4.2", # GeneralAudioWaveformStorage + "1.2.840.10008.5.1.4.1.1.9.1.2", # GeneralECGWaveformStorage + "1.2.840.10008.5.1.4.1.1.11.1", # GrayscaleSoftcopyPresentationStateStorage + "1.2.840.10008.5.1.4.1.1.9.2.1", # HemodynamicWaveformStorage + "1.2.840.10008.5.1.4.1.1.88.70", # ImplantationPlanSRStorage + "1.2.840.10008.5.1.4.1.1.78.8", # IntraocularLensCalculationsStorage + "1.2.840.10008.5.1.4.1.1.14.1", # IntravascularOpticalCoherenceTomographyImageStorageForPresentation + "1.2.840.10008.5.1.4.1.1.14.2", # IntravascularOpticalCoherenceTomographyImageStorageForProcessing + "1.2.840.10008.5.1.4.1.1.78.3", # KeratometryMeasurementsStorage + "1.2.840.10008.5.1.4.1.1.88.59", # KeyObjectSelectionDocumentStorage + "1.2.840.10008.5.1.4.1.1.2.2", # LegacyConvertedEnhancedCTImageStorage + "1.2.840.10008.5.1.4.1.1.4.4", # LegacyConvertedEnhancedMRImageStorage + "1.2.840.10008.5.1.4.1.1.128.1", # LegacyConvertedEnhancedPETImageStorage + "1.2.840.10008.5.1.4.1.1.78.1", # LensometryMeasurementsStorage + "1.2.840.10008.5.1.4.1.1.79.1", # MacularGridThicknessAndVolumeReportStorage + "1.2.840.10008.5.1.4.1.1.88.50", # MammographyCADSRStorage + "1.2.840.10008.5.1.4.1.1.4", # MRImageStorage + "1.2.840.10008.5.1.4.1.1.4.2", # MRSpectroscopyStorage + "1.2.840.10008.5.1.4.1.1.7.2", # MultiframeGrayscaleByteSecondaryCaptureImageStorage + "1.2.840.10008.5.1.4.1.1.7.3", # MultiframeGrayscaleWordSecondaryCaptureImageStorage + "1.2.840.10008.5.1.4.1.1.7.1", # MultiframeSingleBitSecondaryCaptureImageStorage + "1.2.840.10008.5.1.4.1.1.7.4", # MultiframeTrueColorSecondaryCaptureImageStorage + "1.2.840.10008.5.1.4.1.1.20", # NuclearMedicineImageStorage + "1.2.840.10008.5.1.4.1.1.78.7", # OphthalmicAxialMeasurementsStorage + "1.2.840.10008.5.1.4.1.1.77.1.5.2", # OphthalmicPhotography16BitImageStorage + "1.2.840.10008.5.1.4.1.1.77.1.5.1", # OphthalmicPhotography8BitImageStorage + "1.2.840.10008.5.1.4.1.1.81.1", # OphthalmicThicknessMapStorage + "1.2.840.10008.5.1.4.1.1.77.1.5.4", # OphthalmicTomographyImageStorage + "1.2.840.10008.5.1.4.1.1.80.1", # OphthalmicVisualFieldStaticPerimetryMeasurementsStorage + "1.2.840.10008.5.1.4.1.1.128", # PositronEmissionTomographyImageStorage + "1.2.840.10008.5.1.4.1.1.88.40", # ProcedureLogStorage + "1.2.840.10008.5.1.4.1.1.11.3", # PseudoColorSoftcopyPresentationStateStorage + "1.2.840.10008.5.1.4.1.1.66", # RawDataStorage + "1.2.840.10008.5.1.4.1.1.67", # RealWorldValueMappingStorage + "1.2.840.10008.5.1.4.1.1.9.6.1", # RespiratoryWaveformStorage + "1.2.840.10008.5.1.4.34.7", # RTBeamsDeliveryInstructionStorage + "1.2.840.10008.5.1.4.1.1.481.4", # RTBeamsTreatmentRecordStorage + "1.2.840.10008.5.1.4.1.1.481.6", # RTBrachyTreatmentRecordStorage + "1.2.840.10008.5.1.4.1.1.481.2", # RTDoseStorage + "1.2.840.10008.5.1.4.1.1.481.1", # RTImageStorage + "1.2.840.10008.5.1.4.1.1.481.9", # RTIonBeamsTreatmentRecordStorage + "1.2.840.10008.5.1.4.1.1.481.8", # RTIonPlanStorage + "1.2.840.10008.5.1.4.1.1.481.5", # RTPlanStorage + "1.2.840.10008.5.1.4.1.1.481.3", # RTStructureSetStorage + "1.2.840.10008.5.1.4.1.1.481.7", # RTTreatmentSummaryRecordStorage + "1.2.840.10008.5.1.4.1.1.7", # SecondaryCaptureImageStorage + "1.2.840.10008.5.1.4.1.1.66.4", # SegmentationStorage + "1.2.840.10008.5.1.4.1.1.66.2", # SpatialFiducialsStorage + "1.2.840.10008.5.1.4.1.1.66.1", # SpatialRegistrationStorage + "1.2.840.10008.5.1.4.1.1.78.6", # SpectaclePrescriptionReportStorage + "1.2.840.10008.5.1.4.1.1.77.1.5.3", # StereometricRelationshipStorage + "1.2.840.10008.5.1.4.1.1.78.4", # SubjectiveRefractionMeasurementsStorage + "1.2.840.10008.5.1.4.1.1.68.1", # SurfaceScanMeshStorage + "1.2.840.10008.5.1.4.1.1.68.2", # SurfaceScanPointCloudStorage + "1.2.840.10008.5.1.4.1.1.66.5", # SurfaceSegmentationStorage + "1.2.840.10008.5.1.4.1.1.9.1.1", # TwelveLeadECGWaveformStorage + "1.2.840.10008.5.1.4.1.1.6.1", # UltrasoundImageStorage + "1.2.840.10008.5.1.4.1.1.3.1", # UltrasoundMultiframeImageStorage + "1.2.840.10008.5.1.4.1.1.77.1.1.1", # VideoEndoscopicImageStorage + "1.2.840.10008.5.1.4.1.1.77.1.2.1", # VideoMicroscopicImageStorage + "1.2.840.10008.5.1.4.1.1.77.1.4.1", # VideoPhotographicImageStorage + "1.2.840.10008.5.1.4.1.1.78.5", # VisualAcuityMeasurementsStorage + "1.2.840.10008.5.1.4.1.1.77.1.1", # VLEndoscopicImageStorage + "1.2.840.10008.5.1.4.1.1.77.1.2", # VLMicroscopicImageStorage + "1.2.840.10008.5.1.4.1.1.77.1.4", # VLPhotographicImageStorage + "1.2.840.10008.5.1.4.1.1.77.1.3", # VLSlideCoordinatesMicroscopicImageStorage + "1.2.840.10008.5.1.4.1.1.77.1.6", # VLWholeSlideMicroscopyImageStorage + "1.2.840.10008.5.1.4.1.1.11.5", # XAXRFGrayscaleSoftcopyPresentationStateStorage + "1.2.840.10008.5.1.4.1.1.13.1.1", # XRay3DAngiographicImageStorage + "1.2.840.10008.5.1.4.1.1.13.1.2", # XRay3DCraniofacialImageStorage + "1.2.840.10008.5.1.4.1.1.12.1", # XRayAngiographicImageStorage + "1.2.840.10008.5.1.4.1.1.88.67", # XRayRadiationDoseSRStorage + "1.2.840.10008.5.1.4.1.1.12.2", # XRayRadiofluoroscopicImageStorage + ## retired but still in use + "1.2.840.10008.5.1.1.30", # HardcopyColorImageStorage + "1.2.840.10008.5.1.1.29", # HardcopyGrayscaleImageStorage + "1.2.840.10008.5.1.4.1.1.5", # NuclearMedicineImageStorageRetired + "1.2.840.10008.5.1.4.1.1.9", # StandaloneCurveStorage + "1.2.840.10008.5.1.4.1.1.10", # StandaloneModalityLUTStorage + "1.2.840.10008.5.1.4.1.1.8", # StandaloneOverlayStorage + "1.2.840.10008.5.1.4.1.1.129", # StandalonePETCurveStorage + "1.2.840.10008.5.1.4.1.1.11", # StandaloneVOILUTStorage + "1.2.840.10008.5.1.1.27", # StoredPrintStorage + "1.2.840.10008.5.1.4.1.1.6", # UltrasoundImageStorageRetired + "1.2.840.10008.5.1.4.1.1.3", # UltrasoundMultiframeImageStorageRetired + "1.2.840.10008.5.1.4.1.1.77.1", # VLImageStorage + "1.2.840.10008.5.1.4.1.1.77.2", # VLMultiframeImageStorage + "1.2.840.10008.5.1.4.1.1.12.3", # XRayAngiographicBiPlaneImageStorage ] -assert len(_storage) <= 128 +assert len(_storage) <= 120 StoragePresentationContexts = [build_context(uid) for uid in sorted(_storage)] -"""Pre-built presentation contexts for :dcm:`Storage` containing 128 selected SOP Classes.""" +"""Pre-built presentation contexts for :dcm:`Storage` containing 120 selected SOP Classes.""" StorageCommitmentPresentationContexts = [ build_context(uid) for uid in sorted(_STORAGE_COMMITMENT_CLASSES.values()) diff --git a/pynetdicom/tests/test_presentation.py b/pynetdicom/tests/test_presentation.py index 29a5f7418..fef0f7e62 100644 --- a/pynetdicom/tests/test_presentation.py +++ b/pynetdicom/tests/test_presentation.py @@ -2153,14 +2153,17 @@ def test_rt_machine(self): def test_storage(self): """Test the storage service presentation contexts""" contexts = StoragePresentationContexts - assert len(contexts) == 128 + assert len(contexts) == 120 + + # If this assert fails and the previous passes, there is a duplicate in the list + assert len(contexts) == len(set(contexts)) for context in contexts: assert context.transfer_syntax == DEFAULT_TRANSFER_SYNTAXES assert context.context_id is None - assert contexts[0].abstract_syntax == "1.2.840.10008.5.1.4.1.1.1" - assert contexts[80].abstract_syntax == "1.2.840.10008.5.1.4.1.1.77.1.6" + assert contexts[0].abstract_syntax == "1.2.840.10008.5.1.1.27" + assert contexts[80].abstract_syntax == "1.2.840.10008.5.1.4.1.1.77.1.5.1" assert contexts[-1].abstract_syntax == "1.2.840.10008.5.1.4.34.7" def test_storage_commitement(self): diff --git a/pynetdicom/tests/test_service_qr.py b/pynetdicom/tests/test_service_qr.py index bbb601e62..e4dd1212b 100644 --- a/pynetdicom/tests/test_service_qr.py +++ b/pynetdicom/tests/test_service_qr.py @@ -3109,11 +3109,11 @@ def handle_store(event): self.ae = ae = AE() ae.add_supported_context(PatientRootQueryRetrieveInformationModelGet) - ae.requested_contexts = StoragePresentationContexts[:120] + ae.requested_contexts = StoragePresentationContexts ae.add_requested_context(PatientRootQueryRetrieveInformationModelGet) roles = [] - for cx in StoragePresentationContexts[:120]: + for cx in StoragePresentationContexts: roles.append(build_role(cx.abstract_syntax, scp_role=True)) ae.add_supported_context(cx.abstract_syntax, scu_role=False, scp_role=True)