Describe the bug
When acting as an Association Acceptor (SCP), negotiate_as_acceptor() in presentation.py selects the accepted Transfer Syntax by iterating the acceptor's supported TS list and picking the first match found in the requestor's proposed list. This ignores the requestor's preference order.
The DICOM convention (and the behavior of DCMTK, the reference DICOM implementation) is to iterate the requestor's proposed TS list and pick the first one the acceptor supports. The requestor lists transfer syntaxes in preference order, and the acceptor should respect that.
This causes real-world interoperability failures. For example, when a sender has JPEG-LS Lossless compressed mammography files and proposes [JPEG-LS Lossless, Explicit VR LE, Implicit VR LE], the SCP accepts Explicit VR LE (because it appears first in the SCP's own supported list). The sender then cannot use the accepted context because it would need to decompress on the fly, which most DICOM implementations cannot do. The sender aborts the association.
Expected behavior
The SCP should accept 1.2.840.10008.1.2.4.80 (JPEG-LS Lossless) because it is the requestor's first-preference transfer syntax and the SCP supports it. This is how DCMTK's storescp behaves. Actual behavior? The SCP accepts 1.2.840.10008.1.2 (Implicit VR LE) because it appears first in the SCP's own supported transfer syntax list, regardless of the requestor's preference.
Steps To Reproduce
from pynetdicom import AE, evt
from pynetdicom.sop_class import Verification
sop = '1.2.840.10008.5.1.4.1.1.1.2' # Digital Mammography
jpeg_ls = '1.2.840.10008.1.2.4.80' # JPEG-LS Lossless
implicit = '1.2.840.10008.1.2' # Implicit VR LE
# SCP: supports both, but lists implicit first
scp_ae = AE()
scp_ae.add_supported_context(sop, [implicit, jpeg_ls])
scp_ae.add_supported_context(Verification)
server = scp_ae.start_server(('', 11199), block=False)
# SCU: proposes JPEG-LS first (sender's preference)
scu_ae = AE()
scu_ae.add_requested_context(sop, [jpeg_ls, implicit])
scu_ae.add_requested_context(Verification)
assoc = scu_ae.associate('127.0.0.1', 11199)
if assoc.is_established:
for cx in assoc.accepted_contexts:
if str(cx.abstract_syntax) == sop:
print('Accepted TS:', cx.transfer_syntax)
# Prints: ['1.2.840.10008.1.2'] (Implicit VR LE)
# Expected: ['1.2.840.10008.1.2.4.80'] (JPEG-LS Lossless)
assoc.release()
server.shutdown()
**Your environment**
- pynetdicom version: 2.0.2
- Python version: 3.13
- OS: Debian Linux (also reproduced on macOS with Python 3.9)
** Fix**
In `pynetdicom/presentation.py`, function `negotiate_as_acceptor`:
**Current code** (iterates acceptor's list):
```python
for tr_syntax in ac_context.transfer_syntax:
if tr_syntax in rq_context.transfer_syntax:
context.transfer_syntax = [tr_syntax]
context.result = 0x00
result_contexts.append(context)
break
Proposed fix (iterates requestor's list):
for tr_syntax in rq_context.transfer_syntax:
if tr_syntax in ac_context.transfer_syntax:
context.transfer_syntax = [tr_syntax]
context.result = 0x00
result_contexts.append(context)
break
Describe the bug
When acting as an Association Acceptor (SCP),
negotiate_as_acceptor()inpresentation.pyselects the accepted Transfer Syntax by iterating the acceptor's supported TS list and picking the first match found in the requestor's proposed list. This ignores the requestor's preference order.The DICOM convention (and the behavior of DCMTK, the reference DICOM implementation) is to iterate the requestor's proposed TS list and pick the first one the acceptor supports. The requestor lists transfer syntaxes in preference order, and the acceptor should respect that.
This causes real-world interoperability failures. For example, when a sender has JPEG-LS Lossless compressed mammography files and proposes
[JPEG-LS Lossless, Explicit VR LE, Implicit VR LE], the SCP accepts Explicit VR LE (because it appears first in the SCP's own supported list). The sender then cannot use the accepted context because it would need to decompress on the fly, which most DICOM implementations cannot do. The sender aborts the association.Expected behavior
The SCP should accept
1.2.840.10008.1.2.4.80(JPEG-LS Lossless) because it is the requestor's first-preference transfer syntax and the SCP supports it. This is how DCMTK'sstorescpbehaves. Actual behavior? The SCP accepts1.2.840.10008.1.2(Implicit VR LE) because it appears first in the SCP's own supported transfer syntax list, regardless of the requestor's preference.Steps To Reproduce
Proposed fix (iterates requestor's list):