예제 #1
0
 def __init__(self,
              port=1234,
              aet='ACME1',
              output='out',
              implicit=None,
              explicit=None):
     self.remoteAE = None
     self.onDicomSaved = None
     self.import_folder = None
     self.logger = logging.getLogger(__name__)
     if implicit:
         ts = [ImplicitVRLittleEndian]
     elif explicit:
         ts = [ExplicitVRLittleEndian]
     else:
         ts = [
             ExplicitVRLittleEndian, ImplicitVRLittleEndian,
             ExplicitVRBigEndian
         ]
     self.port = port
     self.aet = aet
     self.output = output
     self.logger.info("Creating local AE='%s' port=%d" % (aet, port))
     self.MyAE = AE(aet, port, [
         StudyRootFindSOPClass, StudyRootMoveSOPClass,
         PatientRootFindSOPClass, PatientRootMoveSOPClass,
         VerificationSOPClass
     ], [StorageSOPClass], ts)
     self.MyAE.OnAssociateResponse = self.OnAssociateResponse
     self.MyAE.OnAssociateRequest = self.OnAssociateRequest
     self.MyAE.OnReceiveStore = self.OnReceiveStore
예제 #2
0
    def check_send_dicom(self):

        ts = [
            ExplicitVRLittleEndian, ImplicitVRLittleEndian, ExplicitVRBigEndian
        ]

        # create application entity with Find and Move SOP classes as SCU and
        # Storage SOP class as SCP
        MyAE = AE("DCMTK", 9999, [
            PatientRootFindSOPClass, PatientRootMoveSOPClass,
            VerificationSOPClass
        ], [StorageSOPClass], ts)
        MyAE.OnAssociateResponse = OnAssociateResponse
        MyAE.OnAssociateRequest = OnAssociateRequest
        MyAE.OnReceiveStore = OnReceiveStore
        MyAE.start()

        # remote application entity
        PrismaAE = dict(Address="134.157.205.1", Port=104, AET="AN_MRC35181")

        # create association with remote AE
        self.log.info("Request association on PRISMA")

        assoc = MyAE.RequestAssociation(PrismaAE)

        # perform a DICOM ECHO
        st = assoc.VerificationSOPClass.SCU(1)
        self.log.info('DICOM Echo done with status "%s"', st)

        try:
            self.check_send_dicom_from_remoteAE(assoc)
        except Exception as e:
            self.log.warning('CODE ERROR because of %s', e)

        assoc.Release(0)

        # AGAIN with VERIO
        VerioAE = dict(Address="134.157.205.51", Port=104, AET="MRC40527")

        # create association with remote AE
        self.log.info("Request association on VERIO")

        assoc = MyAE.RequestAssociation(VerioAE)

        # perform a DICOM ECHO
        st = assoc.VerificationSOPClass.SCU(1)
        self.log.info('DICOM Echo done with status "%s"', st)

        #try :
        self.check_send_dicom_from_remoteAE(assoc)
        #except Exception as e:
        #    self.log.warning('CODE ERROR because of %s',e)

        assoc.Release(0)

        MyAE.Quit()
예제 #3
0
def dcm_ser_level_find(aet, node, port, laet, patid, studyuid):
    ''' Use pynetdicom to perform a series level query. The result is a list
        of SeriesLevelFields records.
    '''
    global msg_id
    msg_id += 1

    # Create application entity and association with remote AE (port number of 0 to stop it putting up a listen)
    ae = AE(laet, port=0, SOPSCU=[PatientRootFindSOPClass], SOPSCP=[])
    ae.start()
    assoc = ae.RequestAssociation({'Address': node, 'Port': port, 'AET': aet})

    # Query object
    d = Dataset()
    d.PatientID = patid
    d.StudyInstanceUID = studyuid
    d.SeriesInstanceUID = ''
    d.Modality = ''
    d.SeriesDate = ''
    d.SeriesNumber = ''
    d.SeriesDescription = ''
    d.BodyPartExamined = ''
    d.NumberOfSeriesRelatedInstances = ''
    d.QueryRetrieveLevel = 'SERIES'

    # Request returns a generator
    responses = []
    matches = assoc.PatientRootFindSOPClass.SCU(d, msg_id)
    for state, ds in matches:
        if state == 'Pending':
            patid = ds.PatientID if 'PatientID' in ds else ''
            studyuid = ds.StudyInstanceUID if 'StudyInstanceUID' in ds else ''
            seriesuid = ds.SeriesInstanceUID if 'SeriesInstanceUID' in ds else ''
            seriesdate = ds.SeriesDate if 'SeriesDate' in ds else ''
            seriesdescr = ds.SeriesDescription if 'SeriesDescription' in ds else ''
            seriesnumber = ds.SeriesNumber if 'SeriesNumber' in ds else ''
            modality = ds.Modality if 'Modality' in ds else ''
            bodypart = ds.BodyPartExamined if 'BodyPartExamined' in ds else ''
            nimages = ds.NumberOfSeriesRelatedInstances if 'NumberOfSeriesRelatedInstances' in ds else 0
            responses.append(
                SeriesLevelFields(modality, seriesnumber, seriesuid,
                                  seriesdescr, bodypart, nimages))

    assoc.Release(0)
    ae.Quit()

    return responses
예제 #4
0
    def init(self, name, port):
        """Initialize and start AE
        """
        # setup AE
        self._ae = AE(name, port, [
            PatientRootFindSOPClass, StudyRootFindSOPClass,
            PatientRootMoveSOPClass, StudyRootMoveSOPClass,
            VerificationSOPClass
        ], [StorageSOPClass, VerificationSOPClass])

        self._ae.OnAssociateRequest = self.onAssociateRequest
        self._ae.OnAssociateResponse = self.onAssociateResponse
        self._ae.OnReceiveStore = self.onReceiveStore
        self._ae.OnReceiveEcho = self.onReceiveEcho

        self._ae.start()

        self._logger.info("AE created: " + name + ":" + str(port))
예제 #5
0
def dcm_stu_level_find(aet, node, port, laet, patid):
    ''' Use pynetdicom to perform a study level query. The result is a list
        of StudyLevelFields records.
    '''
    global msg_id
    msg_id += 1

    # Create application entity and association with remote AE (port number of 0 to stop it putting up a listen)
    ae = AE(laet, port=0, SOPSCU=[PatientRootFindSOPClass], SOPSCP=[])
    ae.start()
    assoc = ae.RequestAssociation({'Address': node, 'Port': port, 'AET': aet})

    # Query object
    d = Dataset()
    d.PatientID = patid
    d.StudyInstanceUID = ''
    d.StudyID = ''
    d.StudyDate = ''
    d.StudyDescription = ''
    d.NumberOfStudyRelatedSeries = ''
    d.QueryRetrieveLevel = 'STUDY'

    # Request returns a generator
    responses = []
    matches = assoc.PatientRootFindSOPClass.SCU(d, msg_id)
    for state, ds in matches:
        if state == 'Pending':
            patid = ds.PatientID if 'PatientID' in ds else ''
            studyid = ds.StudyID if 'StudyID' in ds else ''
            studyuid = ds.StudyInstanceUID if 'StudyInstanceUID' in ds else ''
            studydate = ds.StudyDate if 'StudyDate' in ds else ''
            studydescr = ds.StudyDescription if 'StudyDescription' in ds else ''
            nseries = ds.NumberOfStudyRelatedSeries if 'NumberOfStudyRelatedSeries' in ds else 0
            responses.append(
                StudyLevelFields(studyid, studyuid, studydate, studydescr,
                                 nseries))

    assoc.Release(0)
    ae.Quit()

    return responses
예제 #6
0
def dcm_pat_level_find(aet, node, port, laet, query_map):
    ''' Use pynetdicom to perform a patient level query. The result is a list
        of PatientLevelFields records.
    '''
    global msg_id
    msg_id += 1

    # Create application entity and association with remote AE (port number of 0 to stop it putting up a listen)
    ae = AE(laet, port=0, SOPSCU=[PatientRootFindSOPClass], SOPSCP=[])
    ae.start()
    assoc = ae.RequestAssociation({'Address': node, 'Port': port, 'AET': aet})

    # Query object
    d = Dataset()
    d.PatientID = patid
    d.PatientName = patname
    d.PatientBirthDate = birthdate
    d.PatientSex = sex
    d.NumberOfPatientRelatedStudies = ''
    d.QueryRetrieveLevel = 'PATIENT'

    # Request returns a generator
    responses = []
    matches = assoc.PatientRootFindSOPClass.SCU(d, msg_id)

    for state, ds in matches:
        if state == 'Pending':
            patname = ds.PatientName if 'PatientName' in ds else 'Unknown'
            patid = ds.PatientID if 'PatientID' in ds else ''
            patdob = ds.PatientBirthDate if 'PatientBirthDate' in ds else ''
            patsex = ds.PatientSex if 'PatientSex' in ds else ''
            nstudies = ds.NumberOfPatientRelatedStudies if 'NumberOfPatientRelatedStudies' in ds else 0
            responses.append(
                PatientLevelFields(patname, patid, patdob, patsex, nstudies))

    assoc.Release(0)
    ae.Quit()

    return responses
예제 #7
0
def dcm_img_level_find(aet, node, port, laet, patid, studyuid, seriesuid):
    ''' Use pynetdicom to perform a image level query. The result is a list
        of ImageLevelFields records.
    '''
    global msg_id
    msg_id += 1

    # Create application entity and association with remote AE (port number of 0 to stop it putting up a listen)
    ae = AE(laet, port=0, SOPSCU=[PatientRootFindSOPClass], SOPSCP=[])
    ae.start()
    assoc = ae.RequestAssociation({'Address': node, 'Port': port, 'AET': aet})

    # Query object
    d = Dataset()
    d.PatientID = patid
    d.StudyInstanceUID = studyuid
    d.SeriesInstanceUID = seriesuid
    d.SOPInstanceUID = ''
    d.InstanceNumber = ''
    d.QueryRetrieveLevel = 'IMAGE'

    # Request returns a generator
    responses = []
    matches = assoc.PatientRootFindSOPClass.SCU(d, msg_id)
    for state, ds in matches:
        if state == 'Pending':
            patid = ds.PatientID if 'PatientID' in ds else ''
            studyuid = ds.StudyInstanceUID if 'StudyInstanceUID' in ds else ''
            seriesuid = ds.SeriesInstanceUID if 'SeriesInstanceUID' in ds else ''
            imageuid = ds.SOPInstanceUID if 'SOPInstanceUID' in ds else ''
            imagenumber = ds.InstanceNumber if 'InstanceNumber' in ds else ''
            responses.append(ImageLevelFields(imageuid, imagenumber))

    assoc.Release(0)
    ae.Quit()

    return responses
예제 #8
0
def OnAssociateResponse(association):
    print "Association response received"
    print association


def OnReceiveStore(SOPclass, DS):
    assoc = MyAE.RequestAssociation(REMOTEAE)
    if assoc:
        assoc.CRImageStorageSOPClass.StoreSCU(DS, 1)
        assoc.Release(0)
        return 0
    else:
        return 1


def OnReceiveEcho(self):
    print "Echo received"


if __name__ == '__main__':
    start_dcmqrscp()

    MyAE = AE('NETDICOM', 7654, [CRImageStorageSOPClass],
              [CRImageStorageSOPClass, VerificationSOPClass])
    MyAE.OnAssociateRequest = OnAssociateRequest
    MyAE.OnAssociateResponse = OnAssociateResponse
    MyAE.OnReceiveStore = OnReceiveStore
    MyAE.OnReceiveEcho = OnReceiveEcho

    MyAE.start()
예제 #9
0
                         file_meta=file_meta,
                         preamble="\0" * 128)
        ds.update(DS)
        #ds.is_little_endian = True
        #ds.is_implicit_VR = True
        ds.save_as(filename)
        print "File %s written" % filename
    except:
        pass
    # must return appropriate status
    return SOPClass.Success


# create application entity
MyAE = AE(
    args.aet, args.p,
    [PatientRootFindSOPClass, PatientRootMoveSOPClass, VerificationSOPClass],
    [StorageSOPClass], ts)
MyAE.OnAssociateResponse = OnAssociateResponse
MyAE.OnAssociateRequest = OnAssociateRequest
MyAE.OnReceiveStore = OnReceiveStore
MyAE.start()

# remote application entity
RemoteAE = dict(Address=args.remotehost, Port=args.remoteport, AET=args.aec)

# create association with remote AE
print "Request association"
assoc = MyAE.RequestAssociation(RemoteAE)

# perform a DICOM ECHO
print "DICOM Echo ... ",
예제 #10
0
    file_meta.MediaStorageSOPInstanceUID = "1.2.3"
    file_meta.ImplementationClassUID = "1.2.3.4"  # !!! Need valid UIDs here
    filename = '/tmp/%s.dcm' % DS.SOPInstanceUID
    ds = FileDataset(filename, {}, file_meta=file_meta, preamble="\0" * 128)
    ds.update(DS)
    ds.is_little_endian = True
    ds.is_implicit_VR = True
    ds.save_as(filename)
    print "File %s written" % filename
    # must return appropriate status
    return 0


# setup AE
MyAE = AE('SPIN', 9999, [], [
    MRImageStorageSOPClass, CTImageStorageSOPClass, RTImageStorageSOPClass,
    RTPlanStorageSOPClass, VerificationSOPClass
])
MyAE.OnAssociateRequest = OnAssociateRequest
MyAE.OnAssociateResponse = OnAssociateResponse
MyAE.OnReceiveStore = OnReceiveStore
MyAE.OnReceiveEcho = OnReceiveEcho

dcmtkscu.run_in_term('storescu -d localhost 9999 ' +
                     os.path.join(testfiles_dir(), 'rtplan.dcm'))

# start AE
print "starting AE ...,"
MyAE.start()
print "done"
MyAE.QuitOnKeyboardInterrupt()
예제 #11
0
def _pynetdicom_img_get_worker(aet, node, port, laet, patid, studyuid,
                               seriesuid, imageuid, savedir, queue, returns):
    ''' Use pynetdicom to perform a series level c-get fetch. This is to be run in a separate worker thread.
        The c-store callbacks save the images and push a CStoreResponse object onto a queue for the main thread.
        The function returns normally, which will lead to the threading terminating. This is detected by the
        parent thread.
    '''
    global msg_id
    msg_id += 1

    # a slight kludge as python 2.7 doesn't have 'nonlocal' qualifier
    image_counter = [0]

    # The callback function for C-STORE sub-operations
    def on_receive_store(cget_obj, ds):
        try:
            # print 'C-STORE callback(cget=%s,instno=%d)' % (cget_obj, ds.InstanceNumber)
            # This is a bit of a hack but we need to add some file-meta
            file_meta = Dataset()
            file_meta.add_new((2, 0x01), 'OB',
                              b'\0\1')  # FileMetaInformationVersion
            file_meta.add_new((2, 0x02), 'UI',
                              ds.SOPClassUID)  # MediaStorageSOPClassUID
            file_meta.add_new((2, 0x03), 'UI',
                              ds.SOPInstanceUID)  # MediaStorageSOPInstanceUID
            file_meta.add_new((2, 0x10), 'UI',
                              ExplicitVRLittleEndian)  # TransferSyntaxUID
            file_meta.add_new((2, 0x12), 'UI',
                              '1.2.40.0.13.1.1')  # ImplementationClassUID
            file_meta.add_new((2, 0x13), 'SH',
                              'pynetdicom')  # ImplementationVersionName
            ds.file_meta = file_meta
            # and specify the encoding
            ds.is_implicit_VR = False
            ds.is_little_endian = True

            save_path = os.path.join(savedir,
                                     '%05d.dcm' % (image_counter[0] + 1))
            # the WriteLikeOriginal=False flag is need to get preamble etc right
            ds.save_as(filename=save_path, WriteLikeOriginal=False)
            image_counter[0] += 1
            pcid = image_counter[0]  # for the sake of argument
            # actually what we want here is the message object so we can extract the no of operations, status etc
            status = 0
            queue.put(CStoreResponse(pcid, status))

        except Exception as e:
            # print 'Error saving: C-STORE callback(cget=%s, instno=%d), saving to %s [%s]' % (cget_obj, ds.InstanceNumber, save_path, e)
            print('Error Saving: %s' % e)
            return 1  # ?? RHD
        # zero corresponds to DICOM Success
        return 0

    # Create application entity and association with remote AE (port number of 0 to stop it putting up a listen)
    ae = AE(laet,
            port=0,
            SOPSCU=[PatientRootGetSOPClass],
            SOPSCP=[
                RTPlanStorageSOPClass, CTImageStorageSOPClass,
                MRImageStorageSOPClass, RTImageStorageSOPClass
            ])
    ae.OnReceiveStore = on_receive_store
    ae.start()
    assoc = ae.RequestAssociation({'Address': node, 'Port': port, 'AET': aet})

    # Query object
    d = Dataset()
    d.PatientID = str(patid)
    d.StudyInstanceUID = str(studyuid)
    d.SeriesInstanceUID = str(seriesuid)
    d.SOPInstanceUID = str(imageuid)
    d.QueryRetrieveLevel = 'IMAGE'

    st_ds = assoc.PatientRootGetSOPClass.SCU(d, msg_id)
    if st_ds is not None:
        for status, ds in st_ds:
            pass
            # print 'status = %s, dataset = %s' % (status, ds)
    # print 'Done'

    returns.append(status)
    return