@@ -785,25 +785,8 @@ def test_transcode_dicom_to_htj2k_multiframe_metadata(self):
785785 # Verify top-level metadata matches first frame
786786 first_original = original_datasets [0 ]
787787
788- # Check ImagePositionPatient (top-level should match first frame)
789- self .assertTrue (hasattr (ds_multiframe , "ImagePositionPatient" ), "Should have ImagePositionPatient" )
790- np .testing .assert_array_almost_equal (
791- np .array ([float (x ) for x in ds_multiframe .ImagePositionPatient ]),
792- np .array ([float (x ) for x in first_original .ImagePositionPatient ]),
793- decimal = 6 ,
794- err_msg = "Top-level ImagePositionPatient should match first original file" ,
795- )
796- print (f"✓ ImagePositionPatient matches first frame: { ds_multiframe .ImagePositionPatient } " )
797-
798- # Check ImageOrientationPatient
799- self .assertTrue (hasattr (ds_multiframe , "ImageOrientationPatient" ), "Should have ImageOrientationPatient" )
800- np .testing .assert_array_almost_equal (
801- np .array ([float (x ) for x in ds_multiframe .ImageOrientationPatient ]),
802- np .array ([float (x ) for x in first_original .ImageOrientationPatient ]),
803- decimal = 6 ,
804- err_msg = "ImageOrientationPatient should match original" ,
805- )
806- print (f"✓ ImageOrientationPatient matches original: { ds_multiframe .ImageOrientationPatient } " )
788+ # Check ImagePositionPatient is NOT there at top level DICOM file
789+ self .assertFalse (hasattr (ds_multiframe , "ImagePositionPatient" ), "Should not have ImagePositionPatient at top level" )
807790
808791 # Check PixelSpacing
809792 self .assertTrue (hasattr (ds_multiframe , "PixelSpacing" ), "Should have PixelSpacing" )
@@ -826,6 +809,37 @@ def test_transcode_dicom_to_htj2k_multiframe_metadata(self):
826809 )
827810 print (f"✓ SliceThickness matches original: { ds_multiframe .SliceThickness } " )
828811
812+ # Check SOPClassUID conversion to Enhanced/Multi-frame
813+ self .assertTrue (hasattr (ds_multiframe , "SOPClassUID" ), "Should have SOPClassUID" )
814+ self .assertTrue (hasattr (first_original , "SOPClassUID" ), "Original should have SOPClassUID" )
815+
816+ # Map of single-frame to enhanced/multi-frame SOPClassUIDs
817+ sopclass_map = {
818+ "1.2.840.10008.5.1.4.1.1.2" : "1.2.840.10008.5.1.4.1.1.2.1" , # CT -> Enhanced CT
819+ "1.2.840.10008.5.1.4.1.1.4" : "1.2.840.10008.5.1.4.1.1.4.1" , # MR -> Enhanced MR
820+ "1.2.840.10008.5.1.4.1.1.6.1" : "1.2.840.10008.5.1.4.1.1.3.1" , # US -> Ultrasound Multi-frame
821+ }
822+
823+ original_sopclass = str (first_original .SOPClassUID )
824+ multiframe_sopclass = str (ds_multiframe .SOPClassUID )
825+
826+ if original_sopclass in sopclass_map :
827+ expected_sopclass = sopclass_map [original_sopclass ]
828+ self .assertEqual (
829+ multiframe_sopclass ,
830+ expected_sopclass ,
831+ f"SOPClassUID should be converted from { original_sopclass } to { expected_sopclass } "
832+ )
833+ print (f"✓ SOPClassUID converted: { original_sopclass } -> { multiframe_sopclass } " )
834+ else :
835+ # If not in map, should remain unchanged
836+ self .assertEqual (
837+ multiframe_sopclass ,
838+ original_sopclass ,
839+ "SOPClassUID should remain unchanged if not in conversion map"
840+ )
841+ print (f"✓ SOPClassUID unchanged: { multiframe_sopclass } " )
842+
829843 # Check for PerFrameFunctionalGroupsSequence
830844 self .assertTrue (
831845 hasattr (ds_multiframe , "PerFrameFunctionalGroupsSequence" ),
@@ -868,30 +882,31 @@ def test_transcode_dicom_to_htj2k_multiframe_metadata(self):
868882 except AssertionError as e :
869883 mismatches .append (f"Frame { frame_idx } : { e } " )
870884
871- # Check PlaneOrientationSequence
872- self .assertTrue (
885+ # PlaneOrientationSequence should ONLY be in SharedFunctionalGroupsSequence, not per-frame
886+ self .assertFalse (
873887 hasattr (frame_item , "PlaneOrientationSequence" ),
874- f"Frame { frame_idx } should have PlaneOrientationSequence" ,
888+ f"Frame { frame_idx } should not have PlaneOrientationSequence" ,
875889 )
876- plane_orient = frame_item .PlaneOrientationSequence [0 ]
877- self .assertTrue (
878- hasattr (plane_orient , "ImageOrientationPatient" ),
879- f"Frame { frame_idx } should have ImageOrientationPatient in PlaneOrientationSequence" ,
880- )
881-
882- # Verify ImageOrientationPatient matches original
883- multiframe_iop = np .array ([float (x ) for x in plane_orient .ImageOrientationPatient ])
884- original_iop = np .array ([float (x ) for x in original_ds .ImageOrientationPatient ])
885890
886- try :
887- np .testing .assert_array_almost_equal (
888- multiframe_iop ,
889- original_iop ,
890- decimal = 6 ,
891- err_msg = f"Frame { frame_idx } ImageOrientationPatient should match original" ,
892- )
893- except AssertionError as e :
894- mismatches .append (f"Frame { frame_idx } : { e } " )
891+ # Verify ImageOrientationPatient in SharedFunctionalGroupsSequence matches original
892+ shared_fg = ds_multiframe .SharedFunctionalGroupsSequence [0 ]
893+ self .assertTrue (
894+ hasattr (shared_fg , "PlaneOrientationSequence" ),
895+ "SharedFunctionalGroupsSequence should have PlaneOrientationSequence" ,
896+ )
897+ plane_orient = shared_fg .PlaneOrientationSequence [0 ]
898+ multiframe_iop = np .array ([float (x ) for x in plane_orient .ImageOrientationPatient ])
899+ original_iop = np .array ([float (x ) for x in original_datasets [0 ].ImageOrientationPatient ]) # Use first frame
900+
901+ try :
902+ np .testing .assert_array_almost_equal (
903+ multiframe_iop ,
904+ original_iop ,
905+ decimal = 6 ,
906+ err_msg = "SharedFunctionalGroupsSequence ImageOrientationPatient should match original" , # Remove frame_idx
907+ )
908+ except AssertionError as e :
909+ mismatches .append (f"Shared orientation: { e } " ) # Remove frame_idx reference
895910
896911 # Report any mismatches
897912 if mismatches :
0 commit comments