tests.test_transport_dicomtransport — imagedata 1.3.0 documentation

# Source code for tests.test_transport_dicomtransport

    import unittest
    import os.path
    import tempfile
    import numpy as np
    import argparse
    from pydicom.dataset import Dataset
    from pynetdicom import (
        AE, evt,
        StoragePresentationContexts,
        PYNETDICOM_IMPLEMENTATION_UID,
        PYNETDICOM_IMPLEMENTATION_VERSION
    )

    from .context import imagedata
    import imagedata.cmdline
    import imagedata.readdata
    import imagedata.formats
    import imagedata.transports
    from imagedata.series import Series

    scpdir = None

    class TestDicomTransport(unittest.TestCase):
        def setUp(self):
            parser = argparse.ArgumentParser()
            imagedata.cmdline.add_argparse_options(parser)

            self.opts = parser.parse_args([])
            if len(self.opts.output_format) < 1:
                self.opts.output_format = ['dicom']

            self.opts_calling_aet = parser.parse_args(['--calling_aet', 'Temp'])
            if len(self.opts_calling_aet.output_format) < 1:
                self.opts_calling_aet.output_format = ['dicom']

            plugins = imagedata.formats.get_plugins_list()
            self.dicom_plugin = None
            for pname, ptype, pclass in plugins:
                if ptype == 'dicom':
                    self.dicom_plugin = pclass
            self.assertIsNotNone(self.dicom_plugin)
            self.setupDicomSCP(port=11112)

        def setupDicomSCP(self, port=11112):
            global scpdir
            ae = AE()
            ae.ae_title = 'Temp'
            ae.supported_contexts = StoragePresentationContexts
            # ae.on_c_store = self.on_c_store
            handlers = [(evt.EVT_C_STORE, self.handle_store)]
            # Returns a ThreadedAssociationServer instance
            self.server = ae.start_server(('localhost', port), block=False, evt_handlers=handlers)
            scpdir = tempfile.TemporaryDirectory()

        def tearDown(self):
            global scpdir
            self.server.shutdown()
            # noinspection PyUnresolvedReferences
            scpdir.cleanup()

        # Implement a handler evt.EVT_C_STORE
        # @staticmethod
        # def on_c_store(ds, context, info):
        @staticmethod
        def handle_store(event):
            """Store the pydicom Dataset `ds`.

            Parameters
            ----------
            event : pydicom.event

            Returns
            -------
            status : int or pydicom.dataset.Dataset
                The status returned to the peer AE in the C-STORE response. Must be
                a valid C-STORE status value for the applicable Service Class as
                either an ``int`` or a ``Dataset`` object containing (at a
                minimum) a (0000,0900) *Status* element.
            """
            global scpdir
            ds = event.dataset
            context = event.context

            # logging.debug('on_c_store: info {}'.format(info))
            # calling_aet = info['requestor']['ae_title']
            # called_aet = info['acceptor']['ae_title']
            # logging.debug('on_c_store: calling_aet {}'.format(calling_aet))
            # logging.debug('on_c_store: called_aet {}'.format(called_aet))

            # Add the DICOM File Meta Information
            meta = Dataset()
            meta.MediaStorageSOPClassUID = ds.SOPClassUID
            meta.MediaStorageSOPInstanceUID = ds.SOPInstanceUID
            meta.ImplementationClassUID = PYNETDICOM_IMPLEMENTATION_UID
            meta.ImplementationVersionName = PYNETDICOM_IMPLEMENTATION_VERSION
            meta.TransferSyntaxUID = context.transfer_syntax

            # Add the file meta to the dataset
            ds.file_meta = meta

            # Set the transfer syntax attributes of the dataset
            ds.is_little_endian = context.transfer_syntax.is_little_endian
            ds.is_implicit_VR = context.transfer_syntax.is_implicit_VR

            # Save the dataset using the SOP Instance UID as the filename
            ds.save_as(
                os.path.join(scpdir.name, ds.SOPInstanceUID),
                write_like_original=False)

            # Return a 'Success' status
            return 0x0000

        # @unittest.skip("skipping test_transport_single_image")
        def test_transport_single_image(self):
            si1 = Series(
                os.path.join('data', 'dicom', 'time', 'time00', 'Image_00000.dcm')
            )
            si1.write('dicom://localhost:11112/Temp', formats=['dicom'])
            si2 = Series(
                scpdir.name
            )
            # compare_headers(self, si1, si2)
            self.assertEqual(si1.dtype, si2.dtype)
            self.assertEqual(si1.shape, si2.shape)
            np.testing.assert_array_equal(si1, si2)

        # @unittest.skip("skipping test_transport_single_image_calling_aet")
        def test_transport_single_image_calling_aet(self):
            si1 = Series(
                os.path.join('data', 'dicom', 'time', 'time00', 'Image_00000.dcm')
            )
            si1.write(
                'dicom://localhost:11112/Temp',
                formats=['dicom'],
                opts=self.opts_calling_aet
            )

        @unittest.skip("skipping test_transport_walk")
        def test_transport_walk(self):
            patID = '123456'
            stuInsUID = '1.2.3.4'
            serInsUID = '1.2.3.4.5'
            accno = '98765'
            transport = imagedata.transports.Transport(
                'dicom://localhost:11112/Temp')
            for root, dirs, files in transport.walk('{}/*cerebrum*'.format(patID)):
                print(dirs, files)
                for dir in dirs:
                    info = transport.info('{}/{}'.format(root, dir))
                    print(info)
                break
            for root, dirs, files in transport.walk('{}/{}/*'.format(patID, stuInsUID)):
                print(dirs, files)
                for dir in dirs:
                    info = transport.info('{}/{}'.format(root, dir))
                    print(info)
                break
            for root, dirs, files in transport.walk('{}/{}/{}/*'.format(patID, stuInsUID, serInsUID)):
                print(dirs, files)
                for dir in dirs:
                    print(dir)
                for filename in files:
                    info = transport.info('{}/{}'.format(root, filename))
                    print(filename)
                break
            transport.close()

        @unittest.skip("skipping test_transport_cget_series")
        def test_transport_cget_series(self):
            patID = '123456'
            stuInsUID = '1.2.3.4'
            serInsUID = '1.2.3.4.5'
            accno = '98765'
            serNum = 4
            si1 = Series('dicom://localhost:11112/Temp/{}/{}/{}'.format(
                patID, stuInsUID, serInsUID
            ))
            print(si1.shape, si1.spacing, si1.patientName, si1.accessionNumber, si1.seriesNumber)
            si2 = Series('dicom://localhost:11112/Temp/{}/{}/{}'.format(
                patID, accno, serNum
            ))
            print(si2.shape, si2.spacing, si2.patientName, si2.accessionNumber, si2.seriesNumber)