import logging
import os
import subprocess
import tempfile
import dicom2nifti.settings as settings
from dicom2nifti.exceptions import ConversionError
import pydicom
logger = logging.getLogger(__name__)
[docs]def read_file(dicom_file, defer_size=None, stop_before_pixels=False, force=False):
if _is_compressed(dicom_file, force):
with tempfile.NamedTemporaryFile() as fp:
_decompress_dicom(dicom_file, output_file=fp.name)
return pydicom.read_file(fp,
defer_size=None, # We can't defer
stop_before_pixels=stop_before_pixels,
force=force)
dicom_header = pydicom.read_file(dicom_file,
defer_size=defer_size,
stop_before_pixels=stop_before_pixels,
force=force)
return dicom_header
def _compress_dicom(input_file):
"""
This function can be used to convert a jpeg compressed image to an uncompressed one for further conversion
:param input_file: single dicom file to compress
"""
gdcmconv_executable = _get_gdcmconv()
subprocess.check_output([gdcmconv_executable, '-K', input_file, input_file])
def _get_gdcmconv():
"""
Get the full path to gdcmconv.
If not found raise error
"""
gdcmconv_executable = settings.gdcmconv_path
if gdcmconv_executable is None:
gdcmconv_executable = _which('gdcmconv')
if gdcmconv_executable is None:
gdcmconv_executable = _which('gdcmconv.exe')
if gdcmconv_executable is None:
raise ConversionError('GDCMCONV_NOT_FOUND')
return gdcmconv_executable
[docs]def compress_directory(dicom_directory):
"""
This function can be used to convert a folder of jpeg compressed images to an uncompressed ones
:param dicom_directory: directory of dicom files to compress
"""
if _is_compressed(dicom_directory):
return
logger.info('Compressing dicom files in %s' % dicom_directory)
for root, _, files in os.walk(dicom_directory):
for dicom_file in files:
if is_dicom_file(os.path.join(root, dicom_file)):
_compress_dicom(os.path.join(root, dicom_file))
[docs]def is_dicom_file(filename):
"""
Util function to check if file is a dicom file
the first 128 bytes are preamble
the next 4 bytes should contain DICM otherwise it is not a dicom
:param filename: file to check for the DICM header block
:type filename: six.string_types
:returns: True if it is a dicom file
"""
file_stream = open(filename, 'rb')
file_stream.seek(128)
data = file_stream.read(4)
file_stream.close()
if data == b'DICM':
return True
if settings.pydicom_read_force:
try:
dicom_headers = pydicom.read_file(filename, defer_size=100, stop_before_pixels=True, force=True)
if dicom_headers is not None:
return True
except:
pass
return False
def _is_compressed(dicom_file, force=False):
"""
Check if dicoms are compressed or not
"""
header = pydicom.read_file(dicom_file,
defer_size=70,
stop_before_pixels=True,
force=force)
uncompressed_types = ["1.2.840.10008.1.2",
"1.2.840.10008.1.2.1",
"1.2.840.10008.1.2.1.99",
"1.2.840.10008.1.2.2"]
if 'TransferSyntaxUID' in header.file_meta and header.file_meta.TransferSyntaxUID in uncompressed_types:
return False
return True
def _decompress_dicom(dicom_file, output_file):
"""
This function can be used to convert a jpeg compressed image to an uncompressed one for further conversion
:param input_file: single dicom file to decompress
"""
gdcmconv_executable = _get_gdcmconv()
subprocess.check_output([gdcmconv_executable, '-w', dicom_file, output_file])
def _which(program):
import os
def is_exe(executable_file):
return os.path.isfile(executable_file) and os.access(executable_file, os.X_OK)
file_path, file_name = os.path.split(program)
if file_path:
if is_exe(program):
return program
else:
for path in os.environ["PATH"].split(os.pathsep):
path = path.strip('"')
exe_file = os.path.join(path, program)
if is_exe(exe_file):
return exe_file
return None