Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

i want to change workitem's status using n-action #509

Closed
codepage949 opened this issue Jun 28, 2020 · 19 comments
Closed

i want to change workitem's status using n-action #509

codepage949 opened this issue Jun 28, 2020 · 19 comments

Comments

@codepage949
Copy link

i have tried to change status for workitems in uwl using n-action.

but i got status code - 0x0123(No such action).

i am new to dicom and couldn't find references about changing workitem's status with pynetdicom.

please let me know what is the problem in below code.

or are there examples?

thank you in advance.

n-action document: http://dicom.nema.org/dicom/2013/output/chtml/part04/sect_CC.2.html

    from pydicom.dataset import Dataset
    from pynetdicom import AE
    from pynetdicom.sop_class import (
        UnifiedProcedureStepPushSOPClass
    )
    from pynetdicom.presentation import (
        UnifiedProcedurePresentationContexts
    )
    from pydicom.uid import generate_uid

    ae = AE(ae_title='calling_ae')
    assoc = ae.associate(
        ip,
        port,
        contexts=UnifiedProcedurePresentationContexts,
        ae_title='called_ae'
    )
    ds = Dataset()
    ds.TransactionUID = generate_uid()
    ds.ProcedureStepState = 'IN PROGRESS'
    (status, reply) = assoc.send_n_action(
        ds,
        1,
        UnifiedProcedureStepPushSOPClass,
        sop_instance_uid
    )

    assoc.release()
@scaramallion
Copy link
Member

The UPS has been created and is in the SCHEDULED initial state? I've never used UPS so I'm only going off what Part 4 says...

@codepage949
Copy link
Author

@scaramallion

  • The UPS has been created and is in the SCHEDULED initial state?
    • yes
  • I'm only going off what Part 4 says...
    • sorry, i am not good at english. what does it mean?

@scaramallion
Copy link
Member

scaramallion commented Jun 29, 2020

I meant I can only look at Part 4 of the DICOM Standard and try and guess what the problem is.

Are you getting your sop_instance_uid from the results of a C-FIND query? Could you post that part of your code as well? Also can you add a debug_logger() call at the top of your code and post the output?

from pynetdicom import debug_logger

debug_logger()

# ... rest of code

@codepage949
Copy link
Author

codepage949 commented Jun 29, 2020

@scaramallion

  • Are you getting your sop_instance_uid from the results of a C-FIND query?
    • yes
  • Could you post that part of your code as well? Also can you add a debug_logger() call at the top of your code and post the output?
def get_sop_instance_uids():
    sop_instance_uids = []
    ae = AE(ae_title='calling_ae')

    ae.add_requested_context(UnifiedProcedureStepQuerySOPClass)

    ds = Dataset()
    ds.PatientName = '*'
    ds.ProcedureStepState = 'SCHEDULED'
    ds.SOPInstanceUID = '*'
    assoc = ae.associate(
        ip,
        port,
        ae_title='called_ae',
    )

    if assoc.is_established:
        responses = assoc.send_c_find(ds, UnifiedProcedureStepQuerySOPClass)

        for (status, identifier) in responses:
            if status != None:
                # 0xFF00 = pending - Matches are continuing
                if status.Status == 0xFF00:
                    sop_instance_uids.append(identifier.SOPInstanceUID)
            else:
                print('Connection timed out, was aborted or received invalid response')

        assoc.release()
    else:
        print('Association rejected, aborted or never connected')

    return sop_instance_uids

C-FIND and N-ACTION output:

I: Requesting Association
D: Request Parameters:
D: ======================= OUTGOING A-ASSOCIATE-RQ PDU ========================
D: Our Implementation Class UID:      1.2.826.0.1.3680043.9.3811.1.5.1
D: Our Implementation Version Name:   PYNETDICOM_151
D: Application Context Name:    1.2.840.10008.3.1.1.1
D: Calling Application Name:    test      
D: Called Application Name:     DCM4CHEE        
D: Our Max PDU Receive Size:    16382
D: Presentation Context:
D:   Context ID:        1 (Proposed)
D:     Abstract Syntax: =Unified Procedure Step - Query SOP Class
D:     Proposed SCP/SCU Role: Default
D:     Proposed Transfer Syntaxes:
D:       =Implicit VR Little Endian
D:       =Explicit VR Little Endian
D:       =Deflated Explicit VR Little Endian
D:       =Explicit VR Big Endian
D: Requested Extended Negotiation: None
D: Requested Common Extended Negotiation: None
D: Requested Asynchronous Operations Window Negotiation: None
D: Requested User Identity Negotiation: None
D: ========================== END A-ASSOCIATE-RQ PDU ==========================
D: Accept Parameters:
D: ======================= INCOMING A-ASSOCIATE-AC PDU ========================
D: Their Implementation Class UID:    1.2.40.0.13.1.3
D: Their Implementation Version Name: dcm4che-5.22.2
D: Application Context Name:    1.2.840.10008.3.1.1.1
D: Calling Application Name:    test      
D: Called Application Name:     DCM4CHEE        
D: Their Max PDU Receive Size:  16378
D: Presentation Contexts:
D:   Context ID:        1 (Accepted)
D:     Abstract Syntax: =Unified Procedure Step - Query SOP Class
D:     Accepted SCP/SCU Role: Default
D:     Accepted Transfer Syntax: =Implicit VR Little Endian
D: Accepted Extended Negotiation: None
D: Accepted Asynchronous Operations Window Negotiation: None
D: User Identity Negotiation Response: None
D: ========================== END A-ASSOCIATE-AC PDU ==========================
I: Association Accepted
I: Sending Find Request: MsgID 1
I: 
I: # Request Identifier
I: (0008,0018) UI [*]                                      # 1 SOPInstanceUID
I: (0010,0010) PN [*]                                      # 1 PatientName
I: (0074,1000) CS [SCHEDULED]                              # 1 ProcedureStepState
I: 
D: ========================== OUTGOING DIMSE MESSAGE ==========================
D: Message Type                  : C-FIND RQ
D: Presentation Context ID       : 1
D: Message ID                    : 1
D: Affected SOP Class UID        : Unified Procedure Step - Query SOP Class
D: Identifier                    : Present
D: Priority                      : Low
D: ============================ END DIMSE MESSAGE =============================
D: pydicom.read_dataset() TransferSyntax="Little Endian Implicit"
D: 
I: Find SCP Response: 1 - 0xFF00 (Pending)
D: pydicom.read_dataset() TransferSyntax="Little Endian Implicit"
I: 
I: # Response Identifier
I: (0008,0005) CS [ISO_IR 100]                             # 1 SpecificCharacterSet
I: (0008,0018) UI [2.25.86240333294135488660835797081882992519] # 1 SOPInstanceUID
I: (0010,0010) PN [Anonymized]                             # 1 PatientName
I: (0074,1000) CS [SCHEDULED]                              # 1 ProcedureStepState
I: 
D: pydicom.read_dataset() TransferSyntax="Little Endian Implicit"
D: 
I: Find SCP Response: 2 - 0xFF00 (Pending)
D: pydicom.read_dataset() TransferSyntax="Little Endian Implicit"
I: 
I: # Response Identifier
I: (0008,0005) CS [ISO_IR 100]                             # 1 SpecificCharacterSet
I: (0008,0018) UI [2.25.226351993702933115193948206864830216039] # 1 SOPInstanceUID
I: (0010,0010) PN [Anonymized]                             # 1 PatientName
I: (0074,1000) CS [SCHEDULED]                              # 1 ProcedureStepState
I: 
D: pydicom.read_dataset() TransferSyntax="Little Endian Implicit"
D: 
I: Find SCP Response: 3 - 0xFF00 (Pending)
D: pydicom.read_dataset() TransferSyntax="Little Endian Implicit"
I: 
I: # Response Identifier
I: (0008,0005) CS [ISO_IR 100]                             # 1 SpecificCharacterSet
I: (0008,0018) UI [2.25.100004539105216600373164769322183198137] # 1 SOPInstanceUID
I: (0010,0010) PN [Anonymized]                             # 1 PatientName
I: (0074,1000) CS [SCHEDULED]                              # 1 ProcedureStepState
I: 
D: pydicom.read_dataset() TransferSyntax="Little Endian Implicit"
D: 
I: Find SCP Response: 4 - 0xFF00 (Pending)
D: pydicom.read_dataset() TransferSyntax="Little Endian Implicit"
I: 
I: # Response Identifier
I: (0008,0005) CS [ISO_IR 100]                             # 1 SpecificCharacterSet
I: (0008,0018) UI [2.25.116828821981012178512574266057939061020] # 1 SOPInstanceUID
I: (0010,0010) PN [Anonymized]                             # 1 PatientName
I: (0074,1000) CS [SCHEDULED]                              # 1 ProcedureStepState
I: 
D: pydicom.read_dataset() TransferSyntax="Little Endian Implicit"
D: 
I: Find SCP Response: 5 - 0xFF00 (Pending)
D: pydicom.read_dataset() TransferSyntax="Little Endian Implicit"
I: 
I: # Response Identifier
I: (0008,0005) CS [ISO_IR 100]                             # 1 SpecificCharacterSet
I: (0008,0018) UI [2.25.60913100226869995630158290091376709561] # 1 SOPInstanceUID
I: (0010,0010) PN [Anonymized]                             # 1 PatientName
I: (0074,1000) CS [SCHEDULED]                              # 1 ProcedureStepState
I: 
D: pydicom.read_dataset() TransferSyntax="Little Endian Implicit"
D: 
I: Find SCP Response: 6 - 0xFF00 (Pending)
D: pydicom.read_dataset() TransferSyntax="Little Endian Implicit"
I: 
I: # Response Identifier
I: (0008,0005) CS [ISO_IR 100]                             # 1 SpecificCharacterSet
I: (0008,0018) UI [2.25.51858633597428929390592504559484088793] # 1 SOPInstanceUID
I: (0010,0010) PN [Anonymized]                             # 1 PatientName
I: (0074,1000) CS [SCHEDULED]                              # 1 ProcedureStepState
I: 
D: pydicom.read_dataset() TransferSyntax="Little Endian Implicit"
D: 
I: Find SCP Response: 7 - 0xFF00 (Pending)
D: pydicom.read_dataset() TransferSyntax="Little Endian Implicit"
I: 
I: # Response Identifier
I: (0008,0005) CS [ISO_IR 100]                             # 1 SpecificCharacterSet
I: (0008,0018) UI [2.25.19737495633226810052770909550706124415] # 1 SOPInstanceUID
I: (0010,0010) PN [Anonymized]                             # 1 PatientName
I: (0074,1000) CS [SCHEDULED]                              # 1 ProcedureStepState
I: 
D: pydicom.read_dataset() TransferSyntax="Little Endian Implicit"
D: 
I: Find SCP Response: 8 - 0xFF00 (Pending)
D: pydicom.read_dataset() TransferSyntax="Little Endian Implicit"
I: 
I: # Response Identifier
I: (0008,0005) CS [ISO_IR 100]                             # 1 SpecificCharacterSet
I: (0008,0018) UI [2.25.290946983222634535763242323831739290198] # 1 SOPInstanceUID
I: (0010,0010) PN [Anonymized]                             # 1 PatientName
I: (0074,1000) CS [SCHEDULED]                              # 1 ProcedureStepState
I: 
D: pydicom.read_dataset() TransferSyntax="Little Endian Implicit"
D: ========================== INCOMING DIMSE MESSAGE ==========================
D: Message Type                  : C-FIND RSP
D: Message ID Being Responded To : 1
D: Affected SOP Class UID        : Unified Procedure Step - Query SOP Class
D: Identifier                    : None
D: Status                        : 0x0000
D: ============================ END DIMSE MESSAGE =============================
D: 
I: Find SCP Result: 0x0000 (Success)
I: Releasing Association
I: Requesting Association
D: Request Parameters:
D: ======================= OUTGOING A-ASSOCIATE-RQ PDU ========================
D: Our Implementation Class UID:      1.2.826.0.1.3680043.9.3811.1.5.1
D: Our Implementation Version Name:   PYNETDICOM_151
D: Application Context Name:    1.2.840.10008.3.1.1.1
D: Calling Application Name:    test      
D: Called Application Name:     DCM4CHEE        
D: Our Max PDU Receive Size:    16382
D: Presentation Contexts:
D:   Context ID:        1 (Proposed)
D:     Abstract Syntax: =Unified Procedure Step - Push SOP Class
D:     Proposed SCP/SCU Role: Default
D:     Proposed Transfer Syntaxes:
D:       =Implicit VR Little Endian
D:       =Explicit VR Little Endian
D:       =Deflated Explicit VR Little Endian
D:       =Explicit VR Big Endian
D:   Context ID:        3 (Proposed)
D:     Abstract Syntax: =Unified Procedure Step - Watch SOP Class
D:     Proposed SCP/SCU Role: Default
D:     Proposed Transfer Syntaxes:
D:       =Implicit VR Little Endian
D:       =Explicit VR Little Endian
D:       =Deflated Explicit VR Little Endian
D:       =Explicit VR Big Endian
D:   Context ID:        5 (Proposed)
D:     Abstract Syntax: =Unified Procedure Step - Pull SOP Class
D:     Proposed SCP/SCU Role: Default
D:     Proposed Transfer Syntaxes:
D:       =Implicit VR Little Endian
D:       =Explicit VR Little Endian
D:       =Deflated Explicit VR Little Endian
D:       =Explicit VR Big Endian
D:   Context ID:        7 (Proposed)
D:     Abstract Syntax: =Unified Procedure Step - Event SOP Class
D:     Proposed SCP/SCU Role: Default
D:     Proposed Transfer Syntaxes:
D:       =Implicit VR Little Endian
D:       =Explicit VR Little Endian
D:       =Deflated Explicit VR Little Endian
D:       =Explicit VR Big Endian
D:   Context ID:        9 (Proposed)
D:     Abstract Syntax: =Unified Procedure Step - Query SOP Class
D:     Proposed SCP/SCU Role: Default
D:     Proposed Transfer Syntaxes:
D:       =Implicit VR Little Endian
D:       =Explicit VR Little Endian
D:       =Deflated Explicit VR Little Endian
D:       =Explicit VR Big Endian
D: Requested Extended Negotiation: None
D: Requested Common Extended Negotiation: None
D: Requested Asynchronous Operations Window Negotiation: None
D: Requested User Identity Negotiation: None
D: ========================== END A-ASSOCIATE-RQ PDU ==========================
D: Accept Parameters:
D: ======================= INCOMING A-ASSOCIATE-AC PDU ========================
D: Their Implementation Class UID:    1.2.40.0.13.1.3
D: Their Implementation Version Name: dcm4che-5.22.2
D: Application Context Name:    1.2.840.10008.3.1.1.1
D: Calling Application Name:    test      
D: Called Application Name:     DCM4CHEE        
D: Their Max PDU Receive Size:  16378
D: Presentation Contexts:
D:   Context ID:        1 (Accepted)
D:     Abstract Syntax: =Unified Procedure Step - Push SOP Class
D:     Accepted SCP/SCU Role: Default
D:     Accepted Transfer Syntax: =Implicit VR Little Endian
D:   Context ID:        3 (Accepted)
D:     Abstract Syntax: =Unified Procedure Step - Watch SOP Class
D:     Accepted SCP/SCU Role: Default
D:     Accepted Transfer Syntax: =Implicit VR Little Endian
D:   Context ID:        5 (Accepted)
D:     Abstract Syntax: =Unified Procedure Step - Pull SOP Class
D:     Accepted SCP/SCU Role: Default
D:     Accepted Transfer Syntax: =Implicit VR Little Endian
D:   Context ID:        7 (Accepted)
D:     Abstract Syntax: =Unified Procedure Step - Event SOP Class
D:     Accepted SCP/SCU Role: Default
D:     Accepted Transfer Syntax: =Implicit VR Little Endian
D:   Context ID:        9 (Accepted)
D:     Abstract Syntax: =Unified Procedure Step - Query SOP Class
D:     Accepted SCP/SCU Role: Default
D:     Accepted Transfer Syntax: =Implicit VR Little Endian
D: Accepted Extended Negotiation: None
D: Accepted Asynchronous Operations Window Negotiation: None
D: User Identity Negotiation Response: None
D: ========================== END A-ASSOCIATE-AC PDU ==========================
I: Association Accepted
I: Sending Action Request: MsgID 1
D: pydicom.read_dataset() TransferSyntax="Little Endian Implicit"
I: Releasing Association

@scaramallion
Copy link
Member

As far as I can tell you're doing everything correctly. Could you bind the following to EVT_PDU_SENT and post the output for the send_n_action() call?

from pydicom.dataset import Dataset
from pynetdicom import AE, evt, debug_logger
from pynetdicom.sop_class import (
    UnifiedProcedureStepPushSOPClass
)
from pynetdicom.utils import pretty_bytes
from pynetdicom.presentation import (
    UnifiedProcedurePresentationContexts
)
from pydicom.uid import generate_uid

debug_logger()

def pdu_sent(event):
    if event.pdu.pdu_type == 0x04:
        for ii, item in enumerate(event.pdu.presentation_data_value_items):
            print('PDV {}'.format(ii))
            for line in pretty_bytes(item.presentation_data_value):
                print(line)

handlers = [(evt.EVT_PDU_SENT, pdu_sent)]

ae = AE(ae_title='calling_ae')
assoc = ae.associate(
    ip,
    port,
    contexts=UnifiedProcedurePresentationContexts,
    ae_title='called_ae',
    evt_handlers=handlers
)

ds = Dataset()
ds.TransactionUID = generate_uid()
ds.ProcedureStepState = 'IN PROGRESS'

(status, reply) = assoc.send_n_action(
    ds,
    1,
    UnifiedProcedureStepPushSOPClass,
    sop_instance_uid
)

assoc.release()

@codepage949
Copy link
Author

@scaramallion

I: Requesting Association
D: Request Parameters:
D: ======================= OUTGOING A-ASSOCIATE-RQ PDU ========================
D: Our Implementation Class UID:      1.2.826.0.1.3680043.9.3811.1.5.1
D: Our Implementation Version Name:   PYNETDICOM_151
D: Application Context Name:    1.2.840.10008.3.1.1.1
D: Calling Application Name:    test      
D: Called Application Name:     DCM4CHEE        
D: Our Max PDU Receive Size:    16382
D: Presentation Contexts:
D:   Context ID:        1 (Proposed)
D:     Abstract Syntax: =Unified Procedure Step - Push SOP Class
D:     Proposed SCP/SCU Role: Default
D:     Proposed Transfer Syntaxes:
D:       =Implicit VR Little Endian
D:       =Explicit VR Little Endian
D:       =Deflated Explicit VR Little Endian
D:       =Explicit VR Big Endian
D:   Context ID:        3 (Proposed)
D:     Abstract Syntax: =Unified Procedure Step - Watch SOP Class
D:     Proposed SCP/SCU Role: Default
D:     Proposed Transfer Syntaxes:
D:       =Implicit VR Little Endian
D:       =Explicit VR Little Endian
D:       =Deflated Explicit VR Little Endian
D:       =Explicit VR Big Endian
D:   Context ID:        5 (Proposed)
D:     Abstract Syntax: =Unified Procedure Step - Pull SOP Class
D:     Proposed SCP/SCU Role: Default
D:     Proposed Transfer Syntaxes:
D:       =Implicit VR Little Endian
D:       =Explicit VR Little Endian
D:       =Deflated Explicit VR Little Endian
D:       =Explicit VR Big Endian
D:   Context ID:        7 (Proposed)
D:     Abstract Syntax: =Unified Procedure Step - Event SOP Class
D:     Proposed SCP/SCU Role: Default
D:     Proposed Transfer Syntaxes:
D:       =Implicit VR Little Endian
D:       =Explicit VR Little Endian
D:       =Deflated Explicit VR Little Endian
D:       =Explicit VR Big Endian
D:   Context ID:        9 (Proposed)
D:     Abstract Syntax: =Unified Procedure Step - Query SOP Class
D:     Proposed SCP/SCU Role: Default
D:     Proposed Transfer Syntaxes:
D:       =Implicit VR Little Endian
D:       =Explicit VR Little Endian
D:       =Deflated Explicit VR Little Endian
D:       =Explicit VR Big Endian
D: Requested Extended Negotiation: None
D: Requested Common Extended Negotiation: None
D: Requested Asynchronous Operations Window Negotiation: None
D: Requested User Identity Negotiation: None
D: ========================== END A-ASSOCIATE-RQ PDU ==========================
D: Accept Parameters:
D: ======================= INCOMING A-ASSOCIATE-AC PDU ========================
D: Their Implementation Class UID:    1.2.40.0.13.1.3
D: Their Implementation Version Name: dcm4che-5.22.2
D: Application Context Name:    1.2.840.10008.3.1.1.1
D: Calling Application Name:    test      
D: Called Application Name:     DCM4CHEE        
D: Their Max PDU Receive Size:  16378
D: Presentation Contexts:
D:   Context ID:        1 (Accepted)
D:     Abstract Syntax: =Unified Procedure Step - Push SOP Class
D:     Accepted SCP/SCU Role: Default
D:     Accepted Transfer Syntax: =Implicit VR Little Endian
D:   Context ID:        3 (Accepted)
D:     Abstract Syntax: =Unified Procedure Step - Watch SOP Class
D:     Accepted SCP/SCU Role: Default
D:     Accepted Transfer Syntax: =Implicit VR Little Endian
D:   Context ID:        5 (Accepted)
D:     Abstract Syntax: =Unified Procedure Step - Pull SOP Class
D:     Accepted SCP/SCU Role: Default
D:     Accepted Transfer Syntax: =Implicit VR Little Endian
D:   Context ID:        7 (Accepted)
D:     Abstract Syntax: =Unified Procedure Step - Event SOP Class
D:     Accepted SCP/SCU Role: Default
D:     Accepted Transfer Syntax: =Implicit VR Little Endian
D:   Context ID:        9 (Accepted)
D:     Abstract Syntax: =Unified Procedure Step - Query SOP Class
D:     Accepted SCP/SCU Role: Default
D:     Accepted Transfer Syntax: =Implicit VR Little Endian
D: Accepted Extended Negotiation: None
D: Accepted Asynchronous Operations Window Negotiation: None
D: User Identity Negotiation Response: None
D: ========================== END A-ASSOCIATE-AC PDU ==========================
I: Association Accepted
I: Sending Action Request: MsgID 1
PDV 0
  03  00  00  00  00  04  00  00  00  7e  00  00  00  00  00  03
  00  1a  00  00  00  31  2e  32  2e  38  34  30  2e  31  30  30
  30  38  2e  35  2e  31  2e  34  2e  33  34  2e  36  2e  31  00
  00  00  01  02  00  00  00  30  01  00  00  10  01  02  00  00
  00  01  00  00  00  00  08  02  00  00  00  01  00  00  00  01
  10  2c  00  00  00  32  2e  32  35  2e  38  36  32  34  30  33
  33  33  32  39  34  31  33  35  34  38  38  36  36  30  38  33
  35  37  39  37  30  38  31  38  38  32  39  39  32  35  31  39
  00  00  00  08  10  02  00  00  00  01  00
PDV 0
  02  08  00  95  11  40  00  00  00  31  2e  32  2e  38  32  36
  2e  30  2e  31  2e  33  36  38  30  30  34  33  2e  38  2e  34
  39  38  2e  31  35  39  39  39  37  39  32  38  31  37  38  37
  35  31  39  34  31  39  31  37  38  33  32  30  35  39  32  36
  39  34  37  38  35  31  39  30  37  74  00  00  10  0c  00  00
  00  49  4e  20  50  52  4f  47  52  45  53  53  20
D: pydicom.read_dataset() TransferSyntax="Little Endian Implicit"
I: Releasing Association

@scaramallion
Copy link
Member

Everything looks fine, are you sure the problem doesn't lie with the SCP?

PDV 0 
  03 - Command Set, last fragment - little endian implicit
  00  00  00  00  (0000,0000) Command Group Length
  04  00  00  00  Length 4
  7e  00  00  00  126
  00  00  03  00  (0000,0003) Requested SOP Class UID
  1a  00  00  00  Length 26
  -> (ASCII) 1.2.840.10008.5.1.4.34.6.1 - UnifiedProcedureStepPushSOPClass
  31  2e  32  2e  38  34  30  2e  31  30  30  30  38  2e  35  2e  
  31  2e  34  2e  33  34  2e  36  2e  31  
  00  00  00  01  (0000,0100) Command Field
  02  00  00  00  Length 2
  30  01          -> N-ACTION-RQ
  00  00  10  01  (0000,0110) Message ID
  02  00  00  00  Length 2
  01  00          -> ID 1
  00  00  00  08  (0000,0800) Command Data Set Type
  02  00  00  00  Length 2
  01  00          ->Data Set Present
  00  00  01  10  (0000,1001) Requested SOP Instance UID
  2c  00  00  00  Length 44
  -> (ASCII) 2.25.86240333294135488660835797081882992519
  32  2e  32  35  2e  38  36  32  34  30  33  33  33  32  39  34  
  31  33  35  34  38  38  36  36  30  38  33  35  37  39  37  30  
  38  31  38  38  32  39  39  32  35  31  39  00  
  00  00  08  10  (0000,1008) Action Type ID
  02  00  00  00  Length 2
  01  00          ->ID 1

PDV 0
  02 - Dataset, last fragment - little endian implicit
  08  00  95  11  (0008,1195) Transaction UID, UI
  40  00  00  00  Length 64 bytes
  -> (ASCII) 1.2.826.0.1.3680043.8.498.15999792817875194191783205926947851907
  31  2e  32  2e  38  32  36  2e  30  2e  31  2e  33  36  38  30  
  30  34  33  2e  38  2e  34  39  38  2e  31  35  39  39  39  37  
  39  32  38  31  37  38  37  35  31  39  34  31  39  31  37  38  
  33  32  30  35  39  32  36  39  34  37  38  35  31  39  30  37  
  74  00  00  10  (0074,1000) Procedure Step State, CS
  0c  00  00  00  Length 12
  49  4e  20  50  52  4f  47  52  45  53  53  20 -> (ASCII) "IN PROGRESS "

@codepage949
Copy link
Author

@scaramallion

it returns status - 0x0123(No such action) and have no effect on workitems.

but upsscu(dcm4che tool) works correctly with the SCP.

./upsscu -c ae@ip:port -O changeState -P=transaction-uid -u uid

13:58:32,609 INFO  - Initiate connection from 0.0.0.0/0.0.0.0:0 to 127.0.0.1:11112
13:58:32,613 INFO  - Established connection Socket[addr=/127.0.0.1,port=11112,localport=58391]
13:58:32,620 DEBUG - /127.0.0.1:58391->/127.0.0.1:11112(1): enter state: Sta4 - Awaiting transport connection opening to complete
13:58:32,621 INFO  - UPSSCU->DCM4CHEE(1) << A-ASSOCIATE-RQ
13:58:32,639 DEBUG - A-ASSOCIATE-RQ[
  calledAET: DCM4CHEE
  callingAET: UPSSCU
  applicationContext: 1.2.840.10008.3.1.1.1 - DICOM Application Context Name
  implClassUID: 1.2.40.0.13.1.3
  implVersionName: dcm4che-5.22.2
  maxPDULength: 16378
  maxOpsInvoked/maxOpsPerformed: 0/0
  PresentationContext[id: 3
    as: 1.2.840.10008.5.1.4.34.6.3 - Unified Procedure Step - Pull SOP Class
    ts: 1.2.840.10008.1.2 - Implicit VR Little Endian
    ts: 1.2.840.10008.1.2.1 - Explicit VR Little Endian
    ts: 1.2.840.10008.1.2.2 - Explicit VR Big Endian (Retired)
  ]
  PresentationContext[id: 1
    as: 1.2.840.10008.1.1 - Verification SOP Class
    ts: 1.2.840.10008.1.2 - Implicit VR Little Endian
  ]
]
13:58:32,639 DEBUG - UPSSCU->DCM4CHEE(1): enter state: Sta5 - Awaiting A-ASSOCIATE-AC or A-ASSOCIATE-RJ PDU
13:58:32,642 INFO  - UPSSCU->DCM4CHEE(1) >> A-ASSOCIATE-AC
13:58:32,642 DEBUG - A-ASSOCIATE-AC[
  calledAET: DCM4CHEE
  callingAET: UPSSCU
  applicationContext: 1.2.840.10008.3.1.1.1 - DICOM Application Context Name
  implClassUID: 1.2.40.0.13.1.3
  implVersionName: dcm4che-5.22.2
  maxPDULength: 16378
  maxOpsInvoked/maxOpsPerformed: 0/0
  PresentationContext[id: 3
    result: 0 - acceptance
    ts: 1.2.840.10008.1.2 - Implicit VR Little Endian
  ]
  PresentationContext[id: 1
    result: 0 - acceptance
    ts: 1.2.840.10008.1.2 - Implicit VR Little Endian
  ]
]
13:58:32,643 DEBUG - UPSSCU->DCM4CHEE(1): enter state: Sta6 - Association established and ready for data transfer
13:58:32,649 INFO  - UPSSCU->DCM4CHEE(1) << 1:N-ACTION-RQ[pcid=3, actionID=1
  cuid=1.2.840.10008.5.1.4.34.6.1 - Unified Procedure Step - Push SOP Class
  iuid=2.25.86240333294135488660835797081882992519 - ?
  tsuid=1.2.840.10008.1.2 - Implicit VR Little Endian]
13:58:32,672 DEBUG - UPSSCU->DCM4CHEE(1) << 1:N-ACTION-RQ Command:
(0000,0003) UI [1.2.840.10008.5.1.4.34.6.1] RequestedSOPClassUID
(0000,0100) US [304] CommandField
(0000,0110) US [1] MessageID
(0000,0800) US [0] CommandDataSetType
(0000,1001) UI [2.25.86240333294135488660835797081882992519] RequestedSOPInsta
(0000,1008) US [1] ActionTypeID

13:58:32,675 DEBUG - UPSSCU->DCM4CHEE(1) << 1:N-ACTION-RQ Dataset:
(0008,1195) UI [=1.2.3.4.5] TransactionUID
(0074,1000) CS [IN PROGRESS] ProcedureStepState

13:58:32,718 INFO  - UPSSCU->DCM4CHEE(1) >> 1:N-ACTION-RSP[pcid=3, status=0H
  cuid=1.2.840.10008.5.1.4.34.6.1 - Unified Procedure Step - Push SOP Class
  iuid=2.25.86240333294135488660835797081882992519 - ?
  tsuid=1.2.840.10008.1.2 - Implicit VR Little Endian]
13:58:32,719 DEBUG - UPSSCU->DCM4CHEE(1) >> 1:N-ACTION-RSP Command:
(0000,0002) UI [1.2.840.10008.5.1.4.34.6.1] AffectedSOPClassUID
(0000,0100) US [33072] CommandField
(0000,0120) US [1] MessageIDBeingRespondedTo
(0000,0800) US [257] CommandDataSetType
(0000,0900) US [0] Status
(0000,1000) UI [2.25.86240333294135488660835797081882992519] AffectedSOPInstan

13:58:32,721 INFO  - UPSSCU->DCM4CHEE(1) << A-RELEASE-RQ
13:58:32,721 DEBUG - UPSSCU->DCM4CHEE(1): enter state: Sta7 - Awaiting A-RELEASE-RP PDU
13:58:32,724 INFO  - UPSSCU->DCM4CHEE(1) >> A-RELEASE-RP
13:58:32,724 INFO  - UPSSCU->DCM4CHEE(1): close Socket[addr=/127.0.0.1,port=11112,localport=58391]
13:58:32,725 DEBUG - UPSSCU->DCM4CHEE(1): enter state: Sta1 - Idle

it's so confusing..

@scaramallion
Copy link
Member

scaramallion commented Jun 29, 2020

The N-ACTION-RQ looks the same, maybe try setting the AE title to b'UPSSCU'?

@codepage949
Copy link
Author

@scaramallion

yes.. i tried.

but changing AE title didn't have effect.

@jehos
Copy link

jehos commented Jun 29, 2020

hello @scaramallion,

I'm working with @codepage949
Currently using dmc4chee-arc-light-5.22.2, there is no access control by remote scu AE titles...

I think the pynetdicom is correct, but i don't know how to using properly..
If you have a sample code, could you share it with us?

@scaramallion
Copy link
Member

OK, give me a chance to install dcm4chee and I'll try and figure out what's going on

@jehos
Copy link

jehos commented Jun 29, 2020

Oh, thanks. 😉

NOTE1 : DO NOT USING localhost or 127.0.0.1 as hostname, limitation of keycloak service... (in mycase, i'm using docker br0's IP.. its static 😉)
NOTE2: please refer this... https://github.com/dcm4che/dcm4chee-arc-light/wiki/Run-secured-archive-services-and-Elastic-Stack-on-a-single-host

jehos@GogunBuntu:~/src/dcm4che/dcm4chee-dockerfiles$ tree -L 2
.
├── dcm4chee-arc
│   ├── db
│   ├── elasticsearch
│   ├── keycloak
│   ├── ldap
│   ├── logstash
│   ├── slapd.d
│   ├── storage
│   └── wildfly
├── docker-compose.env
└── docker-compose.yml

9 directories, 2 files

docker-compose.env

LOGSTASH_HOST=logstash
ARCHIVE_HOST=172.17.0.1
SYSLOG_HOST=logstash
SYSLOG_PORT=8514
SYSLOG_PROTOCOL=TLS
STORAGE_DIR=/storage/fs1
POSTGRES_DB=pacsdb
POSTGRES_USER=pacs
POSTGRES_PASSWORD=pacs
AUTH_SERVER_URL=https://172.17.0.1:8843/auth

docker-compose.yml

version: "3"
services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.6.0
    environment:
      ES_JAVA_OPTS: -Xms1024m -Xmx1024m
      TAKE_FILE_OWNERSHIP: 1
      discovery.type: single-node
    logging:
      driver: json-file
      options:
        max-size: "10m"
    ports:
      - "9200:9200"
      - "9300:9300"
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /etc/timezone:/etc/timezone:ro
      - ./dcm4chee-arc/elasticsearch:/usr/share/elasticsearch/data
  kibana:
    image: docker.elastic.co/kibana/kibana:7.6.0
    logging:
      driver: json-file
      options:
        max-size: "10m"
    depends_on:
      - elasticsearch
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /etc/timezone:/etc/timezone:ro
  logstash:
    image: dcm4che/logstash-dcm4chee:7.6.0-10
    logging:
      driver: json-file
      options:
        max-size: "10m"
    ports:
      - "12201:12201/udp"
      - "8514:8514/udp"
      - "8514:8514"
    depends_on:
      - elasticsearch
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /etc/timezone:/etc/timezone:ro
      - ./dcm4chee-arc/logstash/filter-hashtree:/usr/share/logstash/data/filter-hashtree
  ldap:
    image: dcm4che/slapd-dcm4chee:2.4.48-22.2
    logging:
      options:
        tag: slapd
    ports:
      - "389:389"
    env_file: docker-compose.env
    volumes:
      - ./dcm4chee-arc/ldap:/var/lib/openldap/openldap-data
      - ./dcm4chee-arc/slapd.d:/etc/openldap/slapd.d
  keycloak:
    image: dcm4che/keycloak:10.0.1
    logging:
      options:
        tag: keycloak
    ports:
      - "8880:8880"
      - "8843:8843"
      - "8990:8990"
    env_file: docker-compose.env
    environment:
      HTTP_PORT: 8880
      HTTPS_PORT: 8843
      MANAGEMENT_HTTP_PORT: 8990
      KEYCLOAK_WAIT_FOR: ldap:389 logstash:8514
    depends_on:
      - ldap
      - logstash
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /etc/timezone:/etc/timezone:ro
      - ./dcm4chee-arc/keycloak:/opt/keycloak/standalone
  keycloak-gatekeeper:
    image: dcm4che/keycloak-gatekeeper:10.0.1
    logging:
      options:
        tag: keycloak-gatekeeper
    ports:
      - "8643:8643"
    environment:
      PROXY_LISTEN: :8643
      PROXY_REDIRECTION_URL: https://172.17.0.1:8643
      PROXY_UPSTREAM_URL: http://kibana:5601
      PROXY_DISCOVERY_URL: https://172.17.0.1:8843/auth/realms/dcm4che
      PROXY_CLIENT_ID: kibana
      PROXY_CLIENT_SECRET: 5f317235-3020-4758-9793-61275604d2f6
      PROXY_ENCRYPTION_KEY: AgXa7xRcoClDEU0ZDSH4X0XhL5Qy2Z2j
    command:
      - "--openid-provider-timeout=120s"
      - "--tls-cert=/etc/certs/cert.pem"
      - "--tls-private-key=/etc/certs/key.pem"
      - "--skip-openid-provider-tls-verify=true"
      - "--enable-refresh-tokens=true"
      - "--resources=uri=/*|roles=auditlog"
    depends_on:
      - kibana
      - keycloak
  db:
    image: dcm4che/postgres-dcm4chee:11.7-22
    #image: dcm4che/postgres-dcm4chee:11.2-16
    logging:
      options:
        tag: postgres
    ports:
      - "5432:5432"
    env_file: docker-compose.env
    depends_on:
      - logstash
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /etc/timezone:/etc/timezone:ro
      - ./dcm4chee-arc/db:/var/lib/postgresql/data
  arc:
    image: dcm4che/dcm4chee-arc-psql:5.22.2-secure
    logging:
      options:
        tag: dcm4chee-arc
    ports:
      - "8080:8080"
      - "8443:8443"
      - "9990:9990"
      - "9993:9993"
      - "11112:11112"
      - "2762:2762"
      - "2575:2575"
      - "12575:12575"
    env_file: docker-compose.env
    environment:
      WILDFLY_CHOWN: /opt/wildfly/standalone /storage
      WILDFLY_WAIT_FOR: ldap:389 db:5432 logstash:8514
    depends_on:
      - ldap
      - keycloak
      - db
      - logstash
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /etc/timezone:/etc/timezone:ro
      - ./dcm4chee-arc/wildfly:/opt/wildfly/standalone
      - ./dcm4chee-arc/storage:/storage

@scaramallion
Copy link
Member

scaramallion commented Jun 29, 2020

OK, I think this is a pynetdicom issue. The DICOM Standard says:

An SCU uses N-ACTION to ask the SCP to change the state of a UPS Instance as shown in Figure CC.1.1-1. Since all UPSs are created as instances of the UPS Push SOP Class, the Requested SOP Class UID (0000,0003) in the N-ACTION request shall be the UID of the UPS Push SOP Class. See Section CC.3.1 for further details.

In essence, dcm4chee wants the requested presentation context to be UPS Pull and the N-ACTION-RQ's Requested SOP Class UID to be UPS Push. pynetdicom doesn't allow that with Association.send_n_action(), when I patch it then everything works as expected. dcm4chee doesn't like having an association with all the UPS presentation contexts, either, it just wants one.

I'll double check my reasoning and probably put out a patch release. If you need it working sooner rather than later then this branch should work with:

def set_in_progress(instance_uid):
    ae = AE()

    ae.add_requested_context(UnifiedProcedureStepPullSOPClass)

    ds = Dataset()
    ds.TransactionUID = generate_uid()
    ds.ProcedureStepState = 'IN PROGRESS'

    assoc = ae.associate('localhost', 11112, ae_title=b"DCM4CHEE")
    if assoc.is_established:
        (status, reply) = assoc.send_n_action(
            ds, 1,
            UnifiedProcedureStepPushSOPClass,
            instance_uid,
        )
        print(f"In-progress: 0x{status.Status:04X}")

        assoc.release()

@codepage949
Copy link
Author

@scaramallion

it was so great experience solving a problem with someone online.

thank you.

@scaramallion
Copy link
Member

Fixed with v1.5.2, do you mind testing it?

@scaramallion
Copy link
Member

scaramallion commented Jul 4, 2020

You know, now that I've done all that work I've realised that the simplest solution would've been to just use the meta_uid keyword parameter instead... ah well.

status, ds = assoc.send_n_action(ds, 1, UnifiedProcedureStepPushSOPClass, '1.2.3.4', meta_uid=UnifiedProcedureStepPullSOPClass)

@codepage949
Copy link
Author

@scaramallion

with v1.5.2, it worked as expected.

and with v1.5.1, meta_uid solved the problem too.

thank you very much!

have a good weekends.

@scaramallion
Copy link
Member

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants