def zero_crossings(y_axis, x_axis=None, window=24): """ Algorithm to find zero crossings. Smoothens the curve and finds the zero-crossings by looking for a sign change. keyword arguments: y_axis -- A list containg the signal over which to find zero-crossings x_axis -- A x-axis whose values correspond to the 'y_axis' list and is used in the return to specify the postion of the zero-crossings. If omitted then the indice of the y_axis is used. (default: None) window -- half of the dimension of the smoothing window; (default: 24) return -- the x_axis value or the indice for each zero-crossing """ # smooth the curve length = len(y_axis) if x_axis == None: x_axis = range(length) x_axis = np.asarray(x_axis) y_axis = smooth(y_axis, window) zero_crossings = np.where(np.diff(np.sign(y_axis)))[0] times = [x_axis[indice] for indice in zero_crossings] # check if zero-crossings are valid diff = np.diff(times) if diff.std() / diff.mean() > 0.1: raise ValueError, "smoothing window too small, false zero-crossings found" return times
def smooth_data(self): with self.data_changed.hold_and_emit(): if self.smooth_degree > 0: degree = int(self.smooth_degree) self.data_y[:, 0] = smooth(self.data_y[:, 0], degree) self.smooth_degree = 0.0
def smooth_pattern(pattern): """ Smooth the given pattern. """ return smooth(pattern, 15)
def plot_specimen(project, specimen, labels, marker_lbls, label_offset, plot_left, offset, scale, marker_scale, axes): """ Plots a specimens patterns, markers and hatches using the given offset and scale """ # Plot the patterns; if specimen.display_experimental: pattern = specimen.experimental_pattern # plot the experimental pattern: plot_pattern(pattern, axes, scale=scale, offset=offset, cap=pattern.cap_value) #make_draggable(getattr(pattern, "__plot_line", None), drag_y_handler=specimen.on_pattern_dragged) # get some common data for the next lines: x_data, y_data = pattern.get_xy_data() xmin, xmax = (np.min(x_data), np.max(x_data)) if x_data.size > 0 else (0, 0) ymin, ymax = (np.min(y_data), np.max(y_data)) if y_data.size > 0 else (0, 0) ######################################################################## # plot the background pattern: bg_line = getattr_or_create( pattern, "__plot_bg_line", (matplotlib.lines.Line2D, ([], []), dict(c="#660099", lw="2", zorder=10))) if pattern.bg_type == 0 and pattern._bg_position != 0.0: bg_line.update( dict(data=apply_transform( ([xmin, xmax], [pattern.bg_position, pattern.bg_position]), scale=scale, offset=offset), visible=True)) elif pattern.bg_type == 1 and pattern.bg_pattern is not None: bg_line.update( dict(data=apply_transform( (x_data, (pattern.bg_pattern * pattern.bg_scale) + pattern.bg_position), scale=scale, offset=offset), visible=True)) else: bg_line.update(dict(data=([], []), visible=True)) if bg_line.get_visible() and not bg_line in axes.get_lines(): axes.add_line(bg_line) elif not bg_line.get_visible(): try: bg_line.remove() except: pass pattern.__plot_bg_line = bg_line ######################################################################## ######################################################################## # plot the smooth pattern: smooth_line = getattr_or_create( pattern, "__plot_smooth_line", (matplotlib.lines.Line2D, ([], []), dict(c="#660099", lw="2", zorder=10))) if int(pattern.smooth_degree) > 1: data = x_data, smooth(y_data, pattern.smooth_degree) else: data = [], [] smooth_line.update( dict(data=apply_transform(data, scale=scale, offset=offset), visible=bool(pattern.smooth_degree > 1))) if smooth_line.get_visible() and not smooth_line in axes.get_lines(): axes.add_line(smooth_line) elif not smooth_line.get_visible(): try: smooth_line.remove() except: pass pattern.__plot_smooth_line = smooth_line ######################################################################## ######################################################################## # plot the noisified pattern: noise_line = getattr_or_create( pattern, "__plot_noise_line", (matplotlib.lines.Line2D, ([], []), dict(c="#660099", lw="2", zorder=10))) if pattern.noise_fraction > 0.0: data = x_data, add_noise(y_data, pattern.noise_fraction) else: data = [], [] noise_line.update( dict(data=apply_transform(data, scale=scale, offset=offset), visible=bool(pattern.noise_fraction > 0.0))) if noise_line.get_visible() and not noise_line in axes.get_lines(): axes.add_line(noise_line) elif not noise_line.get_visible(): try: noise_line.remove() except: pass pattern.__plot_noise_line = noise_line ######################################################################## ######################################################################## # plot the shift & reference lines: shifted_line = getattr_or_create( pattern, "__plot_shifted_line", (matplotlib.lines.Line2D, ([], []), dict(c="#660099", lw="2", zorder=10))) reference_line = getattr_or_create( pattern, "__plot_reference_line", (matplotlib.lines.Line2D, ([], []), dict(c="#660099", lw="2", ls="--", zorder=10))) if pattern.shift_value != 0.0: shifted_line.update( dict(data=apply_transform( (x_data - pattern._shift_value, y_data.copy()), scale=scale, offset=offset), visible=True)) position = specimen.goniometer.get_2t_from_nm( pattern.shift_position) reference_line.update( dict(data=apply_transform(([position, position], [0, ymax]), scale=scale, offset=offset), visible=True)) if not shifted_line in axes.get_lines(): axes.add_line(shifted_line) if not reference_line in axes.get_lines(): axes.add_line(reference_line) else: shifted_line.set_data([], []) shifted_line.set_visible(False) try: shifted_line.remove() except: pass reference_line.set_data([], []) reference_line.set_visible(False) try: reference_line.remove() except: pass pattern.__plot_shifted_line = shifted_line pattern.__plot_reference_line = reference_line ######################################################################## ######################################################################## # plot the pattern after peak stripping: stripped_line = getattr_or_create( pattern, "__plot_stripped_line", (matplotlib.lines.Line2D, ([], []), dict(c="#660099", lw="1", zorder=10))) if pattern.strip_startx != 0.0 and pattern.strip_endx != 0.0: strip_xdata, strip_ydata = pattern.stripped_pattern stripped_line.update( dict(data=apply_transform( (strip_xdata.copy(), strip_ydata.copy()), scale=scale, offset=offset), visible=True)) if not stripped_line in axes.get_lines(): axes.add_line(stripped_line) else: stripped_line.set_data([], []) stripped_line.set_visible(False) try: stripped_line.remove() except: pass pattern.__plot_stripped_line = stripped_line ######################################################################## ######################################################################## # plot the pattern after peak stripping: peak_area = getattr(specimen, "__plot_peak_area", None) if peak_area is not None and peak_area in axes.get_children(): peak_area.remove() if pattern.area_startx != 0.0 and pattern.area_endx != 0.0 and pattern.area_pattern is not None: area_xdata, area_bg, area_ydata = pattern.area_pattern _, area_bg = apply_transform((area_xdata.copy(), area_bg.copy()), scale=scale, offset=offset) area_xdata, area_ydata = apply_transform( (area_xdata.copy(), area_ydata.copy()), scale=scale, offset=offset) peak_area = axes.fill_between(area_xdata, area_bg, area_ydata, interpolate=True, facecolor="#660099", zorder=10) setattr(specimen, "__plot_peak_area", peak_area) if specimen.display_calculated: pattern = specimen.calculated_pattern plot_pattern(pattern, axes, scale=scale, offset=offset) #if not specimen.display_experimental: # make_draggable(getattr(pattern, "__plot_line", None), drag_y_handler=specimen.on_pattern_dragged) # setup or update the calculated lines (phases) if specimen.display_phases: phase_lines = getattr(specimen, "__plot_phase_lines", []) # Clear previous phase lines: for phase_line in phase_lines: if phase_line in axes.get_lines(): axes.remove_line(phase_line) # Update & add phase lines: for i in range(2, pattern.num_columns): phase_data = pattern.get_xy_data(i) # Get the line object or create it: try: phase_line = phase_lines[i - 2] except IndexError: phase_line = matplotlib.lines.Line2D(*phase_data) phase_lines.append(phase_line) # Get the phase color or use a default color: try: phase_color = pattern.phase_colors[i - 2] except IndexError: phase_color = pattern.color # Update the line object properties: phase_line.update( dict(data=apply_transform(phase_data, scale=scale, offset=offset), color=phase_color, linewidth=pattern.lw)) # Add to axes: axes.add_line(phase_line) specimen.__plot_phase_lines = phase_lines # mineral preview sticks if hasattr(specimen, "mineral_preview") and specimen.mineral_preview is not None: name, peaks = specimen.mineral_preview lines = getattr(specimen, "__plot_mineral_preview", []) for line in lines: try: line.remove() except: pass lines = [] for position, intensity in peaks: position = specimen.goniometer.get_2t_from_nm(position / 10.) intensity /= 100. trans = transforms.blended_transform_factory( axes.transData, axes.transAxes) ymin, ymax = axes.get_ybound() style = "solid" color = "#FF00FF" y0 = (offset - ymin) / (ymax - ymin) y1 = y0 + (intensity - ymin) / (ymax - ymin) line = matplotlib.lines.Line2D([position, position], [y0, y1], transform=trans, color=color, ls=style) axes.add_line(line) lines.append(line) setattr(specimen, "__plot_mineral_preview", lines) # exclusion ranges; plot_hatches(project, specimen, offset, scale, axes) # markers; plot_markers(project, specimen, marker_lbls, offset, scale, marker_scale, axes) # & label: plot_label(specimen, labels, label_offset, plot_left, axes)
def plot_specimen(project, specimen, labels, marker_lbls, label_offset, plot_left, offset, scale, marker_scale, axes): """ Plots a specimens patterns, markers and hatches using the given offset and scale """ # Plot the patterns; if specimen.display_experimental: pattern = specimen.experimental_pattern # plot the experimental pattern: plot_pattern(pattern, axes, scale=scale, offset=offset, cap=pattern.cap_value) #make_draggable(getattr(pattern, "__plot_line", None), drag_y_handler=specimen.on_pattern_dragged) # get some common data for the next lines: x_data, y_data = pattern.get_xy_data() xmin, xmax = (np.min(x_data), np.max(x_data)) if x_data.size > 0 else (0, 0) ymin, ymax = (np.min(y_data), np.max(y_data)) if y_data.size > 0 else (0, 0) ######################################################################## # plot the background pattern: bg_line = getattr_or_create(pattern, "__plot_bg_line", (matplotlib.lines.Line2D, ([], []), dict(c="#660099", lw="2", zorder=10))) if pattern.bg_type == 0 and pattern._bg_position != 0.0: bg_line.update(dict( data=apply_transform(([xmin, xmax], [pattern.bg_position, pattern.bg_position]), scale=scale, offset=offset), visible=True )) elif pattern.bg_type == 1 and pattern.bg_pattern is not None: bg_line.update(dict( data=apply_transform((x_data, (pattern.bg_pattern * pattern.bg_scale) + pattern.bg_position), scale=scale, offset=offset), visible=True )) else: bg_line.update(dict( data=([], []), visible=True )) if bg_line.get_visible() and not bg_line in axes.get_lines(): axes.add_line(bg_line) elif not bg_line.get_visible(): try: bg_line.remove() except: pass pattern.__plot_bg_line = bg_line ######################################################################## ######################################################################## # plot the smooth pattern: smooth_line = getattr_or_create(pattern, "__plot_smooth_line", (matplotlib.lines.Line2D, ([], []), dict(c="#660099", lw="2", zorder=10))) if int(pattern.smooth_degree) > 1: data = x_data, smooth(y_data, pattern.smooth_degree) else: data = [], [] smooth_line.update(dict( data=apply_transform(data, scale=scale, offset=offset), visible=bool(pattern.smooth_degree > 1) )) if smooth_line.get_visible() and not smooth_line in axes.get_lines(): axes.add_line(smooth_line) elif not smooth_line.get_visible(): try: smooth_line.remove() except: pass pattern.__plot_smooth_line = smooth_line ######################################################################## ######################################################################## # plot the noisified pattern: noise_line = getattr_or_create(pattern, "__plot_noise_line", (matplotlib.lines.Line2D, ([], []), dict(c="#660099", lw="2", zorder=10))) if pattern.noise_fraction > 0.0: data = x_data, add_noise(y_data, pattern.noise_fraction) else: data = [], [] noise_line.update(dict( data=apply_transform(data, scale=scale, offset=offset), visible=bool(pattern.noise_fraction > 0.0) )) if noise_line.get_visible() and not noise_line in axes.get_lines(): axes.add_line(noise_line) elif not noise_line.get_visible(): try: noise_line.remove() except: pass pattern.__plot_noise_line = noise_line ######################################################################## ######################################################################## # plot the shift & reference lines: shifted_line = getattr_or_create(pattern, "__plot_shifted_line", (matplotlib.lines.Line2D, ([], []), dict(c="#660099", lw="2", zorder=10))) reference_line = getattr_or_create(pattern, "__plot_reference_line", (matplotlib.lines.Line2D, ([], []), dict(c="#660099", lw="2", ls="--", zorder=10))) if pattern.shift_value != 0.0: shifted_line.update(dict( data=apply_transform((x_data - pattern._shift_value, y_data.copy()), scale=scale, offset=offset), visible=True )) position = specimen.goniometer.get_2t_from_nm(pattern.shift_position) reference_line.update(dict( data=apply_transform(([position, position], [0, ymax]), scale=scale, offset=offset), visible=True )) if not shifted_line in axes.get_lines(): axes.add_line(shifted_line) if not reference_line in axes.get_lines(): axes.add_line(reference_line) else: shifted_line.set_data([], []) shifted_line.set_visible(False) try: shifted_line.remove() except: pass reference_line.set_data([], []) reference_line.set_visible(False) try: reference_line.remove() except: pass pattern.__plot_shifted_line = shifted_line pattern.__plot_reference_line = reference_line ######################################################################## ######################################################################## # plot the pattern after peak stripping: stripped_line = getattr_or_create(pattern, "__plot_stripped_line", (matplotlib.lines.Line2D, ([], []), dict(c="#660099", lw="1", zorder=10))) if pattern.strip_startx != 0.0 and pattern.strip_endx != 0.0: strip_xdata, strip_ydata = pattern.stripped_pattern stripped_line.update(dict( data=apply_transform((strip_xdata.copy(), strip_ydata.copy()), scale=scale, offset=offset), visible=True )) if not stripped_line in axes.get_lines(): axes.add_line(stripped_line) else: stripped_line.set_data([], []) stripped_line.set_visible(False) try: stripped_line.remove() except: pass pattern.__plot_stripped_line = stripped_line ######################################################################## ######################################################################## # plot the pattern after peak stripping: peak_area = getattr(specimen, "__plot_peak_area", None) if peak_area is not None and peak_area in axes.get_children(): peak_area.remove() if pattern.area_startx != 0.0 and pattern.area_endx != 0.0 and pattern.area_pattern is not None: area_xdata, area_bg, area_ydata = pattern.area_pattern _, area_bg = apply_transform((area_xdata.copy(), area_bg.copy()), scale=scale, offset=offset) area_xdata, area_ydata = apply_transform((area_xdata.copy(), area_ydata.copy()), scale=scale, offset=offset) peak_area = axes.fill_between(area_xdata, area_bg, area_ydata, interpolate=True, facecolor="#660099", zorder=10) setattr(specimen, "__plot_peak_area", peak_area) if specimen.display_calculated: pattern = specimen.calculated_pattern plot_pattern(pattern, axes, scale=scale, offset=offset) #if not specimen.display_experimental: # make_draggable(getattr(pattern, "__plot_line", None), drag_y_handler=specimen.on_pattern_dragged) # setup or update the calculated lines (phases) if specimen.display_phases: phase_lines = getattr(specimen, "__plot_phase_lines", []) # Clear previous phase lines: for phase_line in phase_lines: if phase_line in axes.get_lines(): axes.remove_line(phase_line) # Update & add phase lines: for i in xrange(2, pattern.num_columns): phase_data = pattern.get_xy_data(i) # Get the line object or create it: try: phase_line = phase_lines[i - 2] except IndexError: phase_line = matplotlib.lines.Line2D(*phase_data) phase_lines.append(phase_line) # Get the phase color or use a default color: try: phase_color = pattern.phase_colors[i - 2] except IndexError: phase_color = pattern.color # Update the line object properties: phase_line.update(dict( data=apply_transform(phase_data, scale=scale, offset=offset), color=phase_color, linewidth=pattern.lw )) # Add to axes: axes.add_line(phase_line) specimen.__plot_phase_lines = phase_lines # mineral preview sticks if hasattr(specimen, "mineral_preview") and specimen.mineral_preview is not None: name, peaks = specimen.mineral_preview lines = getattr(specimen, "__plot_mineral_preview", []) for line in lines: try: line.remove() except: pass lines = [] for position, intensity in peaks: position = specimen.goniometer.get_2t_from_nm(position / 10.) intensity /= 100. trans = transforms.blended_transform_factory(axes.transData, axes.transAxes) ymin, ymax = axes.get_ybound() style = "solid" color = "#FF00FF" y0 = (offset - ymin) / (ymax - ymin) y1 = y0 + (intensity - ymin) / (ymax - ymin) line = matplotlib.lines.Line2D( [position, position], [y0, y1], transform=trans, color=color, ls=style ) axes.add_line(line) lines.append(line) setattr(specimen, "__plot_mineral_preview", lines) # exclusion ranges; plot_hatches(project, specimen, offset, scale, axes) # markers; plot_markers(project, specimen, marker_lbls, offset, scale, marker_scale, axes) # & label: plot_label(specimen, labels, label_offset, plot_left, axes)