def process_dicom_directory(dicom_directory, parent_sorting_field='PatientName', output_image_name_format='{parent_sorting_data}_{study_uid_index}_{Modality}_{image_desc}_{SeriesNumber}', output_structure_name_format='{parent_sorting_data}_{study_uid_index}_{Modality}_{structure_name}', output_dose_name_format='{parent_sorting_data}_{study_uid_index}_{DoseSummationType}', return_extra=True, output_directory='./', output_file_suffix='.nii.gz', overwrite_existing_files=False, write_to_disk=True, verbose=False, initial_sop_class_name_default='UNKNOWN'):
    if (isinstance(dicom_directory, str) or isinstance(dicom_directory, pathlib.Path)):
        root_path = pathlib.Path(dicom_directory)
        dicom_file_list = [p for p in root_path.glob('**/*') if (p.name.lower().endswith('.dcm') or p.name.lower().endswith('.dc3'))]
    elif hasattr(dicom_directory, '__iter__'):
        dicom_file_list = []
        for dicom_dir in dicom_directory:
            root_path = pathlib.Path(dicom_dir)
            dicom_file_list += [p for p in root_path.glob('**/*') if (p.name.lower().endswith('.dcm') or p.name.lower().endswith('.dc3'))]
    if (len(dicom_file_list) == 0):
        logger.info('No DICOM files found in input directory. Exiting now.')
        return
    dicom_series_dict_parent = process_dicom_file_list(dicom_file_list, parent_sorting_field=parent_sorting_field, verbose=verbose)
    if (dicom_series_dict_parent is None):
        logger.info('No valid DICOM files found. Ending.')
        return None
    output = {}
    for (parent_data, dicom_series_dict) in dicom_series_dict_parent.items():
        logger.info(f'Processing data for {parent_sorting_field} = {parent_data}.')
        logger.info(f'  Number of DICOM series = {len(dicom_series_dict.keys())}')
        output_data_dict = {}
        study_uid_dict = {}
        logger.debug(f'  Output image name format: {output_image_name_format}')
        logger.debug(f'  Output structure name format: {output_structure_name_format}')
        logger.debug(f'  Output dose name format: {output_dose_name_format}')
        for series_uid in dicom_series_dict.keys():
            for (dicom_type, dicom_file_metadata, initial_dicom, dicom_file_data) in process_dicom_series(dicom_series_dict=dicom_series_dict, series_uid=series_uid, parent_sorting_field=parent_sorting_field, return_extra=return_extra, initial_sop_class_name_default=initial_sop_class_name_default):
                parent_sorting_data = dicom_file_metadata['parent_sorting_data']
                if ('parent_sorting_data' not in output_data_dict.keys()):
                    output_data_dict['parent_sorting_data'] = parent_sorting_data
                elif (parent_sorting_data != output_data_dict['parent_sorting_data']):
                    logger.error(f'A conflict was found for the parent sorting field ({parent_sorting_field}): {parent_sorting_data}')
                    logger.error('Quitting now.')
                    print(dicom_series_dict_parent.keys())
                    sys.exit()
                else:
                    logger.info(f'  Parent sorting field ({parent_sorting_field}) match found: {parent_sorting_data}')
                study_uid = dicom_file_metadata['study_uid']
                if (study_uid not in study_uid_dict.keys()):
                    try:
                        study_uid_index = (max(study_uid_dict.values()) + 1)
                    except AttributeError:
                        study_uid_index = 0
                    except ValueError:
                        study_uid_index = 0
                    logger.info(f'  Setting study instance UID index: {study_uid_index}')
                    study_uid_dict[study_uid] = study_uid_index
                else:
                    logger.info(f'  Study instance UID index already exists: {study_uid_dict[study_uid]}')
                special_name_fields = ['parent_sorting_data', 'study_uid_index', 'image_desc', 'structure_name']
                image_desc = get_dicom_info_from_description(initial_dicom, return_extra=return_extra)
                if (dicom_type == 'IMAGES'):
                    all_naming_fields = [i[(i.find('{') + 1):] for i in output_image_name_format.split('}') if (len(i) > 0)]
                elif (dicom_type == 'STRUCTURES'):
                    all_naming_fields = [i[(i.find('{') + 1):] for i in output_structure_name_format.split('}') if (len(i) > 0)]
                elif (dicom_type == 'DOSES'):
                    all_naming_fields = [i[(i.find('{') + 1):] for i in output_dose_name_format.split('}') if (len(i) > 0)]
                dicom_header_tags = [i for i in all_naming_fields if (i not in special_name_fields)]
                naming_info_dict = {}
                for dicom_field in dicom_header_tags:
                    try:
                        dicom_field_value = initial_dicom[dicom_field].value
                    except (AttributeError, KeyError):
                        logger.warning(f'  Could not find DICOM header {dicom_field}. Setting as 0 to preserve naming convention.')
                        dicom_field_value = 0
                    naming_info_dict[dicom_field] = dicom_field_value
                if (dicom_type == 'IMAGES'):
                    output_name = output_image_name_format.format(parent_sorting_data=parent_sorting_data, study_uid_index=study_uid_dict[study_uid], image_desc=image_desc, **naming_info_dict)
                    if ('IMAGES' not in output_data_dict.keys()):
                        output_data_dict['IMAGES'] = {output_name: dicom_file_data}
                    elif (output_name not in output_data_dict['IMAGES'].keys()):
                        output_data_dict['IMAGES'][output_name] = dicom_file_data
                    else:
                        logger.info('      An image with this name exists, appending.')
                        if hasattr(output_data_dict['IMAGES'][output_name], '__iter__'):
                            output_data_dict['IMAGES'][output_name] = list([output_data_dict['IMAGES'][output_name]])
                        output_data_dict['IMAGES'][output_name].append(dicom_file_data)
                elif (dicom_type == 'STRUCTURES'):
                    for (structure_name, structure_image) in zip(dicom_file_metadata['structure_name_list'], dicom_file_data):
                        output_name = output_structure_name_format.format(parent_sorting_data=parent_sorting_data, study_uid_index=study_uid_dict[study_uid], image_desc=image_desc, structure_name=structure_name, **naming_info_dict)
                        if ('STRUCTURES' not in output_data_dict.keys()):
                            output_data_dict['STRUCTURES'] = {output_name: structure_image}
                        elif (output_name not in output_data_dict['STRUCTURES'].keys()):
                            output_data_dict['STRUCTURES'][output_name] = structure_image
                        else:
                            logger.info('      A structure with this name exists, appending.')
                            if hasattr(output_data_dict['STRUCTURES'][output_name], '__iter__'):
                                output_data_dict['STRUCTURES'][output_name] = list([output_data_dict['STRUCTURES'][output_name]])
                            output_data_dict['STRUCTURES'][output_name].append(structure_image)
                elif (dicom_type == 'DOSES'):
                    output_name = output_dose_name_format.format(parent_sorting_data=parent_sorting_data, study_uid_index=study_uid_dict[study_uid], **naming_info_dict)
                    if ('DOSES' not in output_data_dict.keys()):
                        output_data_dict['DOSES'] = {output_name: dicom_file_data}
                    elif (output_name not in output_data_dict['DOSES'].keys()):
                        output_data_dict['DOSES'][output_name] = dicom_file_data
                    else:
                        logger.info('      An image with this name exists, appending.')
                        if isinstance(output_data_dict['DOSES'][output_name], sitk.Image):
                            output_data_dict['DOSES'][output_name] = list([output_data_dict['DOSES'][output_name]])
                        output_data_dict['DOSES'][output_name].append(dicom_file_data)
        if write_to_disk:
            output[str(parent_data)] = write_output_data_to_disk(output_data_dict=output_data_dict, output_directory=output_directory, output_file_suffix=output_file_suffix, overwrite_existing_files=overwrite_existing_files)
        else:
            output[str(parent_data)] = output_data_dict
    '\n    TO DO!\n    Memory issue with output_data_dict\n    Use in inner loop, reset output_data_dict\n    '
    return output
def process_dicom_directory(dicom_directory, parent_sorting_field='PatientName', output_image_name_format='{parent_sorting_data}_{study_uid_index}_{Modality}_{image_desc}_{SeriesNumber}', output_structure_name_format='{parent_sorting_data}_{study_uid_index}_{Modality}_{structure_name}', output_dose_name_format='{parent_sorting_data}_{study_uid_index}_{DoseSummationType}', return_extra=True, output_directory='./', output_file_suffix='.nii.gz', overwrite_existing_files=False, write_to_disk=True, verbose=False, initial_sop_class_name_default='UNKNOWN'):
    if (isinstance(dicom_directory, str) or isinstance(dicom_directory, pathlib.Path)):
        root_path = pathlib.Path(dicom_directory)
        dicom_file_list = [p for p in root_path.glob('**/*') if (p.name.lower().endswith('.dcm') or p.name.lower().endswith('.dc3'))]
    elif hasattr(dicom_directory, '__iter__'):
        dicom_file_list = []
        for dicom_dir in dicom_directory:
            root_path = pathlib.Path(dicom_dir)
            dicom_file_list += [p for p in root_path.glob('**/*') if (p.name.lower().endswith('.dcm') or p.name.lower().endswith('.dc3'))]
    if (len(dicom_file_list) == 0):
        logger.info('No DICOM files found in input directory. Exiting now.')
        return
    dicom_series_dict_parent = process_dicom_file_list(dicom_file_list, parent_sorting_field=parent_sorting_field, verbose=verbose)
    if (dicom_series_dict_parent is None):
        logger.info('No valid DICOM files found. Ending.')
        return None
    output = {}
    for (parent_data, dicom_series_dict) in dicom_series_dict_parent.items():
        logger.info(f'Processing data for {parent_sorting_field} = {parent_data}.')
        logger.info(f'  Number of DICOM series = {len(dicom_series_dict.keys())}')
        output_data_dict = {}
        study_uid_dict = {}
        logger.debug(f'  Output image name format: {output_image_name_format}')
        logger.debug(f'  Output structure name format: {output_structure_name_format}')
        logger.debug(f'  Output dose name format: {output_dose_name_format}')
        for series_uid in dicom_series_dict.keys():
            for (dicom_type, dicom_file_metadata, initial_dicom, dicom_file_data) in process_dicom_series(dicom_series_dict=dicom_series_dict, series_uid=series_uid, parent_sorting_field=parent_sorting_field, return_extra=return_extra, initial_sop_class_name_default=initial_sop_class_name_default):
                parent_sorting_data = dicom_file_metadata['parent_sorting_data']
                if ('parent_sorting_data' not in output_data_dict.keys()):
                    output_data_dict['parent_sorting_data'] = parent_sorting_data
                elif (parent_sorting_data != output_data_dict['parent_sorting_data']):
                    logger.error(f'A conflict was found for the parent sorting field ({parent_sorting_field}): {parent_sorting_data}')
                    logger.error('Quitting now.')
                    print(dicom_series_dict_parent.keys())
                    sys.exit()
                else:
                    logger.info(f'  Parent sorting field ({parent_sorting_field}) match found: {parent_sorting_data}')
                study_uid = dicom_file_metadata['study_uid']
                if (study_uid not in study_uid_dict.keys()):
                    try:
                        study_uid_index = (max(study_uid_dict.values()) + 1)
                    except AttributeError:
                        study_uid_index = 0
                    except ValueError:
                        study_uid_index = 0
                    logger.info(f'  Setting study instance UID index: {study_uid_index}')
                    study_uid_dict[study_uid] = study_uid_index
                else:
                    logger.info(f'  Study instance UID index already exists: {study_uid_dict[study_uid]}')
                special_name_fields = ['parent_sorting_data', 'study_uid_index', 'image_desc', 'structure_name']
                image_desc = get_dicom_info_from_description(initial_dicom, return_extra=return_extra)
                if (dicom_type == 'IMAGES'):
                    all_naming_fields = [i[(i.find('{') + 1):] for i in output_image_name_format.split('}') if (len(i) > 0)]
                elif (dicom_type == 'STRUCTURES'):
                    all_naming_fields = [i[(i.find('{') + 1):] for i in output_structure_name_format.split('}') if (len(i) > 0)]
                elif (dicom_type == 'DOSES'):
                    all_naming_fields = [i[(i.find('{') + 1):] for i in output_dose_name_format.split('}') if (len(i) > 0)]
                dicom_header_tags = [i for i in all_naming_fields if (i not in special_name_fields)]
                naming_info_dict = {}
                for dicom_field in dicom_header_tags:
                    try:
                        dicom_field_value = initial_dicom[dicom_field].value
                    except (AttributeError, KeyError):
                        logger.warning(f'  Could not find DICOM header {dicom_field}. Setting as 0 to preserve naming convention.')
                        dicom_field_value = 0
                    naming_info_dict[dicom_field] = dicom_field_value
                if (dicom_type == 'IMAGES'):
                    output_name = output_image_name_format.format(parent_sorting_data=parent_sorting_data, study_uid_index=study_uid_dict[study_uid], image_desc=image_desc, **naming_info_dict)
                    if ('IMAGES' not in output_data_dict.keys()):
                        output_data_dict['IMAGES'] = {output_name: dicom_file_data}
                    elif (output_name not in output_data_dict['IMAGES'].keys()):
                        output_data_dict['IMAGES'][output_name] = dicom_file_data
                    else:
                        logger.info('      An image with this name exists, appending.')
                        if hasattr(output_data_dict['IMAGES'][output_name], '__iter__'):
                            output_data_dict['IMAGES'][output_name] = list([output_data_dict['IMAGES'][output_name]])
                        output_data_dict['IMAGES'][output_name].append(dicom_file_data)
                elif (dicom_type == 'STRUCTURES'):
                    for (structure_name, structure_image) in zip(dicom_file_metadata['structure_name_list'], dicom_file_data):
                        output_name = output_structure_name_format.format(parent_sorting_data=parent_sorting_data, study_uid_index=study_uid_dict[study_uid], image_desc=image_desc, structure_name=structure_name, **naming_info_dict)
                        if ('STRUCTURES' not in output_data_dict.keys()):
                            output_data_dict['STRUCTURES'] = {output_name: structure_image}
                        elif (output_name not in output_data_dict['STRUCTURES'].keys()):
                            output_data_dict['STRUCTURES'][output_name] = structure_image
                        else:
                            logger.info('      A structure with this name exists, appending.')
                            if hasattr(output_data_dict['STRUCTURES'][output_name], '__iter__'):
                                output_data_dict['STRUCTURES'][output_name] = list([output_data_dict['STRUCTURES'][output_name]])
                            output_data_dict['STRUCTURES'][output_name].append(structure_image)
                elif (dicom_type == 'DOSES'):
                    output_name = output_dose_name_format.format(parent_sorting_data=parent_sorting_data, study_uid_index=study_uid_dict[study_uid], **naming_info_dict)
                    if ('DOSES' not in output_data_dict.keys()):
                        output_data_dict['DOSES'] = {output_name: dicom_file_data}
                    elif (output_name not in output_data_dict['DOSES'].keys()):
                        output_data_dict['DOSES'][output_name] = dicom_file_data
                    else:
                        logger.info('      An image with this name exists, appending.')
                        if isinstance(output_data_dict['DOSES'][output_name], sitk.Image):
                            output_data_dict['DOSES'][output_name] = list([output_data_dict['DOSES'][output_name]])
                        output_data_dict['DOSES'][output_name].append(dicom_file_data)
        if write_to_disk:
            output[str(parent_data)] = write_output_data_to_disk(output_data_dict=output_data_dict, output_directory=output_directory, output_file_suffix=output_file_suffix, overwrite_existing_files=overwrite_existing_files)
        else:
            output[str(parent_data)] = output_data_dict
    '\n    TO DO!\n    Memory issue with output_data_dict\n    Use in inner loop, reset output_data_dict\n    '
    return output