Source code for pyccapt.calibration.tutorials.tutorials_helpers.helper_mc_plot

import ipywidgets as widgets
import numpy as np
from IPython.display import display
from ipywidgets import Output

from pyccapt.calibration.core import mc_plot
from pyccapt.calibration.core.mc_plot_peak_helpers import (
    _auto_mrp_window_from_array,
    gaussian_mrp_report,
)

# Define a layout for labels to make them a fixed width
label_layout = widgets.Layout(width='200px')


[docs] def call_mc_plot(variables, selector): out = Output() # Define widgets for fine_tune_t_0 function bin_size_widget = widgets.FloatText(value=0.1) log_widget = widgets.Dropdown(options=[('True', True), ('False', False)]) grid_widget = widgets.Dropdown(options=[('True', True), ('False', False)]) mode_widget = widgets.Dropdown(options=[('False', False), ('True', True)]) mrp_all_widget = widgets.Dropdown(options=[('True', True), ('False', False)]) prominence_widget = widgets.IntText(value=10) distance_widget = widgets.IntText(value=100) lim_widget = widgets.IntText(value=10000) percent_widget = widgets.IntText(value=50) figname_widget = widgets.Text(value='hist') figure_mc_size_x = widgets.FloatText(value=9.0) figure_mc_size_y = widgets.FloatText(value=5.0) target_mode = widgets.Dropdown(options=[('mc', 'mc'), ('tof', 'tof'), ('mc_uc', 'mc_uc'), ('tof_c', 'tof_c')]) plot_peak = widgets.Dropdown(options=[('True', True), ('False', False)]) background_widget = widgets.Dropdown( options=[ ('None', None), ('pchip_valley', 'pchip_valley'), ('decay a/x + b', 'decay_inv_x'), ('decay a/sqrt(x) + b', 'decay_inv_sqrt'), ('decay a*exp(-b*x) + c', 'decay_exp'), ], value=None, ) save = widgets.Dropdown(options=[('False', False), ('True', True)]) mrp_left_widget = widgets.FloatText(value=0.0) mrp_right_widget = widgets.FloatText(value=0.0) load_selection_button = widgets.Button(description='Load selection') gaussian_mrp_button = widgets.Button(description='MRP') def _resolve_hist_array(): if target_mode.value == 'mc_uc': return variables.data['mc_uc (Da)'] if target_mode.value == 'tof_c': return variables.data['t_c (ns)'] if target_mode.value == 'tof': return variables.data['t (ns)'] return variables.data['mc (Da)'] def _auto_mrp_window(half_width=0.8): """Centre a window on the tallest peak in the current histogram.""" result = _auto_mrp_window_from_array(_resolve_hist_array(), half_width=half_width) if result is None: return None left, right, _center = result return left, right def _resolve_gaussian_window(): left = float(mrp_left_widget.value) right = float(mrp_right_widget.value) if right > left: return left, right, 'manual' if getattr(variables, 'selected_x2', 0) > getattr(variables, 'selected_x1', 0): return float(variables.selected_x1), float(variables.selected_x2), 'selection' auto = _auto_mrp_window() if auto is not None: return auto[0], auto[1], 'auto' return None def _print_gaussian_report(result): print('=' * 60) print('PEAK PROFILE MRP REPORT') print('=' * 60) print(f'MRP model: {result["recommended_label"]}') print(f'MRP bin size used: {result["bin_size"]} ({result["num_bins"]} bins)') print(f'Peak position: {result["peak_position"]:.4f}') print(f'Ions in range: {result["num_ions"]:,}') print(f'Recommended FWHM MRP: {result["formatted_recommended_mrp"][0]}') if result["window_warning"]: print(result["window_warning"]) print() print('Gaussian fit MRP:' if result['gaussian_ok'] else 'Gaussian fit FAILED') if result['gaussian_ok']: print(f' MRP(0.5) = {result["formatted_gaussian_mrp"][0]}') print(f' MRP(0.1) = {result["formatted_gaussian_mrp"][1]}') print(f' MRP(0.01) = {result["formatted_gaussian_mrp"][2]}') print() print('Voigt fit MRP:' if result['voigt_ok'] else 'Voigt fit FAILED') if result['voigt_ok']: print(f' MRP(0.5) = {result["formatted_voigt_mrp"][0]}') print(f' MRP(0.1) = {result["formatted_voigt_mrp"][1]}') print(f' MRP(0.01) = {result["formatted_voigt_mrp"][2]}') print(f' Voigt FWHM = {result["voigt_fwhm"]:.6f}') print() print('Asymmetric (err*expDecay) fit MRP:' if result.get('asymmetric_ok') else 'Asymmetric (err*expDecay) fit FAILED') if result.get('asymmetric_ok'): print(f' MRP(0.5) = {result["formatted_asymmetric_mrp"][0]}') print(f' MRP(0.1) = {result["formatted_asymmetric_mrp"][1]}') print(f' MRP(0.01) = {result["formatted_asymmetric_mrp"][2]}') asym_fwhm = result.get('asymmetric_fwhm', float('nan')) if np.isfinite(asym_fwhm): print(f' Asymmetric FWHM = {asym_fwhm:.6f}') print() print('Histogram-based MRP:') print(f' MRP(0.5) = {result["formatted_histogram_mrp"][0]}') print(f' MRP(0.1) = {result["formatted_histogram_mrp"][1]}') print(f' MRP(0.01) = {result["formatted_histogram_mrp"][2]}') print('=' * 60) def on_load_selection(_): with out: window = _resolve_gaussian_window() if window is None: print('No active mass/charge selection is available yet.') else: left, right, source = window mrp_left_widget.value, mrp_right_widget.value = left, right tag = ' (auto-picked around tallest peak)' if source == 'auto' else '' print(f'Loaded Gaussian MRP window: ({left:.4f}, {right:.4f}){tag}') def on_gaussian_mrp(_): gaussian_mrp_button.disabled = True with out: window = _resolve_gaussian_window() if window is None: print('Set MRP left/right or draw a selection first.') else: left, right, source = window mrp_left_widget.value, mrp_right_widget.value = left, right if source == 'auto': print(f'Auto-selected MRP window around tallest peak: ({left:.4f}, {right:.4f})') result = gaussian_mrp_report( _resolve_hist_array(), left, right, bin_size=0.001, ) if result is None: print('Gaussian MRP: insufficient data in selected range') else: _print_gaussian_report(result) gaussian_mrp_button.disabled = False # Create a button widget to trigger the function button_plot = widgets.Button(description='Plot') def on_button_click(_, variables, selector): # Disable the button while the code is running button_plot.disabled = True # Get the values from the widgets bin_size_value = bin_size_widget.value log_value = log_widget.value grid_value = grid_widget.value mode_value = mode_widget.value target_value = target_mode.value prominence_value = prominence_widget.value distance_value = distance_widget.value percent_value = percent_widget.value figname_value = figname_widget.value lim_value = lim_widget.value figure_size = (figure_mc_size_x.value, figure_mc_size_y.value) with out: # Capture the output within the 'out' widget out.clear_output() # Clear any previous output # Call the function if target_value == 'mc_uc': hist = variables.data['mc_uc (Da)'] elif target_value == 'tof_c': hist = variables.data['t_c (ns)'] elif target_value == 'mc': hist = variables.data['mc (Da)'] else: hist = variables.data['t (ns)'] mc_hist = mc_plot.AptHistPlotter(hist[hist < lim_value], variables) mc_hist.plot_histogram( bin_width=bin_size_value, normalize=mode_value, label='mc', steps='stepfilled', log=log_value, grid=grid_value, fig_size=figure_size, ) peak_warning = None if mode_value != 'normalized': try: mc_hist.find_peaks_and_widths( prominence=prominence_value, distance=distance_value, percent=percent_value ) except Exception as exc: peak_warning = f'peak detector raised {type(exc).__name__}: {exc}' if peak_warning is None and (mc_hist.peaks is None or len(mc_hist.peaks) == 0): peak_warning = ( f'no peaks satisfy prominence={prominence_value} and distance={distance_value}' ) if peak_warning is None: if plot_peak.value: try: mc_hist.plot_peaks() except Exception as exc: peak_warning = f'plot_peaks failed: {type(exc).__name__}: {exc}' try: mc_hist.plot_hist_info_legend( label='mc', mrp_all=mrp_all_widget.value, background=None, loc='right' ) except Exception as exc: peak_warning = f'plot_hist_info_legend failed: {type(exc).__name__}: {exc}' if background_widget.value is not None: try: mc_hist.plot_background(mode=background_widget.value) except Exception as exc: print(f'Background fit "{background_widget.value}" failed: ' f'{type(exc).__name__}: {exc}') try: mc_hist.selector(selector=selector) # rect, peak_x, range except Exception as exc: if peak_warning is None: peak_warning = f'selector "{selector}" failed: {type(exc).__name__}: {exc}' if save.value: try: mc_hist.save_fig(label=target_value, fig_name=figname_value) except Exception as exc: print(f'Saving figure failed: {type(exc).__name__}: {exc}') if peak_warning is not None: print('=============================') print('Histogram was plotted, but peak finding did not succeed.') print(f'Reason: {peak_warning}.') print('No peaks are available. Try lowering "Prominence" or "Distance" and plot again.') print('=============================') # Enable the button when the code is finished button_plot.disabled = False button_plot.on_click(lambda b: on_button_click(b, variables, selector)) load_selection_button.on_click(on_load_selection) gaussian_mrp_button.on_click(on_gaussian_mrp) widget_container = widgets.VBox( [ widgets.HBox([widgets.Label(value='Target:', layout=label_layout), target_mode]), widgets.HBox([widgets.Label(value='Bin Size:', layout=label_layout), bin_size_widget]), widgets.HBox([widgets.Label(value='Log:', layout=label_layout), log_widget]), widgets.HBox([widgets.Label(value='Grid:', layout=label_layout), grid_widget]), widgets.HBox([widgets.Label(value='Normalize:', layout=label_layout), mode_widget]), widgets.HBox([widgets.Label(value='Prominence:', layout=label_layout), prominence_widget]), widgets.HBox([widgets.Label(value='Distance:', layout=label_layout), distance_widget]), widgets.HBox([widgets.Label(value='Lim:', layout=label_layout), lim_widget]), widgets.HBox([widgets.Label(value='Percent:', layout=label_layout), percent_widget]), widgets.HBox([widgets.Label(value='MRP all:', layout=label_layout), mrp_all_widget]), widgets.HBox([widgets.Label(value='Plot peak:', layout=label_layout), plot_peak]), widgets.HBox([widgets.Label(value='Background:', layout=label_layout), background_widget]), widgets.HBox([widgets.Label(value='Save:', layout=label_layout), save]), widgets.HBox([widgets.Label(value='Fig name:', layout=label_layout), figname_widget]), widgets.HBox( [widgets.Label(value='Fig size:', layout=label_layout), widgets.HBox([figure_mc_size_x, figure_mc_size_y])] ), widgets.HBox( [widgets.Label(value='MRP range:', layout=label_layout), widgets.HBox([mrp_left_widget, mrp_right_widget])] ), widgets.HBox([load_selection_button, gaussian_mrp_button]), widgets.HBox([button_plot]), ] ) display(widget_container) display(out)