def __make_legend_box(self):
        """Make legend box for the graph.
        """
        box = self.axes.get_position()
        if not self.__position_set:
            self.axes.set_position([box.x0, box.y0, box.width * 0.8, box.height])
            self.__position_set = True
        handles, labels = self.axes.get_legend_handles_labels()
        # self.__ignore_from_ratio = ["Si"]

        concentrations = df.integrate_concentrations(self.read_files, self.__ignore_from_ratio, self.lim_a, self.lim_b)
        percentages, moe = df.integrate_lists(
            self.read_files, self.__ignore_from_ratio, self.lim_a, self.lim_b, self.__systerr
        )
        # Fix labels to proper format, with MoE
        labels_w_percentages = []
        for i in range(0, len(labels)):
            element = Element(labels[i])
            element_str = str(element)
            element_name = element.name
            if element_str in self.__rbs_list.values():
                element_name += "*"
            str_element = "{0:>3}{1:<3}".format(str(element.isotope), str(element_name))
            # str_element = labels[i]
            # percentages[element_str] can be 0 which results false
            # None when element is ignored from ratio calculation.
            if percentages[element_str] != None:
                rounding = self.__physic_rounding_decimals(moe[element_str])
                # lbl_str = '%s %.3f%% ±%.3f%%' % (labels[i],
                #                             percentages[element_str],
                #                             moe[element_str])
                # Extra 5 from math text format for isotope index
                if rounding:
                    str_ratio = "{0}%".format(round(percentages[element_str], rounding))
                    str_err = "± {0}%".format(round(moe[element_str], rounding))
                else:
                    str_ratio = "{0}%".format(int(percentages[element_str]))
                    str_err = "± {0}%".format(int(moe[element_str]))
                lbl_str = "{0} {1:<6} {2}".format(str_element, str_ratio, str_err)
            else:
                lbl_str = "{0}".format(str_element)

            # Use absolute values for the elements instead of percentages.
            if self.__absolute_values:
                lbl_str = "{0} {1:<7} at./1e15 at./cm²".format(str_element, round(sum(concentrations[element_str]), 3))
            labels_w_percentages.append(lbl_str)
        leg = self.axes.legend(
            handles,
            labels_w_percentages,
            loc=3,
            bbox_to_anchor=(1, 0),
            borderaxespad=0,
            prop={"size": 11, "family": "monospace"},
        )
        for handle in leg.legendHandles:
            handle.set_linewidth(3.0)
 def __init__(self, parent, depth_dir, elements, rbs_list, depth_scale,
              x_units='nm', legend=True, line_zero=False, line_scale=False,
              systematic_error=3.0):
     '''Inits depth profile widget.
     
     Args:
         parent: A DepthProfileWidget class object.
         depth_dir: A directory where the depth files are located.
         elements: A list of Element objects.
         rbs_list: A dictionary of RBS selection elements containing 
                   scatter elements.
         depth_scale: A tuple of depth scaling values.
         x_units: An unit to be used as x axis.
         legend: A boolean of whether to show the legend.
         line_zero: A boolean representing if vertical line is drawn at zero.
         line_scale: A boolean representing if horizontal line is drawn at 
                     the defined depth scale.
         systematic_error: A double representing systematic error.
     '''
     super().__init__(parent)
     super().fork_toolbar_buttons()
     self.canvas.manager.set_title("Depth Profile")
     self.axes.fmt_xdata = lambda x: "{0:1.2f}".format(x)
     self.axes.fmt_ydata = lambda y: "{0:1.2f}".format(y)
     self.x_units = x_units
     self.draw_legend = legend
     self.elements = elements
     self.depth_dir = depth_dir
     self.__depth_scale = depth_scale
     self.__line_zero = line_zero
     self.__line_scale = line_scale
     self.__systerr = systematic_error
     self.depth_files = df.get_depth_files(self.elements, self.depth_dir)
     self.read_files = []
     self.rel_files = []
     self.hyb_files = []
     self.__ignore_from_graph = []
     self.__ignore_from_ratio = []
     self.selection_colors = parent.measurement.selector.get_colors()
     self.icon_manager = parent.icon_manager
     self.__masses = parent.parent.masses
     self.lim_a = float
     self.lim_b = float
     self.lim_icons = {'a':'depth_profile_lim_all.svg',
                       'b':'depth_profile_lim_in.svg',
                       'c':'depth_profile_lim_ex.svg'}
     self.lim_mode = 'a'
     self.canvas.mpl_connect('button_press_event', self.onclick)
     self.__files_read = False
     self.__limits_set = False
     self.__position_set = False
     self.__rel_graph = False
     self.__show_limits = False
     self.__log_scale = False
     self.__absolute_values = False
     self.__enable_norm_over_range = False
     self.__use_limit = self.__limit()
     self.__rbs_list = rbs_list
     self.__fork_toolbar_buttons()
     self.on_draw()
    def on_draw(self):
        """Draws the depth profile graph
        """
        # Values for zoom
        x_min, x_max = self.axes.get_xlim()
        y_min, y_max = self.axes.get_ylim()

        # Clear axes for a new draw.
        self.axes.clear()

        # Select the units of the x-axis and what columns to read
        # from the depth files
        y_column = 3
        if self.x_units == "nm":
            x_column = 2
        else:
            x_column = 0
        self.axes.set_xlabel("Depth (%s)" % (self.x_units))
        self.axes.set_ylabel("Concentration (at.%)")

        # If files have not been read before, they are now
        if not self.__files_read:
            full_paths = []
            for file in self.depth_files:
                full_path = os.path.join(self.depth_dir, file)
                full_paths.append(full_path)
            self.read_files = df.extract_from_depth_files(full_paths, self.elements, x_column, y_column)
            self.__files_read = True
            self.rel_files = df.create_relational_depth_files(self.read_files)
            # if not self.lim_a:
            self.lim_a = self.read_files[0][1][0]
            self.lim_b = self.read_files[0][1][-1]
            # self.__limits_set = not self.__limits_set

        # Determine what files to use for plotting
        if not self.__rel_graph:
            files_to_use = self.read_files
        elif self.lim_mode == "a":
            files_to_use = self.rel_files
        else:
            tmp_a = list
            tmp_b = list
            if self.lim_mode == "b":
                tmp_a = self.read_files
                tmp_b = self.rel_files
            else:
                tmp_a = self.rel_files
                tmp_b = self.read_files
            self.hyb_files = df.merge_files_in_range(tmp_a, tmp_b, self.lim_a, self.lim_b)
            files_to_use = self.hyb_files

        # Plot the limits a and b
        if self.__show_limits:
            self.axes.axvline(x=self.lim_a, linestyle="--")
            if self.lim_b:  # TODO: Why is this sometimes null?
                self.axes.axvline(x=self.lim_b, linestyle="--")

        self.axes.axhline(y=0, color="#000000")
        if self.__line_zero:
            self.axes.axvline(x=0, linestyle="-", linewidth=3, color="#C0C0C0", alpha=0.75)

        if self.__line_scale:
            self.axes.axvspan(self.__depth_scale[0], self.__depth_scale[1], color="#C0C0C0", alpha=0.20, edgecolor=None)

        # Plot the lines
        files_to_use = sorted(files_to_use, key=lambda x: self.__sortt(x[0]))
        self.elements = sorted(self.elements, key=lambda x: self.__sortt(x))
        for file in files_to_use:
            if file[0] == "total" or file[0] in self.__ignore_from_graph:
                continue
            element = re.sub("\d+", "", file[0])
            isotope = re.sub("\D", "", file[0])

            # Check RBS selection
            rbs_string = ""
            if file[0] in self.__rbs_list.values():
                rbs_string = "*"

            axe1 = file[1]
            axe2 = file[2]

            # TODO: erd_depth for multiple selections of same element.
            color_key = "{0}{1}0".format(isotope, element)
            filler_length = 3 - len(isotope)
            filler_prefix = ""
            filler_suffix = ""
            for unused_i in range(0, filler_length):
                filler_prefix += "\ "
            filler_length = 4 - len(element) - len(rbs_string)
            for unused_i in range(0, filler_length):
                filler_suffix += "\ "
            # label = r"$^{\mathtt{" + filler_prefix + str(isotope) + \
            #        "}}\mathtt{" + element + rbs_string + filler_suffix + "}$"
            label = str(isotope) + element
            self.axes.plot(axe1, axe2, label=label, color=self.selection_colors[color_key])

        if not self.__position_set:
            self.fig.tight_layout(pad=0.5)

        # Set up the legend
        if self.draw_legend:
            self.__make_legend_box()

        # If drawing for "the first time", get limits from the drawn data.
        if x_max > 0.09 and x_max < 1.01:  # This works...
            x_min, x_max = self.axes.get_xlim()
        if y_max > 0.09 and y_max < 1.01:
            y_min, y_max = self.axes.get_ylim()

        # Set limits accordingly
        self.axes.set_ylim([y_min, y_max])
        self.axes.set_xlim([x_min, x_max])

        if self.__log_scale:
            self.axes.set_yscale("symlog")

        self.remove_axes_ticks()
        self.canvas.draw()