changeset 296:b55b959647ed c-get

merge default -> c-get
author Alain Mazy <alain@mazy.be>
date Tue, 12 May 2020 14:36:29 +0200
parents 946b2199f481 (current diff) 192665e6113f (diff)
children da2be3ff2db5
files Tests/Tests.py
diffstat 6 files changed, 219 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Tue May 12 13:21:38 2020 +0200
+++ b/.hgtags	Tue May 12 14:36:29 2020 +0200
@@ -17,3 +17,5 @@
 99acf0c17348ba6de9a1e2e222a9051ec3af3a23 Orthanc-1.6.0
 a49055a3399b9015335e54f5a622b4432d303f61 Orthanc-1.6.0
 b55a7cb5ee0229f48b7d90e9a05dc15efe2206ec Orthanc-1.6.1
+b55a7cb5ee0229f48b7d90e9a05dc15efe2206ec Orthanc-1.6.1
+2dc6ab42f40133e6e3480a5c03e4b33c9ff34845 Orthanc-1.6.1
Binary file Database/Issue169.dcm.bz2 has changed
--- a/README	Tue May 12 13:21:38 2020 +0200
+++ b/README	Tue May 12 14:36:29 2020 +0200
@@ -135,6 +135,21 @@
 Note that you will have to grant root access for Docker.
 
 
+(Option 2c) On Windows:
+
+Easiest way to run the integration test under windows is actually
+run the remote Orthanc and the python script under WSL and run the
+orthanc under test on Windows (such that you can debug it).
+Note that if Orthanc on Windows is not using the standard port, you
+may specify them when starting the test as shown below
+
+# bash
+# python Tests/Run.py --force --dicom 8567 --rest 8568
+
+Note that you will have to install Linux prerequisites under WSL
+and the orthanc package as well.
+
+
 
 Licensing
 =========
--- a/Tests/Run.py	Tue May 12 13:21:38 2020 +0200
+++ b/Tests/Run.py	Tue May 12 14:36:29 2020 +0200
@@ -105,11 +105,18 @@
 config = re.sub(r'("DicomModalities"\s*:)\s*{', r'\1 { "orthanc" : [ "%s", "%s", %s ]' % 
                 (args.aet, args.server, args.dicom), config)
 
+# New to test transcoding over DICOM (1.7.0)
+config = re.sub(r'("RleTransferSyntaxAccepted"\s*:)\s*true', r'\1 false', config)
+
+
 with open(CONFIG, 'wt') as f:
     f.write(config)
 
 localOrthanc = ExternalCommandThread([ 
-    'Orthanc', CONFIG, #'--verbose',
+    'Orthanc', 
+    CONFIG, 
+    #'--verbose', 
+    #'--no-jobs'
     #'/home/jodogne/Subversion/Orthanc/i/Orthanc', CONFIG, '--verbose'
 ])
 
--- a/Tests/Tests.py	Tue May 12 13:21:38 2020 +0200
+++ b/Tests/Tests.py	Tue May 12 14:36:29 2020 +0200
@@ -22,6 +22,7 @@
 
 
 import base64
+import bz2
 import copy
 import pprint
 import tempfile
@@ -139,7 +140,6 @@
 
 
 
-
 class Orthanc(unittest.TestCase):
     def setUp(self):
         if (sys.version_info >= (3, 0)):
@@ -5451,6 +5451,189 @@
         self.assertEqual(1, len(DoGet(_LOCAL, '/instances')))
         self.assertEqual(0, len(DoGet(_REMOTE, '/instances')))
 
+
+    def test_storescu_transcoding(self):  # New in Orthanc 1.7.0       
+        # Add a RLE-encoded DICOM file
+        i = UploadInstance(_REMOTE, 'TransferSyntaxes/1.2.840.10008.1.2.5.dcm')['ID']
+        self.assertEqual(0, len(DoGet(_LOCAL, '/instances')))
+        self.assertEqual(1, len(DoGet(_REMOTE, '/instances')))
+        rleSize = len(DoGet(_REMOTE, '/instances/%s/file' % i))
+
+        # Export the instance, with transcoding: "_REMOTE" is the
+        # Orthanc server being tested
+        try:
+            DoDelete(_REMOTE, '/modalities/toto')
+        except:
+            pass
+
+        params = DoGet(_REMOTE, '/modalities?expand') ['orthanctest']
+        DoPut(_REMOTE, '/modalities/toto', params)
+        DoPost(_REMOTE, '/modalities/toto/store', str(i), 'text/plain')
+        j = DoGet(_LOCAL, '/instances')
+        self.assertEqual(1, len(j))
+        uncompressedSize = len(DoGet(_LOCAL, '/instances/%s/file' % j[0]))
+        self.assertTrue(uncompressedSize > rleSize / 2)
+
+        # Export, with transcoding disabled => this fails
+        params['AllowTranscoding'] = False
+        DoPut(_REMOTE, '/modalities/toto', params)
+        self.assertRaises(Exception, lambda: DoPost(_REMOTE, '/modalities/toto/store', str(i), 'text/plain'))
+
+
+    def test_bitbucket_issue_169(self):
+        with open(GetDatabasePath('Issue169.dcm.bz2'), 'rb') as f:
+            dicom = bz2.decompress(f.read())
+
+        self.assertEqual('1.2.840.10008.1.2.1', GetTransferSyntax(dicom))
+
+        self.assertEqual(44350560, len(dicom))
+        i = DoPost(_REMOTE, '/instances', dicom, 'application/dicom') ['ID']
+        
+        tags = DoGet(_REMOTE, '/instances/%s/tags' % i)
+        self.assertEqual('NORMAL', tags['1337,1001']['Value'])
+        
+        self.assertEqual(0, len(DoGet(_LOCAL, '/instances')))
+        DoPost(_REMOTE, '/modalities/orthanctest/store', str(i), 'text/plain')
+        j = DoGet(_LOCAL, '/instances')
+        self.assertEqual(1, len(j))
+
+        # In Orthanc <= 1.6.1, transfer syntax changed from "Explicit
+        # VR Little Endian" (1.2.840.10008.1.2.1) to "Implicit VR
+        # Little Endian" (1.2.840.10008.1.2)
+        self.assertEqual('1.2.840.10008.1.2.1', GetTransferSyntax(
+            DoGet(_LOCAL, '/instances/%s/file' % j[0])))
+
+        # In Orthanc <= 1.6.1, the value of the private tags was lost
+        # because of this transcoding
+        tags = DoGet(_LOCAL, '/instances/%s/tags' % j[0])
+        self.assertEqual('NORMAL', tags['1337,1001']['Value'])
+
+
+    def test_modify_transcode(self):
+        i = UploadInstance(_REMOTE, 'KarstenHilbertRF.dcm')['ID']
+        self.assertEqual('1.2.840.10008.1.2.1', GetTransferSyntax(
+            DoGet(_REMOTE, '/instances/%s/file' % i)))
+
+        for syntax in [
+                '1.2.840.10008.1.2',        
+                '1.2.840.10008.1.2.1',
+                #'1.2.840.10008.1.2.1.99',  # Deflated Explicit VR Little Endian
+                '1.2.840.10008.1.2.2',
+                '1.2.840.10008.1.2.4.50',
+                '1.2.840.10008.1.2.4.51',
+                '1.2.840.10008.1.2.4.57',
+                '1.2.840.10008.1.2.4.70',
+                #'1.2.840.10008.1.2.4.80',  # This makes DCMTK 3.6.2 crash
+                #'1.2.840.10008.1.2.4.81',  # This makes DCMTK 3.6.2 crash
+        ]:
+            transcoded = DoPost(_REMOTE, '/instances/%s/modify' % i, {
+                'Transcode' : syntax,
+                })
+            
+            self.assertEqual(syntax, GetTransferSyntax(transcoded))
+
+
+    def test_archive_transcode(self):
+        info = UploadInstance(_REMOTE, 'KarstenHilbertRF.dcm')
+
+        # GET on "/media"
+        z = GetArchive(_REMOTE, '/patients/%s/media' % info['ParentPatient'])
+        self.assertEqual(2, len(z.namelist()))
+        self.assertEqual('1.2.840.10008.1.2.1', GetTransferSyntax(z.read('IMAGES/IM0')))
+
+        self.assertRaises(Exception, lambda: DoGet(_REMOTE, '/patients/%s/media?transcode=nope' % info['ParentPatient']))
+
+        z = GetArchive(_REMOTE, '/patients/%s/media?transcode=1.2.840.10008.1.2.4.50' % info['ParentPatient'])
+        self.assertEqual('1.2.840.10008.1.2.4.50', GetTransferSyntax(z.read('IMAGES/IM0')))
+
+        z = GetArchive(_REMOTE, '/studies/%s/media?transcode=1.2.840.10008.1.2.4.51' % info['ParentStudy'])
+        self.assertEqual('1.2.840.10008.1.2.4.51', GetTransferSyntax(z.read('IMAGES/IM0')))
+
+        z = GetArchive(_REMOTE, '/series/%s/media?transcode=1.2.840.10008.1.2.4.57' % info['ParentSeries'])
+        self.assertEqual('1.2.840.10008.1.2.4.57', GetTransferSyntax(z.read('IMAGES/IM0')))
+
+
+        # POST on "/media"
+        self.assertRaises(Exception, lambda: PostArchive(
+            _REMOTE, '/patients/%s/media' % info['ParentPatient'], { 'Transcode' : 'nope' }))
+
+        z = PostArchive(_REMOTE, '/patients/%s/media' % info['ParentPatient'], {
+            'Transcode' : '1.2.840.10008.1.2.4.50',
+            })
+        self.assertEqual('1.2.840.10008.1.2.4.50', GetTransferSyntax(z.read('IMAGES/IM0')))
+
+        z = PostArchive(_REMOTE, '/studies/%s/media' % info['ParentStudy'], {
+            'Transcode' : '1.2.840.10008.1.2.4.51',
+            })
+        self.assertEqual('1.2.840.10008.1.2.4.51', GetTransferSyntax(z.read('IMAGES/IM0')))
+
+        z = PostArchive(_REMOTE, '/series/%s/media' % info['ParentSeries'], {
+            'Transcode' : '1.2.840.10008.1.2.4.57',
+            })
+        self.assertEqual('1.2.840.10008.1.2.4.57', GetTransferSyntax(z.read('IMAGES/IM0')))
+
+        
+        # GET on "/archive"
+        z = GetArchive(_REMOTE, '/patients/%s/archive' % info['ParentPatient'])
+        self.assertEqual(1, len(z.namelist()))
+        self.assertEqual('1.2.840.10008.1.2.1', GetTransferSyntax(z.read(z.namelist()[0])))
+
+        self.assertRaises(Exception, lambda: DoGet(_REMOTE, '/patients/%s/archive?transcode=nope' % info['ParentPatient']))
+
+        z = GetArchive(_REMOTE, '/patients/%s/archive?transcode=1.2.840.10008.1.2' % info['ParentPatient'])
+        self.assertEqual('1.2.840.10008.1.2', GetTransferSyntax(z.read(z.namelist()[0])))
+
+        z = GetArchive(_REMOTE, '/studies/%s/archive?transcode=1.2.840.10008.1.2.2' % info['ParentStudy'])
+        self.assertEqual('1.2.840.10008.1.2.2', GetTransferSyntax(z.read(z.namelist()[0])))
+
+        z = GetArchive(_REMOTE, '/series/%s/archive?transcode=1.2.840.10008.1.2.4.70' % info['ParentSeries'])
+        self.assertEqual('1.2.840.10008.1.2.4.70', GetTransferSyntax(z.read(z.namelist()[0])))
+
+
+        # POST on "/archive"
+        self.assertRaises(Exception, lambda: PostArchive(
+            _REMOTE, '/patients/%s/archive' % info['ParentPatient'], { 'Transcode' : 'nope' }))
+
+        z = PostArchive(_REMOTE, '/patients/%s/archive' % info['ParentPatient'], {
+            'Transcode' : '1.2.840.10008.1.2.4.50',
+            })
+        self.assertEqual('1.2.840.10008.1.2.4.50', GetTransferSyntax(z.read(z.namelist()[0])))
+
+        z = PostArchive(_REMOTE, '/studies/%s/archive' % info['ParentStudy'], {
+            'Transcode' : '1.2.840.10008.1.2.4.51',
+            })
+        self.assertEqual('1.2.840.10008.1.2.4.51', GetTransferSyntax(z.read(z.namelist()[0])))
+
+        z = PostArchive(_REMOTE, '/series/%s/archive' % info['ParentSeries'], {
+            'Transcode' : '1.2.840.10008.1.2.4.57',
+            })
+        self.assertEqual('1.2.840.10008.1.2.4.57', GetTransferSyntax(z.read(z.namelist()[0])))
+        
+
+        # "/tools/create-*"
+        z = PostArchive(_REMOTE, '/tools/create-archive', {
+            'Resources' : [ info['ParentStudy'] ],
+            'Transcode' : '1.2.840.10008.1.2.4.50',
+            })
+        self.assertEqual(1, len(z.namelist()))
+        self.assertEqual('1.2.840.10008.1.2.4.50', GetTransferSyntax(z.read(z.namelist()[0])))
+
+        z = PostArchive(_REMOTE, '/tools/create-media', {
+            'Resources' : [ info['ParentStudy'] ],
+            'Transcode' : '1.2.840.10008.1.2.4.51',
+            })
+        self.assertEqual(2, len(z.namelist()))
+        self.assertEqual('1.2.840.10008.1.2.4.51', GetTransferSyntax(z.read('IMAGES/IM0')))
+
+        z = PostArchive(_REMOTE, '/tools/create-media-extended', {
+            'Resources' : [ info['ParentStudy'] ],
+            'Transcode' : '1.2.840.10008.1.2.4.57',
+            })
+        self.assertEqual(2, len(z.namelist()))
+        self.assertEqual('1.2.840.10008.1.2.4.57', GetTransferSyntax(z.read('IMAGES/IM0')))
+
+        
+
     def test_getscu(self):
         
         # no transcoding required
--- a/Tests/Toolbox.py	Tue May 12 13:21:38 2020 +0200
+++ b/Tests/Toolbox.py	Tue May 12 14:36:29 2020 +0200
@@ -26,6 +26,7 @@
 import re
 import signal
 import subprocess
+import tempfile
 import threading
 import sys
 import time
@@ -379,3 +380,12 @@
 
     else:
         self.assertAlmostEqual(a, b, places = places)
+
+
+def GetTransferSyntax(dicom):
+    with tempfile.NamedTemporaryFile(delete = True) as f:
+        f.write(dicom)
+        f.flush()
+        data = subprocess.check_output([ FindExecutable('dcm2xml'), f.name ])
+
+    return re.search('<data-set xfer="(.*?)"', data).group(1)