import re from django.conf import settings from django.core.management.base import BaseCommand, CommandError import pydicom import pydicom.errors from django_rich.management import RichCommand from rich.progress import track import six import os class Command(RichCommand): help = 'Checks dicom files for anonymisation' #def add_arguments(self, parser): # parser.add_argument('poll_ids', nargs='+', type=int) def handle(self, *args, **options): self.console.print("[bold blue]Finding files:[/bold blue]") files = get_all_media() self.console.print(f"[bold blue]Files to check: {len(files)}[/bold blue]") for file in track(files, description="Checking file..."): try: ds = pydicom.dcmread(file, force=False) except pydicom.errors.InvalidDicomError: continue site_codes = ("ref", "rk9", "ra9", "rh8", "rbz", "rba") for code in site_codes: # TODO rewrite try: if code in ds.PatientID.lower(): self.stdout.write(self.style.WARNING(f"Identifiable dicom [{ds.PatientID.lower()}] {file}")) except AttributeError: self.stdout.write(self.style.WARNING(f"Error parsing {file}")) pass try: if code in ds.AccessionNumber.lower(): self.stdout.write(self.style.WARNING(f"Error parsing [{ds.AccessionNumber.lower()}] {file}")) except AttributeError: pass if code in ds.to_json(): self.stdout.write(self.style.WARNING(f"Error parsing [{code} in json dataset] {file}")) def get_all_media(exclude=None): """ Get all media from MEDIA_ROOT """ if not exclude: exclude = [] media = set() for root, dirs, files in os.walk(six.text_type(settings.MEDIA_ROOT)): for name in files: path = os.path.abspath(os.path.join(root, name)) relpath = os.path.relpath(path, settings.MEDIA_ROOT) for e in exclude: if re.match(r'^%s$' % re.escape(e).replace('\\*', '.*'), relpath): break else: media.add(path) return media