Example #1
0
    def __init__(self, ortho, *args, **kwargs):
        """
        This function initializes the control panel. It generates the widgets and adds them to the panel. It also sets
        the initial position of the panel to the left
        :param ortho: This is used to access the ortho ops in order to turn off the X and Y canvas as well as the cursor
        """
        ctrlpanel.ControlPanel.__init__(self, ortho, *args, **kwargs)

        # Add a sizer to the control panel
        # This sizer will contain the buttons
        sizer_h = wx.BoxSizer(wx.VERTICAL)

        # Add the logo to the control panel
        ADS_logo = self.get_logo()
        sizer_h.Add(ADS_logo, flag=wx.SHAPED, proportion=1)

        # Add the citation to the control panel
        citation_box = wx.TextCtrl(self,
                                   value=self.get_citation(),
                                   size=(100, 50),
                                   style=wx.TE_MULTILINE)
        sizer_h.Add(citation_box, flag=wx.SHAPED, proportion=1)

        # Add a hyperlink to the documentation
        hyper = hl.HyperLinkCtrl(
            self,
            -1,
            label="Need help? Read the documentation",
            URL="https://axondeepseg.readthedocs.io/en/latest/")
        sizer_h.Add(hyper, flag=wx.SHAPED, proportion=1)

        # Define the color of button labels
        button_label_color = (0, 0, 0)

        # Add the image loading button
        load_png_button = wx.Button(self, label="Load PNG or TIF file")
        load_png_button.SetForegroundColour(button_label_color)
        load_png_button.Bind(wx.EVT_BUTTON, self.on_load_png_button)
        load_png_button.SetToolTip(
            wx.ToolTip("Loads a .png or .tif file into FSLeyes"))
        sizer_h.Add(load_png_button, flag=wx.SHAPED, proportion=1)

        # Add the mask loading button
        load_mask_button = wx.Button(self, label="Load existing mask")
        load_mask_button.SetForegroundColour(button_label_color)
        load_mask_button.Bind(wx.EVT_BUTTON, self.on_load_mask_button)
        load_mask_button.SetToolTip(
            wx.ToolTip(
                "Loads an existing axonmyelin mask into FSLeyes. "
                "The selected image should contain both the axon and myelin masks. "
                "The regions on the image should have an intensity of 0 for the background, "
                "127 for the myelin and 255 for the axons. "))
        sizer_h.Add(load_mask_button, flag=wx.SHAPED, proportion=1)

        # Add the model choice combobox
        self.model_combobox = wx.ComboBox(
            self,
            choices=ads_utils.get_existing_models_list(),
            size=(100, 20),
            value="Select the modality",
        )
        self.model_combobox.SetForegroundColour(button_label_color)
        self.model_combobox.SetToolTip(
            wx.ToolTip("Select the modality used to acquire the image"))
        sizer_h.Add(self.model_combobox, flag=wx.SHAPED, proportion=1)

        # Add the button that applies the prediction model
        apply_model_button = wx.Button(self,
                                       label="Apply ADS prediction model")
        apply_model_button.SetForegroundColour(button_label_color)
        apply_model_button.Bind(wx.EVT_BUTTON, self.on_apply_model_button)
        apply_model_button.SetToolTip(
            wx.ToolTip("Applies the prediction model and displays the masks"))
        sizer_h.Add(apply_model_button, flag=wx.SHAPED, proportion=1)

        # The Watershed button's purpose isn't clear. It is unavailable for now.

        # # Add the button that runs the watershed algorithm
        # run_watershed_button = wx.Button(self, label="Run Watershed")
        # run_watershed_button.Bind(wx.EVT_BUTTON, self.on_run_watershed_button)
        # run_watershed_button.SetToolTip(
        #     wx.ToolTip(
        #         "Uses a watershed algorithm to find the different axon+myelin"
        #         "objects. This is used to see if where are connections"
        #         " between two axon+myelin objects."
        #     )
        # )
        # sizer_h.Add(run_watershed_button, flag=wx.SHAPED, proportion=1)

        # Add the fill axon tool
        fill_axons_button = wx.Button(self, label="Fill axons")
        fill_axons_button.SetForegroundColour(button_label_color)
        fill_axons_button.Bind(wx.EVT_BUTTON, self.on_fill_axons_button)
        fill_axons_button.SetToolTip(
            wx.ToolTip(
                "Automatically fills the axons inside myelin objects."
                " THE MYELIN OBJECTS NEED TO BE CLOSED AND SEPARATED FROM EACH "
                "OTHER (THEY MUST NOT TOUCH) FOR THIS TOOL TO WORK CORRECTLY.")
        )
        sizer_h.Add(fill_axons_button, flag=wx.SHAPED, proportion=1)

        # Add the save Segmentation button
        save_segmentation_button = wx.Button(self, label="Save segmentation")
        save_segmentation_button.SetForegroundColour(button_label_color)
        save_segmentation_button.Bind(wx.EVT_BUTTON,
                                      self.on_save_segmentation_button)
        save_segmentation_button.SetToolTip(
            wx.ToolTip(
                "Saves the axon and myelin masks in the selected folder"))
        sizer_h.Add(save_segmentation_button, flag=wx.SHAPED, proportion=1)

        # Add compute morphometrics button
        compute_morphometrics_button = wx.Button(self,
                                                 label="Compute morphometrics")
        compute_morphometrics_button.SetForegroundColour(button_label_color)
        compute_morphometrics_button.Bind(wx.EVT_BUTTON,
                                          self.on_compute_morphometrics_button)
        compute_morphometrics_button.SetToolTip(
            wx.ToolTip(
                "Calculates and saves the morphometrics to an excel and csv file. "
                "Shows the numbers of the axons at the coordinates specified in the morphometrics file."
            ))
        sizer_h.Add(compute_morphometrics_button, flag=wx.SHAPED, proportion=1)

        # Set the sizer of the control panel
        self.SetSizer(sizer_h)

        # Initialize the variables that are used to track the active image
        self.png_image_name = []
        self.image_dir_path = []
        self.most_recent_watershed_mask_name = None

        # Toggle off the X and Y canvas
        oopts = ortho.sceneOpts
        oopts.showXCanvas = False
        oopts.showYCanvas = False

        # Toggle off the cursor
        oopts.showCursor = False

        # Toggle off the radiological orientation
        self.displayCtx.radioOrientation = False

        # Invert the Y display
        self.frame.viewPanels[0].frame.viewPanels[0].getZCanvas(
        ).opts.invertY = True

        # Create a temporary directory that will hold the NIfTI files
        self.ads_temp_dir_var = tempfile.TemporaryDirectory(
        )  #This variable needs to stay loaded to keep the temporary
        # directory from being destroyed
        self.ads_temp_dir = Path(self.ads_temp_dir_var.name)

        # Check the version
        self.verrify_version()
Example #2
0
    def on_apply_model_button(self, event):
        """
        This function is called when the user presses on the ApplyModel button. It is used to apply the prediction model
        selected in the combobox. The segmentation masks are then loaded into FSLeyes
        """

        # Declare the default resolution of the model
        resolution = 0.1

        # Get the image name and directory
        image_overlay = self.get_visible_image_overlay()
        if self.get_visible_image_overlay() is None:
            return

        n_loaded_images = self.png_image_name.__len__()
        image_name = None
        image_directory = None
        for i in range(n_loaded_images):
            if image_overlay.name == (Path(self.png_image_name[i])).stem:
                image_name = self.png_image_name[i]
                image_directory = self.image_dir_path[i]

        if (image_name is None) or (image_directory is None):
            self.show_message(
                "Couldn't find the path to the loaded image. "
                "Please use the plugin's image loader to import the image you wish to segment. "
            )
            return

        image_path = image_directory / image_name
        image_name_no_extension = Path(image_name).stem

        # Get the selected model
        selected_model = self.model_combobox.GetStringSelection()

        # Get the path of the selected model
        if any(selected_model in models
               for models in ads_utils.get_existing_models_list()):
            dir_path = Path(AxonDeepSeg.__file__).parents[0]
            model_path = dir_path / "models" / selected_model
        else:
            self.show_message("Please select a model")
            return

        # If the TEM model is selected, modify the resolution
        if "TEM" in selected_model.upper():
            resolution = 0.01

        # Check if the pixel size txt file exist in the imageDirPath
        pixel_size_exists = (image_directory /
                             "pixel_size_in_micrometer.txt").exists()

        # if it doesn't exist, ask the user to input the pixel size
        if pixel_size_exists is False:
            with wx.TextEntryDialog(self,
                                    "Enter the pixel size in micrometer",
                                    value="0.07") as text_entry:
                if text_entry.ShowModal() == wx.ID_CANCEL:
                    return

                pixel_size_str = text_entry.GetValue()
            pixel_size_float = float(pixel_size_str)

        else:  # read the pixel size
            resolution_file = open(
                (image_directory / "pixel_size_in_micrometer.txt").__str__(),
                'r')
            pixel_size_float = float(resolution_file.read())

        # Load model configs and apply prediction
        model_configfile = model_path / "config_network.json"
        with open(model_configfile.__str__(), "r") as fd:
            config_network = json.loads(fd.read())

        segment_image(image_path,
                      model_path,
                      25,
                      config_network,
                      resolution,
                      acquired_resolution=pixel_size_float,
                      verbosity_level=3)

        # The axon_segmentation function creates the segmentation masks and stores them as PNG files in the same folder
        # as the original image file.

        # Load the axon and myelin masks into FSLeyes
        axon_mask_path = image_directory / (image_name_no_extension +
                                            "_seg-axon.png")
        myelin_mask_path = image_directory / (image_name_no_extension +
                                              "_seg-myelin.png")
        self.load_png_image_from_path(axon_mask_path,
                                      is_mask=True,
                                      colormap="blue")
        self.load_png_image_from_path(myelin_mask_path,
                                      is_mask=True,
                                      colormap="red")
        self.pixel_size_float = pixel_size_float

        return self