# HG changeset patch # User Alain Mazy # Date 1687876905 -7200 # Node ID 1028b75ac1ce1b55d20395c6f632a4dcae3ce58e # Parent 739cad709a8c44280bab7957b7ca97f5b1025f51# Parent ede184638961116dafc95fd0c08db7161ed120d1 merge diff -r 739cad709a8c -r 1028b75ac1ce Tests/GuessPixelDataVR.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Tests/GuessPixelDataVR.py Tue Jun 27 16:41:45 2023 +0200 @@ -0,0 +1,60 @@ +#!/usr/bin/env python3 + +import os +import sys +import pydicom + +ROOT = os.path.join(os.path.dirname(__file__), '..', 'Database') + +for root, dirs, files in os.walk(ROOT): + for f in files: + path = os.path.join(root, f) + + try: + ds = pydicom.dcmread(path) + except: + continue + + ts = ds.file_meta.TransferSyntaxUID + + if not 'PixelData' in ds: + print(path, '=> no pixel data') + continue + + print(path) + + if ts == '1.2.840.10008.1.2': + # Implicit VR Endian + # https://dicom.nema.org/medical/dicom/current/output/chtml/part05/chapter_A.html#sect_A.1 + assert(ds['PixelData'].VR == 'OW') + + elif ts in [ '1.2.840.10008.1.2.1', + '1.2.840.10008.1.2.2' ]: + # Explicit VR Little Endian + # https://dicom.nema.org/medical/dicom/current/output/chtml/part05/sect_A.2.html + + # DICOM Big Endian Transfer Syntax (Explicit VR) - Retired, but same rule + # https://dicom.nema.org/medical/dicom/2016b/output/chtml/part05/sect_A.3.html + + if f in [ 'PilatesArgenturGEUltrasoundOsiriX.dcm', + 'KarstenHilbertRF.dcm', + 'Issue143.dcm' ]: + continue + + if ds['BitsAllocated'].value <= 8: + assert(ds['PixelData'].VR == 'OB') + else: + assert(ds['PixelData'].VR == 'OW') + + else: + if (('Beaufix/IM-' in path or + 'Comunix/Ct/IM-' in path or + 'Comunix/Pet/IM-' in path or + 'Knee/T1/IM-' in path or + 'Knee/T2/IM-' in path) and + ts == '1.2.840.10008.1.2.4.91'): + # JPEG2k should be "OB", but this is not the case of these modalities + continue + + assert(ds['PixelData'].VR == 'OB') + diff -r 739cad709a8c -r 1028b75ac1ce Tests/Tests.py --- a/Tests/Tests.py Tue Jun 27 16:41:28 2023 +0200 +++ b/Tests/Tests.py Tue Jun 27 16:41:45 2023 +0200 @@ -1171,20 +1171,13 @@ self.assertEqual(DoGet(_REMOTE, '/series/%s/metadata/RemoteAET' % series), '') # None, received by REST API m = DoGet(_REMOTE, '/instances/%s/metadata' % i) - if IsOrthancVersionAbove(_REMOTE, 1, 12, 1): - self.assertEqual(11, len(m)) - elif IsOrthancVersionAbove(_REMOTE, 1, 11, 0): + if IsOrthancVersionAbove(_REMOTE, 1, 11, 0): self.assertEqual(10, len(m)) elif IsOrthancVersionAbove(_REMOTE, 1, 9, 1): self.assertEqual(9, len(m)) else: self.assertEqual(8, len(m)) - if IsOrthancVersionAbove(_REMOTE, 1, 12, 1): - # ./Tests/GetPixelDataVR.py ./Database/Knee/T1/IM-0001-0001.dcm - self.assertTrue('PixelDataVR' in m) # New in Orthanc 1.12.1 - self.assertEqual('OW', DoGet(_REMOTE, '/instances/%s/metadata/PixelDataVR' % i)) - if IsOrthancVersionAbove(_REMOTE, 1, 11, 0): self.assertTrue('MainDicomTagsSignature' in m) @@ -1393,20 +1386,13 @@ self.assertEqual(1, len(i)) m = DoGet(_REMOTE, '/instances/%s/metadata' % i[0]) - if IsOrthancVersionAbove(_REMOTE, 1, 12, 1): - self.assertEqual(11, len(m)) - elif IsOrthancVersionAbove(_REMOTE, 1, 11, 0): + if IsOrthancVersionAbove(_REMOTE, 1, 11, 0): self.assertEqual(10, len(m)) elif IsOrthancVersionAbove(_REMOTE, 1, 9, 1): self.assertEqual(9, len(m)) else: self.assertEqual(8, len(m)) - if IsOrthancVersionAbove(_REMOTE, 1, 12, 1): - # ./Tests/GetPixelDataVR.py ./Database/ColorTestImageJ.dcm - self.assertTrue('PixelDataVR' in m) # New in Orthanc 1.12.1 - self.assertEqual('OB', DoGet(_REMOTE, '/instances/%s/metadata/PixelDataVR' % i[0])) - if IsOrthancVersionAbove(_REMOTE, 1, 11, 0): self.assertTrue('MainDicomTagsSignature' in m) # New in Orthanc 1.11.0 @@ -9793,3 +9779,38 @@ self.assertNotEqual(studyLastUpdate1, studyLastUpdate2) self.assertNotEqual(patientLastUpdate1, patientLastUpdate2) + def test_pixel_data_vr(self): + def Check(path, hasPixelData, hasMetadata, expectedVR): + i = UploadInstance(_REMOTE, path) ['ID'] + m = DoGet(_REMOTE, '/instances/%s/metadata?expand' % i) + if hasMetadata: + self.assertTrue('PixelDataVR' in m) + self.assertEqual(expectedVR, m['PixelDataVR']) + else: + self.assertFalse('PixelDataVR' in m) + + if hasPixelData: + self.assertTrue('PixelDataOffset' in m) + j = DoGet(_REMOTE, '/instances/%s/file?expand' % i, headers = { + 'Accept': 'application/dicom+json' + }) + self.assertEqual(expectedVR, j['7FE00010']['vr']) + + if IsOrthancVersionAbove(_REMOTE, 1, 12, 1): + # File without pixel data + Check('MarekLatin2.dcm', False, False, None) + + # Those files are badly formatted, and should be 'OB' + # according to the DICOM standard => medata is present + Check('Issue143.dcm', True, True, 'OW') # Little Endian Explicit, 8bpp + Check('KarstenHilbertRF.dcm', True, True, 'OW') # Little Endian Explicit, 8bpp + Check('PilatesArgenturGEUltrasoundOsiriX.dcm', True, True, 'OW') # Little Endian Explicit, 8bpp + + # Those files are formatted as expected + Check('ColorTestMalaterre.dcm', True, False, 'OW') # Implicit Little Endian, 8bpp + Check('Issue94.dcm', True, False, 'OW') # Implicit Little Endian, 16bpp + Check('TransferSyntaxes/1.2.840.10008.1.2.1.dcm', True, False, 'OB') # Explicit Little Endian, 8bpp + Check('Phenix/IM-0001-0001.dcm', True, False, 'OW') # Explicit Little Endian, 16bpp + Check('TransferSyntaxes/1.2.840.10008.1.2.2.dcm', True, False, 'OB') # Explicit Big Endian, 8bpp + Check('TransferSyntaxes/1.2.840.10008.1.2.4.50.dcm', True, False, 'OB') # JPEG + Check('Knee/T1/IM-0001-0001.dcm', True, False, 'OB') # JPEG2k