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()