def __sortt(self, key): cut_file = key.split('.') element_object = Element(cut_file[0].strip()) element, isotope = element_object.get_element_and_isotope() mass = str(isotope) if not mass: mass = self.__masses.get_standard_isotope(element) else: mass = float(mass) return mass
def __sortt(self, key): if key == "total": return -1 element_object = Element(key) element, isotope = element_object.get_element_and_isotope() mass = str(isotope) if not mass: mass = self.__masses.get_standard_isotope(element) else: mass = float(mass) return mass
def __init__(self, axes, masses, element_colormap, settings, element=None, isotope=None, element_type="ERD", color=None, points=None, scatter=None, weight_factor=1, transposed=False): '''Inits Selection class. Args: axes: Matplotlib FigureCanvas's subplot masses: Reference to element masses object of main program. element_colormap: Default colors for new element selections. settings: Measurement's settings to which selector belongs. (for selection dialog) element: String representing element isotope: String representing isotope element_type: "ERD" or "RBS" color: String representing color for the element points: String list representing points in selection. "X1, X2, X3;Y1, Y2, Y3" scatter: String representing scatter element. weight_factor: Weight factor for the element. transposed: Boolean representing if axes are transposed. ''' self.id = Selection.GLOBAL_ID self.masses = masses # Element isotopes self.element_colormap = element_colormap self.settings = settings if color != None: self.default_color = color elif element != None: self.default_color = self.element_colormap[element] else: # By change that color is not in element_colormap self.default_color = "red" self.type = element_type self.element = Element(element, isotope) self.weight_factor = weight_factor self.element_scatter = Element(scatter) self.events_counted = False self.event_count = 0 self.__is_transposed = False self.is_closed = False self.points = None self.axes = axes self.axes_limits = AxesLimits() Selection.GLOBAL_ID += 1 if points != None: points = points.split(';') if transposed: points[0], points[1] = points[1], points[0] x = [int(i) for i in points[0].split(',')] # y = [int(i) for i in points[1].split(',')] # point_count = len(x) # for i in range(point_count): # self.add_point((x[i], y[i])) self.end_selection()
def on_draw(self): '''Draw method for matplotlib. ''' self.axes.clear() # Clear old stuff # keys = sorted(self.split.keys()) keys = [item[0] for item in sorted(self.split.items(), key=lambda x: self.__sortt(x[0]))] for key in keys: cut_file = key.split('.') element_object = Element(cut_file[0].strip()) element, isotope = element_object.get_element_and_isotope() if key in self.__ignore_elements: continue # Check RBS selection rbs_string = "" if len(cut_file) == 2: if key + ".cut" in self.__rbs_list.keys(): element_object = self.__rbs_list[key + ".cut"] element, isotope = element_object.get_element_and_isotope() rbs_string = "*" else: if key + cut_file[2] in self.__rbs_list.keys(): element_object = self.__rbs_list[key + cut_file[2]] element, isotope = element_object.get_element_and_isotope() rbs_string = "*" # Get color for selection color_string = "{0}{1}{2}".format(isotope, element, cut_file[1]) if not color_string in self.selection_colors: color = "red" else: color = self.selection_colors[color_string] # Set label text if len(cut_file) == 2: label = r"$^{" + str(isotope) + "}$" + element + rbs_string else: label = r"$^{" + str(isotope) + "}$" + element + rbs_string \ + "$_{split: " + cut_file[2] + "}$" # Modify data if scaled to 100. data = self.split[key] if self.__scale_mode == 2: modifier = 100 / self.split[key][0] data = [i * modifier for i in data] self.axes.plot(data, color=color, label=label) if self.draw_legend: if not self.__initiated_box: self.fig.tight_layout(pad=0.5) box = self.axes.get_position() self.axes.set_position([box.x0, box.y0, box.width * 0.9, box.height]) self.__initiated_box = True handles, labels = self.axes.get_legend_handles_labels() leg = self.axes.legend(handles, labels, loc=3, bbox_to_anchor=(1, 0), borderaxespad=0, prop={'size':12}) for handle in leg.legendHandles: handle.set_linewidth(3.0) # Scale based on values x_min, x_max = self.axes.get_xlim() y_min, y_max = self.axes.get_ylim() # Y-axis scaling option, 0 = 0-max, 1 = min-max if self.y_scale == 0: y_min = 0 # Set limits accordingly self.axes.set_ylim([y_min, y_max]) self.axes.set_xlim([x_min, x_max]) # Scale for log if self.__scale_mode == 1: self.axes.set_yscale('symlog') else: self.axes.set_yscale('linear') # Set axes names if self.__scale_mode == 2: self.axes.set_ylabel("Scaled count") else: self.axes.set_ylabel("Count") self.axes.set_xlabel("Split") # Remove axis ticks self.remove_axes_ticks() self.canvas.draw()
class Selection: """Selection object which knows all selection points. """ LINE_STYLE = "-" # Default line style for selections LINE_MARKER = "o" # Default node style for selections LINE_MARKER_SIZE = 3.0 GLOBAL_ID = 0 def __init__( self, axes, masses, element_colormap, settings, element=None, isotope=None, element_type="ERD", color=None, points=None, scatter=None, weight_factor=1, transposed=False, ): """Inits Selection class. Args: axes: Matplotlib FigureCanvas's subplot masses: Reference to element masses object of main program. element_colormap: Default colors for new element selections. settings: Measurement's settings to which selector belongs. (for selection dialog) element: String representing element isotope: String representing isotope element_type: "ERD" or "RBS" color: String representing color for the element points: String list representing points in selection. "X1, X2, X3;Y1, Y2, Y3" scatter: String representing scatter element. weight_factor: Weight factor for the element. transposed: Boolean representing if axes are transposed. """ self.id = Selection.GLOBAL_ID self.masses = masses # Element isotopes self.element_colormap = element_colormap self.settings = settings if color != None: self.default_color = color elif element != None: self.default_color = self.element_colormap[element] else: # By change that color is not in element_colormap self.default_color = "red" self.type = element_type self.element = Element(element, isotope) self.weight_factor = weight_factor self.element_scatter = Element(scatter) self.events_counted = False self.__event_count = 0 self.__is_transposed = False self.is_closed = False self.points = None self.axes = axes self.axes_limits = AxesLimits() Selection.GLOBAL_ID += 1 if points != None: points = points.split(";") if transposed: points[0], points[1] = points[1], points[0] x = [int(i) for i in points[0].split(",")] # y = [int(i) for i in points[1].split(",")] # point_count = len(x) # for i in range(point_count): # self.add_point((x[i], y[i])) self.end_selection() def add_point(self, point): """Adds a point to selection. Adds a point to selection. If selection is closed, do nothing. Args: point: Point (x, y) to be added to selection. Return: 0: Point was added. -1: If selection is closed. """ if self.is_closed: return -1 else: if self.points == None: self.points = Line2D( [point[0]], [point[1]], linestyle=Selection.LINE_STYLE, marker=Selection.LINE_MARKER, markersize=Selection.LINE_MARKER_SIZE, color=self.default_color, ) else: x, y = self.points.get_data() x.append(point[0]) y.append(point[1]) self.points.set_data(x, y) self.axes.add_line(self.points) return 0 def undo_last(self): """Undo last point in selection. Return: 1: If selection is closed or there are no points in selection. 0: If everything is ok. """ if self.is_closed: return 1 # After this, purge the last points so no duplicates should be inside. x, y = self.points.get_data() if not x: return 1 x.pop() y.pop() self.points.set_data(x, y) return 0 def get_points(self): """Get points in selection Get points in selection in list. Format: ((x1,y1), (x2,y2), ...). If no points, empty list is returned Return: ((x1, y1), (x2, y2), ...) """ points = self.points.get_data() pointlist = [] n = 0 x = len(points[0]) while n < x: pointlist.append([points[0][n], points[1][n]]) n += 1 return pointlist def get_first(self): """Get first point in selection Return: None: If no point in selection (x, y): Otherwise """ if self.count() > 0: x, y = self.points.get_data() return (x[0], y[0]) # TODO: Should this be tuple or a class? else: return None def get_last(self): """Get last point in selection Return: None: If no point in selection (x, y): Otherwise """ if self.count() > 0: x, y = self.points.get_data() return (x[-1], y[-1]) # TODO: Should this be tuple or a class? else: return None def count(self): """Get the count of node points in selection. Return Returns the count of node points in selection. """ if self.points == None: # No data yet, "empty" list return 0 return len(self.points.get_data()[0]) # X data count is fine. def end_selection(self, canvas=None): """End selection. Ends selection. If selection is open and canvas is not None, it will show dialog to select element information and draws into canvas before opening the dialog. Args: canvas: Matplotlib's FigureCanvas or None when we don't want to new selection window. None, when loading selections so we do not want to open new selection settings dialog. Return: True: Selection was completed False: Selection settings was not set (cancel button) """ for point in self.get_points(): self.axes_limits.update_limits(point) # Add first point again, so drawing the line is closed. # Then remove it, so no duplicates in points. (roundabout) self.add_point(self.get_first()) x, y = self.points.get_data() x.pop() y.pop() selection_completed = True if canvas != None: canvas.draw_idle() selection_settings_dialog = SelectionSettingsDialog(self) # True = ok, False = cancel -> delete selection selection_completed = selection_settings_dialog.isOk self.is_closed = True return selection_completed def delete(self): """Delete this selection. """ self.points.set_data(((), ())) self.points = None self.masses = None self.element_colormap = None def draw(self): """Draw selection points into graph (matplotlib) axes """ self.axes.add_line(self.points) def set_color(self, color): """Set selection color Args: color: String representing color. Format is whatever QtGui.QColor(string) understands. """ self.points.set_color(color) def reset_color(self): """Reset selection color to default color. """ self.set_color(self.default_color) def __save_points(self, is_transposed): """Get selection points in format for saving. Args: is_transposed: Boolean representing if axes are transposed. Return: Returns string representing current points in selection. """ # [1, 4, 2, 6] # to # 1,4,2,6 x, y = self.points.get_data() x = ",".join(str(i) for i in x) y = ",".join(str(j) for j in y) # x = str(x).strip('[').strip(']').strip(' ') # TODO: format? # y = str(y).strip('[').strip(']').strip(' ') # TODO: format? if is_transposed: x, y = y, x s = (x, y) return ";".join(s) def save_string(self, is_transposed): """Get selection in string format for selectiong file save. Args: is_transposed: Boolean representing if axes are transposed. Return: String representing current selection object. """ element, isotope = self.element.get_element_and_isotope() save_string = "{0} {1} {2} {3} {4} {5} {6}".format( self.type, element, isotope, self.weight_factor, self.element_scatter, self.default_color, self.__save_points(is_transposed), ) return save_string def transpose(self, transpose): """Transpose selection points. Args: transpose: Boolean representing whether to transpose selection points. """ if transpose: # and not self.__is_transposed self.__is_transposed = True x, y = self.points.get_data() x.append(x[0]) y.append(y[0]) self.points.set_data(y, x) elif not transpose: # and self.__is_transposed self.__is_transposed = False x, y = self.points.get_data() x.append(x[0]) y.append(y[0]) self.points.set_data(y, x) def get_event_count(self): """Get the count of event points within the selection. Return: Returns an integer representing the count of event points within the selection. """ return self.__event_count def point_inside(self, point): """Check if point is inside selection. Args: point: [X, Y] representing a point. Return: Returns True if point is within selection. False otherwise. """ if not self.axes_limits.is_inside(point): return False inside = self.__point_inside_polygon(point[0], point[1], self.get_points()) # While at it, increase event point counts if not counted already. if inside and not self.events_counted: self.__event_count += 1 return inside def __point_inside_polygon(self, x, y, poly): """Finds out if a point x, y is inside a polygon "poly" Determine if a point is inside a given polygon or not Polygon is a list of (x,y) pairs. Algorithm got from: http://www.ariel.com.au/a/python-point-int-poly.html """ n = len(poly) inside = False p1x, p1y = poly[0] for i in range(n + 1): p2x, p2y = poly[i % n] if y > min(p1y, p2y): if y <= max(p1y, p2y): if x <= max(p1x, p2x): if p1y != p2y: xinters = (y - p1y) * (p2x - p1x) / (p2y - p1y) + p1x if p1x == p2x or x <= xinters: inside = not inside p1x, p1y = p2x, p2y return inside
def on_draw(self): '''Draw method for matplotlib. ''' # Values for zoom x_min, x_max = self.axes.get_xlim() y_min, y_max = self.axes.get_ylim() self.axes.clear() # Clear old stuff self.axes.set_ylabel("Yield (counts)") self.axes.set_xlabel("Energy (MeV)") element_counts = {} keys = [item[0] for item in sorted(self.histed_files.items(), key=lambda x: self.__sortt(x[0]))] for key in keys: cut_file = key.split('.') cut = self.histed_files[key] element_object = Element(cut_file[0]) # Yeah... element, isotope = element_object.get_element_and_isotope() if key in self.__ignore_elements: continue # Check RBS selection rbs_string = "" if len(cut_file) == 2: if key + ".cut" in self.__rbs_list.keys(): element_object = self.__rbs_list[key + ".cut"] element, isotope = element_object.get_element_and_isotope() rbs_string = "*" else: if key in self.__rbs_list.keys(): element_object = self.__rbs_list[key] element, isotope = element_object.get_element_and_isotope() rbs_string = "*" x = tuple(float(pair[0]) for pair in cut) y = tuple(float(pair[1]) for pair in cut) # Get color for selection dirtyinteger = 0 while "{0}{1}{2}".format(isotope, element, dirtyinteger) in element_counts: dirtyinteger += 1 color_string = "{0}{1}{2}".format(isotope, element, dirtyinteger) element_counts[color_string] = 1 if not color_string in self.__selection_colors: color = "red" else: color = self.__selection_colors[color_string] if len(cut_file) == 2: label = r"$^{" + str(isotope) + "}$" + element + rbs_string else: label = r"$^{" + str(isotope) + "}$" + element + rbs_string \ + "$_{split: " + cut_file[2] + "}$" self.axes.plot(x, y, color=color, label=label) if self.draw_legend: if not self.__initiated_box: self.fig.tight_layout(pad=0.5) box = self.axes.get_position() self.axes.set_position([box.x0, box.y0, box.width * 0.9, box.height]) self.__initiated_box = True handles, labels = self.axes.get_legend_handles_labels() leg = self.axes.legend(handles, labels, loc=3, bbox_to_anchor=(1, 0), borderaxespad=0, prop={'size':12}) for handle in leg.legendHandles: handle.set_linewidth(3.0) if x_max > 0.09 and x_max < 1.01: # This works... x_max = self.axes.get_xlim()[1] if y_max > 0.09 and y_max < 1.01: y_max = self.axes.get_ylim()[1] # 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') # Remove axis ticks self.remove_axes_ticks() # Draw magic self.canvas.draw()