def button_clear_fit(event): '''Clear the fits curves from the plot''' nonlocal list_fit_denser_line2D nonlocal fit_function clear_line2D(figure, lines2D['fit'], axes, redraw=True) for line2D in list_fit_denser_line2D: clear_line2D(figure, line2D, axes, redraw=True) fit_function = None
def button_add_fit(event): '''Add the fit to the plot''' nonlocal fit_function if fit_interval_ready: # If a previous fit, clear it clear_line2D(figure, lines2D['fit'], axes, redraw=False) if not ivar['not_refresh_flag']: clear_line2D(figure, lines2D['fit_denser'], axes, redraw=False) # Get current colors in the axis to not repeat them colors = [ l.get_color() for l in axes.get_lines() ] # Fit if mask['nonfit'] is not None: if interval['xmin_nonfit'] > interval['xmin_fit'] and interval['xmax_nonfit'] < interval['xmax_fit']: mask_fit_minus_nonfit = np.logical_xor(mask['fit'], mask['nonfit']) else: print('**The non fit interval is outside the fit interval. It will be ignored.**') mask_fit_minus_nonfit = mask['fit'].copy() else: mask_fit_minus_nonfit = mask['fit'].copy() xfit = x[mask_fit_minus_nonfit] yfit = y[mask_fit_minus_nonfit] # Force the fit to match the fist two data points and the last two data points to promote a smoother match with the original xfit_fixed = np.concatenate([ [xfit[0]], [xfit[1]], [xfit[-2]], [xfit[-1]] ]) yfit_fixed = np.concatenate([ [yfit[0]], [yfit[1]], [yfit[-2]], [yfit[-1]] ]) # Fit fit_function = np.poly1d( polyfit_with_fixed_points(ivar['polynomial_degree'], xfit, yfit, xfit_fixed, yfit_fixed) ) color = 'lime' if not 'lime' in colors else None lines2D['fit'], = axes.plot(x[mask['fit']], fit_function(x[mask['fit']]), linestyle='None', marker='o', color=color, markerfacecolor=color, markeredgecolor='None') # Plot a denser x to evidence possible wiggles between the original data points_in_between = np.arange(0.0, 1.0, 0.1) x_mask_diff = np.diff(x[mask['fit']]) x_mask_denser = np.array([]) for shift in points_in_between: x_mask_denser = np.concatenate( [ x_mask_denser, x[mask['fit']][:-1] + x_mask_diff * shift ] ) # Add the last point x_mask_denser = np.concatenate( [ x_mask_denser, np.array( [ x[mask['fit']][-1] ] ) ] ) x_mask_denser = np.sort( x_mask_denser ) color = lines2D['fit'].get_color() lines2D['fit_denser'], = axes.plot(x_mask_denser, fit_function(x_mask_denser), linestyle='solid', marker=None, color=color, label='Polynomial fit n={}'.format(ivar['polynomial_degree'])) list_fit_denser_line2D.append(lines2D['fit_denser']) # Redraw axes.legend(loc='best', ncol=1, framealpha=0.5, fontsize=10) figure.canvas.draw()
def onselect(vmin, vmax): '''Select the interval for the fit and the interval to be excluded in the fit''' nonlocal fit_interval_ready # Interval to fit # Activate by pressing Enter and then using the left button if ivar['keystroke'] == 'enter' and ivar['pressed_button'] == 1: clear_line2D(figure, lines2D['fit_interval'], axes, redraw=False) # Store the values interval['xmin_fit'] = vmin interval['xmax_fit'] = vmax # Print the interval print('Interval for the fit:') print('xmin = {:.3},\t xmax = {:.3}\n'.format(vmin, vmax)) # Get the indices of the values within the selected span condition1_fit = interval['xmin_fit'] < x condition2_fit = x < interval['xmax_fit'] mask['fit'] = np.logical_and(condition1_fit, condition2_fit) # Plot in red the selected span as an aditional Line2D object in lines if interval['xmin_fit'] != interval['xmax_fit']: lines2D['fit_interval'], = axes.plot(x[mask['fit']], y[mask['fit']], linestyle='None', marker='o', markerfacecolor='red', markeredgecolor='None', label='Fit interval') fit_interval_ready = True else: fit_interval_ready = False # Interval to exclude # Activate by pressing Enter and then using the right button OR pressing Shift+Enter and the using left button if (ivar['keystroke']=='shift+enter' and ivar['pressed_button']==1) or (ivar['keystroke']=='enter' and ivar['pressed_button']==3): clear_line2D(figure, lines2D['v1'], axes, redraw=False) clear_line2D(figure, lines2D['v2'], axes, redraw=False) interval['xmin_nonfit'] = vmin interval['xmax_nonfit'] = vmax # Print the interval print('Interval to be excluded in the fit:') print('xmin = {:.3},\t xmax = {:.3}\n'.format(vmin, vmax)) # Get the indices of the values within the selected span condition1_nonfit = interval['xmin_nonfit'] < x condition2_nonfit = x < interval['xmax_nonfit'] mask['nonfit'] = np.logical_and(condition1_nonfit, condition2_nonfit) # Plot in black the selected span if interval['xmin_nonfit'] != interval['xmax_nonfit']: lines2D['v1'] = axes.axvline(interval['xmin_nonfit'], label='Nonfit interval', linestyle='dashed', color='black') lines2D['v2'] = axes.axvline(interval['xmax_nonfit'], linestyle='dashed', color='black') # Redraw axes.legend(loc='best', ncol=1, framealpha=0.5, fontsize=10) figure.canvas.draw()