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
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
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
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