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()
예제 #2
0
    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
예제 #3
0
    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()
예제 #5
0
    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)