this gist is used as a supporting doc, in response to
https://github.com/pydicom/pydicom/discussions/1705
Last active
May 24, 2024 08:06
-
-
Save pangyuteng/803cf2fda3d7568aaa348fdd409937d7 to your computer and use it in GitHub Desktop.
DO-NOT-USE dicom multiframe to single frame conversion
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
import sys | |
import pydicom | |
essential_group_list = [0x0008,0x0010,0x0018,0x0020,0x0028] | |
def main(input_file,output_folder): | |
os.makedirs(output_folder,exist_ok=True) | |
ds = pydicom.dcmread(input_file) | |
number_of_frames = int(ds.NumberOfFrames) | |
# requirements | |
assert(number_of_frames > 1) | |
assert(ds.pixel_array.shape[0]==number_of_frames) | |
assert('SharedFunctionalGroupsSequence' in ds) | |
assert('PerFrameFunctionalGroupsSequence' in ds) | |
assert(len(ds.SharedFunctionalGroupsSequence)==1) | |
assert(len(ds.PerFrameFunctionalGroupsSequence)==number_of_frames) | |
img = ds.pixel_array.squeeze() | |
for idx in range(number_of_frames): | |
target_file = os.path.join(output_folder,f'foobar.{idx:05d}.dcm') | |
file_meta = pydicom.dataset.FileMetaDataset() | |
file_meta.MediaStorageSOPClassUID = pydicom.uid.SecondaryCaptureImageStorage | |
file_meta.MediaStorageSOPInstanceUID = pydicom.uid.generate_uid() | |
file_meta.TransferSyntaxUID = pydicom.uid.ImplicitVRLittleEndian # pydicom.uid.ExplicitVRLittleEndian | |
tmp_ds = pydicom.dataset.Dataset() | |
tmp_ds.file_meta = file_meta | |
tmp_ds.is_little_endian = tmp_ds.file_meta.TransferSyntaxUID.is_little_endian | |
tmp_ds.is_implicit_VR = tmp_ds.file_meta.TransferSyntaxUID.is_implicit_VR | |
essential_group_list = [0x0020,0x0028] # barebones... | |
for group in essential_group_list: | |
for k,v in ds.group_dataset(group).items(): | |
tmp_ds[k]=v | |
foo = ds.SharedFunctionalGroupsSequence[0] | |
bar = ds.PerFrameFunctionalGroupsSequence[idx] | |
for tag_name in ['RescaleIntercept','RescaleSlope','RescaleType']: | |
if tag_name in foo[(0x0028,0x9145)][0]: | |
value = foo[(0x0028,0x9145)][0][tag_name].value | |
setattr(tmp_ds,tag_name,value) | |
del tmp_ds.NumberOfFrames | |
tmp_ds.InstanceNumber = idx+1 | |
tmp_ds.PixelData = img[idx,:].squeeze().tobytes() | |
tmp_ds.save_as(target_file,write_like_original=False) | |
if __name__ == "__main__": | |
input_file = sys.argv[1] | |
output_folder = sys.argv[2] | |
raise NotImplementedError() | |
main(input_file,output_folder) | |
''' | |
** DISCLAIMER ** | |
i definitely would not use the above. | |
only tested using 1 hologic tomosythesis multiframe file. | |
Clients should acknowledge and accept they are okay having private tags nuked. | |
Further, to prove this method works, | |
you'll need to gather dicom file flavors from your clients/institutions and then implement and verify | |
the output dicom files can be opened by downstream workstations | |
''' |
First you should google the current top results in google
keywords I used: "split dicom multiframe to single frame"
If you don't like the results you can check the below related links:
i reserve all rights to not respond to questions here XDDDD
please go to stackoverflow and ask your questions there!
--
-
relevant discussion in pydicom ! pydicom/pydicom#1705
-
long thread: https://groups.google.com/g/comp.protocols.dicom/c/h-8rj9ObBMM?pli=1
-
existing tools:
- dclunie's dicom3tools
dcuncat
(you will need to compile it yourself)
https://github.com/QIICR/dicom3tools/blob/master/appsrc/dcfile/dcuncat.cc https://github.com/QIICR/dicom3tools/blob/master/INSTALL original site - https://www.dclunie.com/dicom3tools.html
- dcm4chee's emf2sf (java yucky, haven't tried)
https://github.com/dcm4che/dcm4che/blob/master/dcm4che-tool/dcm4che-tool-emf2sf/README.md
- gdcm's gdcmtar (tried, did not work for 1 test scan - hologic tomosythesis)
https://gdcm.sourceforge.net/html/gdcmtar.html
- work-in-progress over at highdicom
https://github.com/dcm4che/dcm4che/blob/master/dcm4che-tool/dcm4che-tool-emf2sf/README.md
- last resort: copy and start hacking using my below
do-not-use.py
- dclunie's dicom3tools
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
personal relevant gist
https://gist.github.com/pangyuteng/2fbaea6b1eebb310fe46eef4d8f7e18f