Esempio n. 1
0
    def update_tree(self, image_slice, id, name):
        """
        Update the DICOM Tree view.
        :param image_slice: Boolean indicating if it is an image slice or not
        :param id: ID for the selected file
        :param name: Name of the selected dataset if not an image file
        :return:
        """
        self.model_tree.clear()

        if image_slice:
            filename = self.patient_dict_container.filepaths[id]
            dicom_tree_slice = DicomTree(filename)
            dict_tree = dicom_tree_slice.dict

        elif name == "rtdose":
            dict_tree = self.patient_dict_container.get("dict_dicom_tree_rtdose")

        elif name == "rtss":
            dict_tree = self.patient_dict_container.get("dict_dicom_tree_rtss")

        elif name == "rtplan":
            dict_tree = self.patient_dict_container.get("dict_dicom_tree_rtplan")

        else:
            dict_tree = None
            print("Error filename in update_tree function")

        parent_item = self.model_tree.invisibleRootItem()
        self.recurse_build_model(dict_tree, parent_item)
        self.init_headers_tree()
        self.tree_view.setModel(self.model_tree)
        self.init_parameters_tree()
        self.dicom_tree_layout.addWidget(self.tree_view)
Esempio n. 2
0
def test_file_components(test_obj):
    """
    Unit Test for DICOM Tree
    :test_tree: Window to be tested - DICOM Tree window
    :return:
    """

    # Test initial values are correct and initial tree is clear
    file_count = len(test_obj.dicom_tree.special_files) + len(
        test_obj.main_window.dicom_tree.patient_dict_container.get(
            "pixmaps_axial"))
    assert test_obj.dicom_tree.model_tree.rowCount() == 0
    assert test_obj.dicom_tree.selector.currentIndex() == 0
    current_text = test_obj.dicom_tree.selector.currentText()
    assert current_text == "Select a DICOM dataset..."

    # Check tree loaded all files from patient_dict_container
    assert test_obj.dicom_tree.selector.count() - 1 == file_count

    # Loop through each file
    for i in range(1, file_count):

        # Set program to next file
        test_obj.dicom_tree.selector.setCurrentIndex(i)
        test_obj.dicom_tree.item_selected(i)
        current_text = test_obj.dicom_tree.selector.currentText()

        # Make New Tree to compare
        if i > len(test_obj.dicom_tree.special_files):
            index = i - len(test_obj.dicom_tree.special_files) - 1
            name = test_obj.dicom_tree.patient_dict_container.filepaths[index]
            dicom_tree_slice = DicomTree(name)
            dict_tree = dicom_tree_slice.dict
            text = "Image Slice " + str(index + 1)
            assert current_text == text

        elif test_obj.dicom_tree.special_files[i - 1] == "rtss":
            dict_tree = test_obj.dicom_tree.patient_dict_container.get(
                "dict_dicom_tree_rtss")
            assert current_text == "RT Structure Set"

        elif test_obj.dicom_tree.special_files[i - 1] == "rtdose":
            dict_tree = test_obj.dicom_tree.patient_dict_container.get(
                "dict_dicom_tree_rtdose")
            assert current_text == "RT Dose"

        elif test_obj.dicom_tree.special_files[i - 1] == "rtplan":
            dict_tree = test_obj.dicom_tree.patient_dict_container.get(
                "dict_dicom_tree_rtplan")
            assert current_text == "RT Plan"

        else:
            dict_tree = None
            print("Error filename in update_tree function")

        # Loop Through Each Row
        parent = test_obj.dicom_tree.model_tree.invisibleRootItem()
        total_count = test_obj.dicom_tree.model_tree.rowCount()
        assert recursive_search(dict_tree, parent) == total_count
    def get_patients_info(self):
        """
        Retrieve the patient's study description of the fixed image
        and for the moving image (if it exists).
        """
        patient_dict_container = PatientDictContainer()
        if not patient_dict_container.is_empty():
            filename = patient_dict_container.filepaths[0]
            dicom_tree_slice = DicomTree(filename)
            dict_tree = dicom_tree_slice.dict
            try:
                self.fixed_image = dict_tree["Series Instance UID"][0]
            except:
                self.fixed_image = ""
                self.warning_label.setText(
                    'Couldn\'t find the series instance '
                    'UID for the Fixed Image.')

        moving_dict_container = MovingDictContainer()
        if not moving_dict_container.is_empty():
            filename = moving_dict_container.filepaths[0]
            dicom_tree_slice = DicomTree(filename)
            dict_tree = dicom_tree_slice.dict
            try:
                self.moving_image = dict_tree["Series Instance UID"][0]
            except:
                self.moving_image = ""
                self.warning_label.setText(
                    'Couldn\'t find the series instance '
                    'UID for the Moving Image.')

        if moving_dict_container.is_empty() and self.moving_image != "":
            self.moving_image = ""

        self.fixed_image_placeholder.setText(str(self.fixed_image))
        self.moving_image_placeholder.setText(str(self.moving_image))
Esempio n. 4
0
    def create_new_rtstruct(cls, progress_callback):
        """
        Generates a new RTSS and edits the patient dict container. Used
        for batch processing.
        """
        # Get common directory
        patient_dict_container = PatientDictContainer()
        file_path = patient_dict_container.filepaths.values()
        file_path = Path(os.path.commonpath(file_path))

        # Get new RT Struct file path
        file_path = str(file_path.joinpath("rtss.dcm"))

        # Create RT Struct file
        progress_callback.emit(("Generating RT Structure Set", 60))
        ct_uid_list = ImageLoading.get_image_uid_list(
            patient_dict_container.dataset)
        ds = ROI.create_initial_rtss_from_ct(patient_dict_container.dataset[0],
                                             file_path, ct_uid_list)
        ds.save_as(file_path)

        # Add RT Struct file path to patient dict container
        patient_dict_container.filepaths['rtss'] = file_path
        filepaths = patient_dict_container.filepaths

        # Add RT Struct dataset to patient dict container
        patient_dict_container.dataset['rtss'] = ds
        dataset = patient_dict_container.dataset

        # Set some patient dict container attributes
        patient_dict_container.set("file_rtss", filepaths['rtss'])
        patient_dict_container.set("dataset_rtss", dataset['rtss'])

        dicom_tree_rtss = DicomTree(filepaths['rtss'])
        patient_dict_container.set("dict_dicom_tree_rtss",
                                   dicom_tree_rtss.dict)

        dict_pixluts = ImageLoading.get_pixluts(patient_dict_container.dataset)
        patient_dict_container.set("pixluts", dict_pixluts)

        rois = ImageLoading.get_roi_info(ds)
        patient_dict_container.set("rois", rois)

        patient_dict_container.set("selected_rois", [])
        patient_dict_container.set("dict_polygons_axial", {})

        patient_dict_container.set("rtss_modified", True)
Esempio n. 5
0
    def load_temp_rtss(self, path, progress_callback, interrupt_flag):
        """
        Generate a temporary rtss and load its data into
        MovingDictContainer
        :param path: str. The common root folder of all DICOM files.
        :param progress_callback: A signal that receives the current
        progress of the loading.
        :param interrupt_flag: A threading.Event() object that tells the
        function to stop loading.
        """
        progress_callback.emit(("Generating temporary rtss...", 20))
        moving_dict_container = MovingDictContainer()
        rtss_path = Path(path).joinpath('rtss.dcm')
        uid_list = ImageLoading.get_image_uid_list(
            moving_dict_container.dataset)
        rtss = create_initial_rtss_from_ct(moving_dict_container.dataset[0],
                                           rtss_path, uid_list)

        if interrupt_flag.is_set():  # Stop loading.
            print("stopped")
            return False

        progress_callback.emit(("Loading temporary rtss...", 50))
        # Set ROIs
        rois = ImageLoading.get_roi_info(rtss)
        moving_dict_container.set("rois", rois)

        # Set pixluts
        dict_pixluts = ImageLoading.get_pixluts(moving_dict_container.dataset)
        moving_dict_container.set("pixluts", dict_pixluts)

        # Add RT Struct file path and dataset to moving dict container
        moving_dict_container.filepaths['rtss'] = rtss_path
        moving_dict_container.dataset['rtss'] = rtss

        # Set some moving dict container attributes
        moving_dict_container.set("file_rtss", rtss_path)
        moving_dict_container.set("dataset_rtss", rtss)
        ordered_dict = DicomTree(None).dataset_to_dict(rtss)
        moving_dict_container.set("dict_dicom_tree_rtss", ordered_dict)
        moving_dict_container.set("selected_rois", [])
Esempio n. 6
0
    def fixed_container_structure_modified(self, changes):
        """
        Executes when a structure of fixed patient container is modified
        Displays indicator that structure has changed.
        Changes is a tuple of (new_dataset,
        description_of_changes)
        description_of_changes follows the format
        {"type_of_change": value_of_change}.
        Examples:
        {"rename": ["TOOTH", "TEETH"]} represents that the TOOTH structure has
            been renamed to TEETH.
        {"delete": ["TEETH", "MAXILLA"]} represents that the TEETH and MAXILLA
            structures have been deleted.
        {"draw": "AORTA"} represents that a new structure AORTA has been drawn.
        Note: Use {"draw": None} after multiple ROIs are generated
        (E.g., from ISO2ROI functionality), and use {"transfer":None} for
         ROI Transfer instead of calling this function
        multiple times. This will trigger auto save.
        """

        new_dataset = changes[0]
        change_description = changes[1]

        # Only show the modified indicator if description_of_changes is
        # not {"draw": None}, as this description means that the RTSS
        # is autosaved, and therefore there is no need to tell the user
        # that the RTSS has been modified
        if not("draw" in change_description
               and change_description["draw"] is None) and \
                not ("transfer" in change_description):
            self.show_modified_indicator()

        # If this is the first change made to the RTSS file, update the
        # dataset with the new one so that OnkoDICOM starts working off this
        # dataset rather than the original RTSS file.
        self.patient_dict_container.set("rtss_modified", True)
        self.patient_dict_container.set("dataset_rtss", new_dataset)

        # Refresh ROIs in main page
        self.patient_dict_container.set("rois",
                                        ImageLoading.get_roi_info(new_dataset))
        self.rois = self.patient_dict_container.get("rois")
        contour_data = ImageLoading.get_raw_contour_data(new_dataset)
        self.patient_dict_container.set("raw_contour", contour_data[0])
        self.patient_dict_container.set("num_points", contour_data[1])
        pixluts = ImageLoading.get_pixluts(self.patient_dict_container.dataset)
        self.patient_dict_container.set("pixluts", pixluts)
        self.patient_dict_container.set(
            "list_roi_numbers",
            ordered_list_rois(self.patient_dict_container.get("rois")))
        self.patient_dict_container.set("selected_rois", [])
        self.patient_dict_container.set("dict_polygons_axial", {})
        self.patient_dict_container.set("dict_polygons_sagittal", {})
        self.patient_dict_container.set("dict_polygons_coronal", {})

        if "draw" in change_description or "transfer" in change_description:
            dicom_tree_rtss = DicomTree(None)
            dicom_tree_rtss.dataset = new_dataset
            dicom_tree_rtss.dict = dicom_tree_rtss.dataset_to_dict(
                dicom_tree_rtss.dataset)
            self.patient_dict_container.set("dict_dicom_tree_rtss",
                                            dicom_tree_rtss.dict)
            self.color_dict = self.init_color_roi(self.patient_dict_container)
            self.patient_dict_container.set("roi_color_dict", self.color_dict)
            if self.patient_dict_container.has_attribute("raw_dvh"):
                # DVH will be outdated once changes to it are made, and
                # recalculation will be required.
                self.patient_dict_container.set("dvh_outdated", True)

        if self.patient_dict_container.has_attribute("raw_dvh"):
            # Rename structures in DVH list
            if "rename" in change_description:
                new_raw_dvh = self.patient_dict_container.get("raw_dvh")
                for key, dvh in new_raw_dvh.items():
                    if dvh.name == change_description["rename"][0]:
                        dvh.name = change_description["rename"][1]
                        break

                self.patient_dict_container.set("raw_dvh", new_raw_dvh)
                dvh2rtdose(new_raw_dvh)

            # Remove structures from DVH list - the only visible effect of
            # this section is the exported DVH csv
            if "delete" in change_description:
                list_of_deleted = []
                new_raw_dvh = self.patient_dict_container.get("raw_dvh")
                for key, dvh in new_raw_dvh.items():
                    if dvh.name in change_description["delete"]:
                        list_of_deleted.append(key)
                for key in list_of_deleted:
                    new_raw_dvh.pop(key)
                self.patient_dict_container.set("raw_dvh", new_raw_dvh)
                dvh2rtdose(new_raw_dvh)

        # Refresh ROIs in DVH tab and DICOM View
        self.request_update_structures.emit()

        # Refresh structure tab
        self.update_content()

        if "draw" in change_description and change_description["draw"] is None:
            self.save_new_rtss_to_fixed_image_set(auto=True)
        elif "transfer" in change_description \
                and change_description["transfer"] is None:
            self.save_new_rtss_to_fixed_image_set(auto=True)
Esempio n. 7
0
def create_moving_model():
    """
    This function initializes all the attributes in the
    MovingDictContainer model required for the operation of the main
    window. This should be called before the
    main window's components are constructed, but after the initial
    values of the MovingDictContainer instance are set (i.e. dataset
    and filepaths).
    """
    ##############################
    #  LOAD PATIENT INFORMATION  #
    ##############################
    moving_dict_container = MovingDictContainer()

    dataset = moving_dict_container.dataset
    filepaths = moving_dict_container.filepaths
    moving_dict_container.set("rtss_modified_moving", False)

    # Determine if dataset is CT for aditional rescaling
    is_ct = False
    if dataset[0].Modality == "CT":
        is_ct = True

    if 'WindowWidth' in dataset[0]:
        if isinstance(dataset[0].WindowWidth, pydicom.valuerep.DSfloat):
            window = int(dataset[0].WindowWidth)
        elif isinstance(dataset[0].WindowWidth, pydicom.multival.MultiValue):
            window = int(dataset[0].WindowWidth[1])
    else:
        window = int(400)

    if 'WindowCenter' in dataset[0]:
        if isinstance(dataset[0].WindowCenter, pydicom.valuerep.DSfloat):
            level = int(dataset[0].WindowCenter) - window / 2
        elif isinstance(dataset[0].WindowCenter, pydicom.multival.MultiValue):
            level = int(dataset[0].WindowCenter[1]) - window / 2
        if is_ct:
            level += CT_RESCALE_INTERCEPT
    else:
        level = int(800)

    moving_dict_container.set("window", window)
    moving_dict_container.set("level", level)

    # Check to see if the imageWindowing.csv file exists
    if os.path.exists(data_path('imageWindowing.csv')):
        # If it exists, read data from file into the self.dict_windowing
        # variable
        dict_windowing = {}
        with open(data_path('imageWindowing.csv'), "r") \
                as fileInput:
            next(fileInput)
            dict_windowing["Normal"] = [window, level]
            for row in fileInput:
                # Format: Organ - Scan - Window - Level
                items = [item for item in row.split(',')]
                dict_windowing[items[0]] = [int(items[2]), int(items[3])]
    else:
        # If csv does not exist, initialize dictionary with default
        # values
        dict_windowing = {
            "Normal": [window, level],
            "Lung": [1600, -300],
            "Bone": [1400, 700],
            "Brain": [160, 950],
            "Soft Tissue": [400, 800],
            "Head and Neck": [275, 900]
        }

    moving_dict_container.set("dict_windowing_moving", dict_windowing)

    if not moving_dict_container.has_attribute("scaled"):
        moving_dict_container.set("scaled", True)
        pixel_values = convert_raw_data(dataset, False, is_ct)
    else:
        pixel_values = convert_raw_data(dataset, True)

    # Calculate the ratio between x axis and y axis of 3 views
    pixmap_aspect = {}
    pixel_spacing = dataset[0].PixelSpacing
    slice_thickness = dataset[0].SliceThickness
    pixmap_aspect["axial"] = pixel_spacing[1] / pixel_spacing[0]
    pixmap_aspect["sagittal"] = pixel_spacing[1] / slice_thickness
    pixmap_aspect["coronal"] = slice_thickness / pixel_spacing[0]
    pixmaps_axial, pixmaps_coronal, pixmaps_sagittal = \
        get_pixmaps(pixel_values, window, level, pixmap_aspect)

    moving_dict_container.set("pixmaps_axial", pixmaps_axial)
    moving_dict_container.set("pixmaps_coronal", pixmaps_coronal)
    moving_dict_container.set("pixmaps_sagittal", pixmaps_sagittal)
    moving_dict_container.set("pixel_values", pixel_values)
    moving_dict_container.set("pixmap_aspect", pixmap_aspect)

    basic_info = get_basic_info(dataset[0])
    moving_dict_container.set("basic_info", basic_info)

    moving_dict_container.set("dict_uid", dict_instance_uid(dataset))

    # Set RTSS attributes
    if moving_dict_container.has_modality("rtss"):
        moving_dict_container.set("file_rtss", filepaths['rtss'])
        moving_dict_container.set("dataset_rtss", dataset['rtss'])

        dicom_tree_rtss = DicomTree(filepaths['rtss'])
        moving_dict_container.set("dict_dicom_tree_rtss", dicom_tree_rtss.dict)

        moving_dict_container.set(
            "list_roi_numbers",
            ordered_list_rois(moving_dict_container.get("rois")))
        moving_dict_container.set("selected_rois", [])

        moving_dict_container.set("dict_polygons", {})

    # Set RTDOSE attributes
    if moving_dict_container.has_modality("rtdose"):
        dicom_tree_rtdose = DicomTree(filepaths['rtdose'])
        moving_dict_container.set("dict_dicom_tree_rtdose",
                                  dicom_tree_rtdose.dict)

        moving_dict_container.set("dose_pixluts", get_dose_pixluts(dataset))

        moving_dict_container.set("selected_doses", [])
        # This will be overwritten if an RTPLAN is present.
        moving_dict_container.set("rx_dose_in_cgray", 1)

    # Set RTPLAN attributes
    if moving_dict_container.has_modality("rtplan"):
        rx_dose_in_cgray = calculate_rx_dose_in_cgray(dataset["rtplan"])
        moving_dict_container.set("rx_dose_in_cgray", rx_dose_in_cgray)

        dicom_tree_rtplan = DicomTree(filepaths['rtplan'])
        moving_dict_container.set("dict_dicom_tree_rtplan",
                                  dicom_tree_rtplan.dict)
Esempio n. 8
0
def create_initial_model():
    """
    This function initializes all the attributes in the PatientDictContainer model required for the operation of the
    main window. This should be called before the main window's components are constructed, but after the initial
    values of the PatientDictContainer instance are set (i.e. dataset and filepaths).
    """
    ##############################
    #  LOAD PATIENT INFORMATION  #
    ##############################
    patient_dict_container = PatientDictContainer()

    dataset = patient_dict_container.dataset
    filepaths = patient_dict_container.filepaths
    patient_dict_container.set("rtss_modified", False)

    if ('WindowWidth' in dataset[0]):
        if isinstance(dataset[0].WindowWidth, pydicom.valuerep.DSfloat):
            window = int(dataset[0].WindowWidth)
        elif isinstance(dataset[0].WindowWidth, pydicom.multival.MultiValue):
            window = int(dataset[0].WindowWidth[1])
    else:
        window = int(400)

    if ('WindowCenter' in dataset[0]):
        if isinstance(dataset[0].WindowCenter, pydicom.valuerep.DSfloat):
            level = int(dataset[0].WindowCenter)
        elif isinstance(dataset[0].WindowCenter, pydicom.multival.MultiValue):
            level = int(dataset[0].WindowCenter[1])
    else:
        level = int(800)

    patient_dict_container.set("window", window)
    patient_dict_container.set("level", level)

    # Check to see if the imageWindowing.csv file exists
    if os.path.exists(resource_path('data/csv/imageWindowing.csv')):
        # If it exists, read data from file into the self.dict_windowing variable
        dict_windowing = {}
        with open(resource_path('data/csv/imageWindowing.csv'),
                  "r") as fileInput:
            next(fileInput)
            dict_windowing["Normal"] = [window, level]
            for row in fileInput:
                # Format: Organ - Scan - Window - Level
                items = [item for item in row.split(',')]
                dict_windowing[items[0]] = [int(items[2]), int(items[3])]
    else:
        # If csv does not exist, initialize dictionary with default values
        dict_windowing = {
            "Normal": [window, level],
            "Lung": [1600, -300],
            "Bone": [1400, 700],
            "Brain": [160, 950],
            "Soft Tissue": [400, 800],
            "Head and Neck": [275, 900]
        }

    patient_dict_container.set("dict_windowing", dict_windowing)

    pixel_values = convert_raw_data(dataset)
    pixmaps = get_pixmaps(pixel_values, window, level)
    patient_dict_container.set("pixmaps", pixmaps)
    patient_dict_container.set("pixel_values", pixel_values)

    basic_info = get_basic_info(dataset[0])
    patient_dict_container.set("basic_info", basic_info)

    patient_dict_container.set("dict_uid", dict_instanceUID(dataset))

    # Set RTSS attributes
    if patient_dict_container.has_modality("rtss"):
        patient_dict_container.set("file_rtss", filepaths['rtss'])
        patient_dict_container.set("dataset_rtss", dataset['rtss'])

        dicom_tree_rtss = DicomTree(filepaths['rtss'])
        patient_dict_container.set("dict_dicom_tree_rtss",
                                   dicom_tree_rtss.dict)

        patient_dict_container.set(
            "list_roi_numbers",
            ordered_list_rois(patient_dict_container.get("rois")))
        patient_dict_container.set("selected_rois", [])

        patient_dict_container.set("dict_polygons", {})

    # Set RTDOSE attributes
    if patient_dict_container.has_modality("rtdose"):
        dicom_tree_rtdose = DicomTree(filepaths['rtdose'])
        patient_dict_container.set("dict_dicom_tree_rtdose",
                                   dicom_tree_rtdose.dict)

        patient_dict_container.set("dose_pixluts", get_dose_pixluts(dataset))

        patient_dict_container.set("selected_doses", [])
        patient_dict_container.set(
            "rx_dose_in_cgray",
            1)  # This will be overwritten if an RTPLAN is present.

    # Set RTPLAN attributes
    if patient_dict_container.has_modality("rtplan"):
        # the TargetPrescriptionDose is type 3 (optional), so it may not be there
        # However, it is preferable to the sum of the beam doses
        # DoseReferenceStructureType is type 1 (value is mandatory),
        # but it can have a value of ORGAN_AT_RISK rather than TARGET
        # in which case there will *not* be a TargetPrescriptionDose
        # and even if it is TARGET, that's no guarantee that TargetPrescriptionDose
        # will be encoded and have a value
        rx_dose_in_cgray = calculate_rx_dose_in_cgray(dataset["rtplan"])
        patient_dict_container.set("rx_dose_in_cgray", rx_dose_in_cgray)

        dicom_tree_rtplan = DicomTree(filepaths['rtplan'])
        patient_dict_container.set("dict_dicom_tree_rtplan",
                                   dicom_tree_rtplan.dict)
Esempio n. 9
0
    def structure_modified(self, changes):
        """
        Executes when a structure is renamed/deleted. Displays indicator that structure has changed.
        changes is a tuple of (new_dataset, description_of_changes)
        description_of_changes follows the format {"type_of_change": value_of_change}.
        Examples: {"rename": ["TOOTH", "TEETH"]} represents that the TOOTH structure has been renamed to TEETH.
        {"delete": ["TEETH", "MAXILLA"]} represents that the TEETH and MAXILLA structures have been deleted.
        {"draw": "AORTA"} represents that a new structure AORTA has been drawn.
        """

        new_dataset = changes[0]
        change_description = changes[1]

        # If this is the first time the RTSS has been modified, create a modified indicator giving the user the option
        # to save their new file.
        if self.patient_dict_container.get("rtss_modified") is False:
            self.show_modified_indicator()

        # If this is the first change made to the RTSS file, update the dataset with the new one so that OnkoDICOM
        # starts working off this dataset rather than the original RTSS file.
        self.patient_dict_container.set("rtss_modified", True)
        self.patient_dict_container.set("dataset_rtss", new_dataset)

        # Refresh ROIs in main page
        self.patient_dict_container.set("rois",
                                        ImageLoading.get_roi_info(new_dataset))
        self.rois = self.patient_dict_container.get("rois")
        contour_data = ImageLoading.get_raw_contour_data(new_dataset)
        self.patient_dict_container.set("raw_contour", contour_data[0])
        self.patient_dict_container.set("num_points", contour_data[1])
        pixluts = ImageLoading.get_pixluts(self.patient_dict_container.dataset)
        self.patient_dict_container.set("pixluts", pixluts)
        self.patient_dict_container.set(
            "list_roi_numbers",
            ordered_list_rois(self.patient_dict_container.get("rois")))
        self.patient_dict_container.set("selected_rois", [])
        self.patient_dict_container.set("dict_polygons", {})

        if "draw" in change_description:
            dicom_tree_rtss = DicomTree(None)
            dicom_tree_rtss.dataset = new_dataset
            dicom_tree_rtss.dict = dicom_tree_rtss.dataset_to_dict(
                dicom_tree_rtss.dataset)
            self.patient_dict_container.set("dict_dicom_tree_rtss",
                                            dicom_tree_rtss.dict)
            self.color_dict = self.init_color_roi()
            self.patient_dict_container.set("roi_color_dict", self.color_dict)
            if self.patient_dict_container.has_attribute("raw_dvh"):
                # DVH will be outdated once changes to it are made, and recalculation will be required.
                self.patient_dict_container.set("dvh_outdated", True)

        if self.patient_dict_container.has_modality("raw_dvh"):
            # Rename structures in DVH list
            if "rename" in changes[1]:
                new_raw_dvh = self.patient_dict_container.get("raw_dvh")
                for key, dvh in new_raw_dvh.items():
                    if dvh.name == change_description["rename"][0]:
                        dvh.name = change_description["rename"][1]
                        break

                self.patient_dict_container.set("raw_dvh", new_raw_dvh)

            # Remove structures from DVH list - the only visible effect of this section is the exported DVH csv
            if "delete" in changes[1]:
                list_of_deleted = []
                new_raw_dvh = self.patient_dict_container.get("raw_dvh")
                for key, dvh in new_raw_dvh.items():
                    if dvh.name in change_description["delete"]:
                        list_of_deleted.append(key)
                for key in list_of_deleted:
                    new_raw_dvh.pop(key)
                self.patient_dict_container.set("raw_dvh", new_raw_dvh)

        # Refresh ROIs in DVH tab and DICOM View
        self.request_update_structures.emit()

        # Refresh structure tab
        self.update_content()
Esempio n. 10
0
def create_initial_model_batch():
    """
    This function initializes all the attributes in the PatientDictContainer
    required for the operation of batch processing. It is a modified version
    of create_initial_model. This function only sets RTSS values in the
    PatientDictContainer if an RTSS exists. If one does not exist it will only
    be created if needed, whereas the original create_initial_model assumes
    that one is always created. This function also does not set SR attributes
    in the PatientDictContainer, as SRs are only needed for SR2CSV functions,
    which do not require the use of the PatientDictContainer.
    """
    ##############################
    #  LOAD PATIENT INFORMATION  #
    ##############################
    patient_dict_container = PatientDictContainer()

    dataset = patient_dict_container.dataset
    filepaths = patient_dict_container.filepaths
    patient_dict_container.set("rtss_modified", False)

    if 'WindowWidth' in dataset[0]:
        if isinstance(dataset[0].WindowWidth, pydicom.valuerep.DSfloat):
            window = int(dataset[0].WindowWidth)
        elif isinstance(dataset[0].WindowWidth, pydicom.multival.MultiValue):
            window = int(dataset[0].WindowWidth[1])
    else:
        window = int(400)

    if 'WindowCenter' in dataset[0]:
        if isinstance(dataset[0].WindowCenter, pydicom.valuerep.DSfloat):
            level = int(dataset[0].WindowCenter)
        elif isinstance(dataset[0].WindowCenter, pydicom.multival.MultiValue):
            level = int(dataset[0].WindowCenter[1])
    else:
        level = int(800)

    patient_dict_container.set("window", window)
    patient_dict_container.set("level", level)

    # Check to see if the imageWindowing.csv file exists
    if os.path.exists(data_path('imageWindowing.csv')):
        # If it exists, read data from file into the self.dict_windowing
        # variable
        dict_windowing = {}
        with open(data_path('imageWindowing.csv'), "r") \
                as fileInput:
            next(fileInput)
            dict_windowing["Normal"] = [window, level]
            for row in fileInput:
                # Format: Organ - Scan - Window - Level
                items = [item for item in row.split(',')]
                dict_windowing[items[0]] = [int(items[2]), int(items[3])]
    else:
        # If csv does not exist, initialize dictionary with default values
        dict_windowing = {
            "Normal": [window, level],
            "Lung": [1600, -300],
            "Bone": [1400, 700],
            "Brain": [160, 950],
            "Soft Tissue": [400, 800],
            "Head and Neck": [275, 900]
        }

    patient_dict_container.set("dict_windowing", dict_windowing)

    pixel_values = convert_raw_data(dataset)
    # Calculate the ratio between x axis and y axis of 3 views
    pixmap_aspect = {}
    pixel_spacing = dataset[0].PixelSpacing
    slice_thickness = dataset[0].SliceThickness
    pixmap_aspect["axial"] = pixel_spacing[1] / pixel_spacing[0]
    pixmap_aspect["sagittal"] = pixel_spacing[1] / slice_thickness
    pixmap_aspect["coronal"] = slice_thickness / pixel_spacing[0]
    pixmaps_axial, pixmaps_coronal, pixmaps_sagittal = \
        get_pixmaps(pixel_values, window, level, pixmap_aspect)

    patient_dict_container.set("pixmaps_axial", pixmaps_axial)
    patient_dict_container.set("pixmaps_coronal", pixmaps_coronal)
    patient_dict_container.set("pixmaps_sagittal", pixmaps_sagittal)
    patient_dict_container.set("pixel_values", pixel_values)
    patient_dict_container.set("pixmap_aspect", pixmap_aspect)

    basic_info = get_basic_info(dataset[0])
    patient_dict_container.set("basic_info", basic_info)

    patient_dict_container.set("dict_uid", dict_instance_uid(dataset))

    # Set RTSS attributes
    if patient_dict_container.has_modality("rtss"):
        patient_dict_container.set("file_rtss", filepaths['rtss'])
        patient_dict_container.set("dataset_rtss", dataset['rtss'])
        dict_raw_contour_data, dict_numpoints = \
            ImageLoading.get_raw_contour_data(dataset['rtss'])
        patient_dict_container.set("raw_contour", dict_raw_contour_data)
        dicom_tree_rtss = DicomTree(filepaths['rtss'])
        patient_dict_container.set("dict_dicom_tree_rtss",
                                   dicom_tree_rtss.dict)

        patient_dict_container.set(
            "list_roi_numbers",
            ordered_list_rois(patient_dict_container.get("rois")))
        patient_dict_container.set("selected_rois", [])

        patient_dict_container.set("dict_polygons_axial", {})
        patient_dict_container.set("dict_polygons_sagittal", {})
        patient_dict_container.set("dict_polygons_coronal", {})

    # Set RTDOSE attributes
    if patient_dict_container.has_modality("rtdose"):
        dicom_tree_rtdose = DicomTree(filepaths['rtdose'])
        patient_dict_container.set("dict_dicom_tree_rtdose",
                                   dicom_tree_rtdose.dict)

        patient_dict_container.set("dose_pixluts", get_dose_pixluts(dataset))

        patient_dict_container.set("selected_doses", [])

        # overwritten if RTPLAN is present.
        patient_dict_container.set("rx_dose_in_cgray", 1)

    # Set RTPLAN attributes
    if patient_dict_container.has_modality("rtplan"):
        # the TargetPrescriptionDose is type 3 (optional), so it may not be
        # there However, it is preferable to the sum of the beam doses
        # DoseReferenceStructureType is type 1 (value is mandatory), but it
        # can have a value of ORGAN_AT_RISK rather than TARGET in which case
        # there will *not* be a TargetPrescriptionDose and even if it is
        # TARGET, that's no guarantee that TargetPrescriptionDose will be
        # encoded and have a value
        rx_dose_in_cgray = calculate_rx_dose_in_cgray(dataset["rtplan"])
        patient_dict_container.set("rx_dose_in_cgray", rx_dose_in_cgray)

        dicom_tree_rtplan = DicomTree(filepaths['rtplan'])
        patient_dict_container.set("dict_dicom_tree_rtplan",
                                   dicom_tree_rtplan.dict)
Esempio n. 11
0
def create_initial_model():
    """
    This function initializes all the attributes in the PatientDictContainer
    model required for the operation of the main window. This should be
    called before the main window's components are constructed, but after
    the initial values of the PatientDictContainer instance are set (i.e.
    dataset and filepaths).
    """
    ##############################
    #  LOAD PATIENT INFORMATION  #
    ##############################
    patient_dict_container = PatientDictContainer()

    dataset = patient_dict_container.dataset
    filepaths = patient_dict_container.filepaths
    patient_dict_container.set("rtss_modified", False)

    # Determine if dataset is CT for aditional rescaling
    is_ct = False
    if dataset[0].Modality == "CT":
        is_ct = True

    if 'WindowWidth' in dataset[0]:
        if isinstance(dataset[0].WindowWidth, pydicom.valuerep.DSfloat):
            window = int(dataset[0].WindowWidth)
        elif isinstance(dataset[0].WindowWidth, pydicom.multival.MultiValue):
            window = int(dataset[0].WindowWidth[1])
    else:
        window = int(400)

    if 'WindowCenter' in dataset[0]:
        if isinstance(dataset[0].WindowCenter, pydicom.valuerep.DSfloat):
            level = int(dataset[0].WindowCenter) - window / 2
        elif isinstance(dataset[0].WindowCenter, pydicom.multival.MultiValue):
            level = int(dataset[0].WindowCenter[1]) - window / 2
        if is_ct:
            level += CT_RESCALE_INTERCEPT
    else:
        level = int(800)

    patient_dict_container.set("window", window)
    patient_dict_container.set("level", level)

    # Check to see if the imageWindowing.csv file exists
    if os.path.exists(data_path('imageWindowing.csv')):
        # If it exists, read data from file into the self.dict_windowing
        # variable
        dict_windowing = {}
        with open(data_path('imageWindowing.csv'), "r") \
                as fileInput:
            next(fileInput)
            dict_windowing["Normal"] = [window, level]
            for row in fileInput:
                # Format: Organ - Scan - Window - Level
                items = [item for item in row.split(',')]
                dict_windowing[items[0]] = [int(items[2]), int(items[3])]
    else:
        # If csv does not exist, initialize dictionary with default values
        dict_windowing = {
            "Normal": [window, level],
            "Lung": [1600, -300],
            "Bone": [1400, 700],
            "Brain": [160, 950],
            "Soft Tissue": [400, 800],
            "Head and Neck": [275, 900]
        }

    patient_dict_container.set("dict_windowing", dict_windowing)

    if not patient_dict_container.has_attribute("scaled"):
        patient_dict_container.set("scaled", True)
        pixel_values = convert_raw_data(dataset, False, is_ct)
    else:
        pixel_values = convert_raw_data(dataset, True)

    # Calculate the ratio between x axis and y axis of 3 views
    pixmap_aspect = {}
    pixel_spacing = dataset[0].PixelSpacing
    slice_thickness = dataset[0].SliceThickness
    pixmap_aspect["axial"] = pixel_spacing[1] / pixel_spacing[0]
    pixmap_aspect["sagittal"] = pixel_spacing[1] / slice_thickness
    pixmap_aspect["coronal"] = slice_thickness / pixel_spacing[0]
    pixmaps_axial, pixmaps_coronal, pixmaps_sagittal = \
        get_pixmaps(pixel_values, window, level, pixmap_aspect)

    patient_dict_container.set("pixmaps_axial", pixmaps_axial)
    patient_dict_container.set("pixmaps_coronal", pixmaps_coronal)
    patient_dict_container.set("pixmaps_sagittal", pixmaps_sagittal)
    patient_dict_container.set("pixel_values", pixel_values)
    patient_dict_container.set("pixmap_aspect", pixmap_aspect)

    basic_info = get_basic_info(dataset[0])
    patient_dict_container.set("basic_info", basic_info)

    patient_dict_container.set("dict_uid", dict_instance_uid(dataset))

    # Set RTSS attributes
    patient_dict_container.set("file_rtss", filepaths['rtss'])
    patient_dict_container.set("dataset_rtss", dataset['rtss'])
    dict_raw_contour_data, dict_numpoints = \
        ImageLoading.get_raw_contour_data(dataset['rtss'])
    patient_dict_container.set("raw_contour", dict_raw_contour_data)

    # dict_dicom_tree_rtss will be set in advance if the program
    # generates a new rtss through the execution of
    # ROI.create_initial_rtss_from_ct(...)
    if patient_dict_container.get("dict_dicom_tree_rtss") is None:
        dicom_tree_rtss = DicomTree(filepaths['rtss'])
        patient_dict_container.set("dict_dicom_tree_rtss",
                                   dicom_tree_rtss.dict)

    patient_dict_container.set(
        "list_roi_numbers",
        ordered_list_rois(patient_dict_container.get("rois")))
    patient_dict_container.set("selected_rois", [])

    patient_dict_container.set("dict_polygons_axial", {})
    patient_dict_container.set("dict_polygons_sagittal", {})
    patient_dict_container.set("dict_polygons_coronal", {})

    # Set RTDOSE attributes
    if patient_dict_container.has_modality("rtdose"):
        dicom_tree_rtdose = DicomTree(filepaths['rtdose'])
        patient_dict_container.set("dict_dicom_tree_rtdose",
                                   dicom_tree_rtdose.dict)

        patient_dict_container.set("dose_pixluts", get_dose_pixluts(dataset))

        patient_dict_container.set("selected_doses", [])

        # overwritten if RTPLAN is present.
        patient_dict_container.set("rx_dose_in_cgray", 1)

    # Set RTPLAN attributes
    if patient_dict_container.has_modality("rtplan"):
        # the TargetPrescriptionDose is type 3 (optional), so it may not be
        # there However, it is preferable to the sum of the beam doses
        # DoseReferenceStructureType is type 1 (value is mandatory), but it
        # can have a value of ORGAN_AT_RISK rather than TARGET in which case
        # there will *not* be a TargetPrescriptionDose and even if it is
        # TARGET, that's no guarantee that TargetPrescriptionDose will be
        # encoded and have a value
        rx_dose_in_cgray = calculate_rx_dose_in_cgray(dataset["rtplan"])
        patient_dict_container.set("rx_dose_in_cgray", rx_dose_in_cgray)

        dicom_tree_rtplan = DicomTree(filepaths['rtplan'])
        patient_dict_container.set("dict_dicom_tree_rtplan",
                                   dicom_tree_rtplan.dict)

    # Set SR attributes
    if patient_dict_container.has_modality("sr-cd"):
        dicom_tree_sr_clinical_data = DicomTree(filepaths['sr-cd'])
        patient_dict_container.set("dict_dicom_tree_sr_cd",
                                   dicom_tree_sr_clinical_data.dict)

    if patient_dict_container.has_modality("sr-rad"):
        dicom_tree_sr_pyrad = DicomTree(filepaths['sr-rad'])
        patient_dict_container.set("dict_dicom_tree_sr_pyrad",
                                   dicom_tree_sr_pyrad.dict)