Пример #1
0
def remove_private_identifiers(dicom_files,
                               save=True,
                               overwrite=False,
                               output_folder=None,
                               force=True):
    """remove_private_identifiers is a wrapper for the 
    simple call to dicom.remove_private_tags, it simply
    reads in the files for the user and saves accordingly
    """
    updated_files = []
    if not isinstance(dicom_files, list):
        dicom_files = [dicom_files]

    for dicom_file in dicom_files:
        dicom = read_file(dicom_file, force=force)
        dicom.remove_private_tags()
        dicom_name = os.path.basename(dicom_file)
        bot.debug("Removed private identifiers for %s" % dicom_name)

        if save:
            dicom = save_dicom(
                dicom=dicom,
                dicom_file=dicom_file,
                output_folder=output_folder,
                overwrite=overwrite,
            )

        updated_files.append(dicom)
    return updated_files
Пример #2
0
 def save(self, filename, overwrite=False):
     """After a parse action, the user can choose to save the dicom to file."""
     filename = filename or self.dicom_file
     ds = save_dicom(
         dicom=self.dicom,
         dicom_file=os.path.basename(filename),
         output_folder=os.path.dirname(filename),
         overwrite=overwrite,
     )
     return ds
Пример #3
0
def replace_identifiers(
    dicom_files,
    ids=None,
    deid=None,
    save=False,
    overwrite=False,
    output_folder=None,
    force=True,
    config=None,
    strip_sequences=False,
    remove_private=False,
):

    """replace identifiers using pydicom, can be slow when writing
    and saving new files. If you want to replace sequences, they need
    to be extracted with get_identifiers and expand_sequences to True.
    """

    if not isinstance(dicom_files, list):
        dicom_files = [dicom_files]

    # Warn the user that we use the default deid recipe
    if not deid:
        bot.warning("No deid specification provided, will use defaults.")

    # ids (a lookup) is not required
    ids = ids or {}

    # Parse through dicom files, update headers, and save
    updated_files = []
    for dicom_file in dicom_files:
        parser = DicomParser(dicom_file, force=force, config=config, recipe=deid)

        # If a custom lookup was provided, update the parser
        if parser.dicom_file in ids:
            parser.lookup.update(ids[parser.dicom_file])

        parser.parse(strip_sequences=strip_sequences, remove_private=remove_private)

        # Save to file, otherwise return updated objects
        if save is True:
            ds = save_dicom(
                dicom=parser.dicom,
                dicom_file=parser.dicom_file,
                output_folder=output_folder,
                overwrite=overwrite,
            )
            updated_files.append(ds)
        else:
            updated_files.append(parser.dicom)

    return updated_files
Пример #4
0
def replace_identifiers(
    dicom_files,
    ids=None,
    deid=None,
    save=True,
    overwrite=False,
    output_folder=None,
    force=True,
    config=None,
    strip_sequences=True,
    remove_private=True,
):
    """replace identifiers using pydicom, can be slow when writing
       and saving new files. If you want to replace sequences, they need
       to be extracted with get_identifiers and expand_sequences to True.
    """
    dicom_files, recipe, config = _prepare_replace_config(dicom_files,
                                                          deid=deid,
                                                          config=config)

    # ids (a lookup) is not required
    ids = ids or {}

    # Parse through dicom files, update headers, and save
    updated_files = []
    for _, dicom_file in enumerate(dicom_files):

        if isinstance(dicom_file, Dataset):
            dicom = dicom_file
            dicom_file = dicom.filename
        else:
            dicom = read_file(dicom_file, force=force)
        dicom_name = os.path.basename(dicom_file)

        # Remove sequences first, maintained in DataStore
        if strip_sequences is True:
            dicom = remove_sequences(dicom)

        # Remove private tags at the onset, if requested
        if remove_private:
            try:
                dicom.remove_private_tags()
            except:
                bot.error(
                    """Private tags for %s could not be completely removed, usually
                             this is due to invalid data type. Removing others."""
                    % dicom_name)
                private_tags = get_private(dicom)
                for ptag in private_tags:
                    del dicom[ptag.tag]
                continue

        # Include private tags (if not removed) plus dicom.dir
        fields = dicom_dir(dicom)

        if recipe.deid is not None:

            if dicom_file not in ids:
                ids[dicom_file] = {}

            # Prepare additional lists of values and fields (updates item)
            if recipe.has_values_lists():
                for group, actions in recipe.get_values_lists().items():
                    ids[dicom_file][group] = extract_values_list(
                        dicom=dicom, actions=actions)

            if recipe.has_fields_lists():
                for group, actions in recipe.get_fields_lists().items():
                    ids[dicom_file][group] = extract_fields_list(
                        dicom=dicom, actions=actions)

            for action in recipe.get_actions():
                dicom = perform_action(dicom=dicom,
                                       item=ids[dicom_file],
                                       action=action)

        # Next perform actions in default config, only if not done
        for action in config["put"]["actions"]:
            if action["field"] in fields:
                dicom = perform_action(dicom=dicom, action=action)

        # Assemble a new dataset, again accounting for private tags
        ds = Dataset()
        for field in dicom_dir(dicom):

            try:
                # Most fields are strings
                if isinstance(field, str):
                    ds.add(dicom.data_element(field))

                # Remainder are tags
                else:
                    ds.add(dicom.get(field))
            except:
                pass

        # Copy original data attributes
        attributes = [
            "is_little_endian",
            "is_implicit_VR",
            "is_decompressed",
            "read_encoding",
            "read_implicit_vr",
            "read_little_endian",
            "_parent_encoding",
        ]

        # We aren't including preamble, we will reset to be empty 128 bytes
        ds.preamble = b"\0" * 128

        for attribute in attributes:
            if hasattr(dicom, attribute):
                ds.__setattr__(attribute, dicom.__getattribute__(attribute))

        # Original meta data                     # or default empty dataset
        file_metas = getattr(dicom, "file_meta", Dataset())

        # Media Storage SOP Instance UID can be identifying
        if hasattr(file_metas, "MediaStorageSOPInstanceUID"):
            file_metas.MediaStorageSOPInstanceUID = ""

        # Save meta data
        ds.file_meta = file_metas

        # Save to file?
        if save is True:
            ds = save_dicom(
                dicom=ds,
                dicom_file=dicom_file,
                output_folder=output_folder,
                overwrite=overwrite,
            )
        updated_files.append(ds)

    return updated_files