def populate_new_fields(apps, schema_editor): Series = apps.get_model("django_dicom", "Series") for series in Series.objects.all(): header = DicomHeader(str(series.image_set.first().dcm)) series.pulse_sequence_name = header.get((0x0019, 0x109C)) series.sequence_name = header.get((0x0018, 0x0024)) series.save()
def get_or_create_from_dcm(self, path: Path, autoremove: bool = True) -> Tuple: """ Gets or creates an :class:`~django_dicom.models.image.Image` instance based on the contents of the provided *.dcm* path. Parameters ---------- path : :class:`pathlib.Path` Local *.dcm* file path autoremove : bool, optional Whether to remove the local copy of the *.dcm* file under MEDIA_ROOT if creation fails, by default True Returns ------- Tuple[Image, bool] image, created """ header = DicomHeader(path) uid = header.get("SOPInstanceUID") try: existing = self.get(uid=uid) except ObjectDoesNotExist: new_instance = self.create_from_dcm(path, autoremove=autoremove) return new_instance, True else: return existing, False
def instance(self) -> DicomHeader: """ Caches the created :class:`dicom_parser.header.Header` instance to prevent multiple reades. Returns ------- :class:`dicom_parser.header.Header` Header information """ if not isinstance(self._instance, DicomHeader): dcm_path = (self.image.dcm.name if os.getenv("USE_S3") else self.image.dcm.path) self._instance = DicomHeader(dcm_path) return self._instance
def scan_subject_to_session(apps, schema_editor): Subject = get_subject_model() Scan = apps.get_model("django_mri", "Scan") Session = apps.get_model("django_mri", "Session") for scan in Scan.objects.all(): subject = Subject.objects.filter( id_number=scan.dicom.patient.uid ).first() first_image = scan.dicom.image_set.first().dcm.path header = DicomHeader(first_image) date = header.get("StudyDate") or header.get("SeriesDate") try: time = header.get("StudyTime") except ValueError: time = datetime.time() else: if not time: time = datetime.time() session_time = datetime.datetime.combine(date, time) if not subject: session = Session.objects.create(time=session_time) scan.session_id = session.id else: session = subject.mri_session_set.filter( time=session_time ).first() if not session: session = Session.objects.create( subject_id=subject.id, time=session_time ) else: existing_scan_number = Scan.objects.filter( session_id=session.id, number=scan.number ) if existing_scan_number: session = Session.objects.create( subject_id=subject.id, time=session_time ) scan.session_id = session.id scan.save()
def import_path( self, path: Path, progressbar: bool = True, report: bool = True, persistent: bool = True, force_patient_uid: bool = False, ) -> QuerySet: """ Iterates the given directory tree and imports any *.dcm* files found within it. Parameters ---------- path : :class:`pathlib.Path` Base path for recursive *.dcm* import progressbar : bool, optional Whether to display a progressbar or not, by default True report : bool, optional Whether to print out a summary report when finished or not, by default True persistent : bool, optional Whether to continue and raise a warning or to raise an exception when failing to read a DICOM file's header force_patient_uid : bool, optional If patient UID for an existing image doesn't match the DB value, change the DB value to match that of the imported image Returns ------- :class:`~django.db.models.query.QuerySet` The created :class:`~django_dicom.models.image.Image` instances """ # Create an iterator iterator = Path(path).rglob("*.dcm") if progressbar: # Create a progressbar wrapped iterator using tqdm iterator = create_progressbar(iterator, unit="image") if report: counter = {"created": 0, "existing": 0} # Keep a list of all the created images' primary keys created_ids = [] # Keep a list of patient UID mismatches to log patient_uid_mismatch = [] for dcm_path in iterator: # Atomic image import # For more information see: # https://docs.djangoproject.com/en/3.0/topics/db/transactions/#controlling-transactions-explicitly with transaction.atomic(): try: image, created = self.get_or_create_from_dcm( dcm_path, autoremove=True) except InvalidDicomError as e: if persistent: IMPORT_LOGGER.warning(e) continue else: raise if report: counter_key = "created" if created else "existing" counter[counter_key] += 1 if created: created_ids.append(image.id) else: if image.patient.uid not in patient_uid_mismatch: # Validate patient UID for existing images header = DicomHeader(dcm_path) patient_uid = header.get("PatientID") if patient_uid != image.patient.uid: # Log patient UID mismatch image_uid = header.get("SOPInstanceUID") message = PATIENT_UID_MISMATCH.format( image_uid=image_uid, db_value=image.patient.uid, patient_uid=patient_uid, ) IMPORT_LOGGER.warning(message) patient_uid_mismatch.append(image.patient.uid) if report: self.report_import_path_results(path, counter) return self.filter(id__in=created_ids)