123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541 |
- namespace OINA.Extender.WPF.Testharness
- {
- using System;
- using System.Collections.ObjectModel;
- using System.ComponentModel;
- using System.Globalization;
- using System.Text;
- using System.Windows;
- using System.Windows.Controls;
- using System.Windows.Media;
- using System.Windows.Threading;
- using OINA.Extender.Acquisition.Quant;
- using OINA.Extender.Controls.Spectrum;
- /// <summary>
- /// Interaction logic for Calibrate.xaml
- /// </summary>
- public partial class Calibrate : Window, INotifyPropertyChanged
- {
- /// <summary>
- /// The quant calibration controller
- /// </summary>
- private readonly IQuantCalibrationController controller;
- /// <summary>
- /// The quant calibration settings
- /// </summary>
- private readonly IQuantCalibrationSettings settings;
- /// <summary>
- /// The current calibration element
- /// </summary>
- private int currentCalibrationElement;
- /// <summary>
- /// Flag to show if the use has been warned about insignificant calibration peak for a particular run
- /// </summary>
- private bool userWarnedOnCalibrationPeakInsignificant;
- /// <summary>
- /// Gets or sets the current calibration element
- /// </summary>
- public int CurrentCalibrationElement
- {
- get
- {
- return this.currentCalibrationElement;
- }
- set
- {
- if (value == this.currentCalibrationElement)
- {
- return;
- }
- this.currentCalibrationElement = value;
- this.OnPropertyChanged(nameof(this.CurrentCalibrationElement));
- }
- }
- /// <summary>
- /// The list of allowed calibration elements
- /// </summary>
- private ReadOnlyCollection<int> allowedCalibrationElements;
- /// <summary>
- /// Gets or sets the list of allowed calibration elements
- /// </summary>
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly", Justification = "By design.")]
- public ReadOnlyCollection<int> AllowedCalibrationElements
- {
- get
- {
- return this.allowedCalibrationElements;
- }
- set
- {
- if (value == this.allowedCalibrationElements)
- {
- return;
- }
- this.allowedCalibrationElements = value;
- this.OnPropertyChanged(nameof(this.AllowedCalibrationElements));
- }
- }
- /// <summary>
- /// Calibrate constructor
- /// </summary>
- public Calibrate()
- {
- this.InitializeComponent();
- this.CalibrateElementCombo.DataContext = this;
- this.settings = OIHelper.QuantCalibrationSettings;
- // use the same Ed settings as spectrum acquistion
- var spectrumSettings = OIHelper.EdSpectrumSettings;
- this.settings.EdSettings.CopyFrom(spectrumSettings.EdSettings);
- this.AllowedCalibrationElements = this.settings.Capabilities.AllowedCalibrationElements;
- this.CurrentCalibrationElement = this.settings.CalibrationElementAtomicNumber;
- if (this.settings.CalibrationMode == QuantCalibrationMode.EnergyCalibration)
- {
- this.RoutineCombobox.SelectedIndex = 0;
- this.SettingsButton.Visibility = Visibility.Hidden;
- }
- else if (this.settings.CalibrationMode == QuantCalibrationMode.BeamMeasurement)
- {
- this.RoutineCombobox.SelectedIndex = 1;
- this.SettingsButton.Visibility = Visibility.Visible;
- }
- this.settings.PropertyChanged += this.OnSettingsPropertyChanged;
- this.settings.Capabilities.PropertyChanged += this.OnCapabilitiesPropertyChanged;
- this.CurrentStatusTextbox.Text = string.Empty;
- this.controller = OIHelper.QuantCalibrationController;
- // beam measurement
- this.controller.BeamMeasurementAcquisitionStarted += this.OnBeamMeasurementAcquisitionStarted;
- this.controller.BeamMeasurementAcquisitionFinished += this.OnBeamMeasurementAcquisitionFinished;
- this.controller.BeamMeasurementResult += this.OnBeamMeasurementResult;
- this.controller.BeamMeasurementFinished += this.OnBeamMeasurementFinished;
- // common
- this.controller.CalibrationPeakInsignificant += this.OnCalibrationPeakInsignificant;
- // energy calibration
- this.controller.EnergyCalibrationAcquisitionStarted += this.OnEnergyCalibrationAcquisitionStarted;
- this.controller.EnergyCalibrationAcquisitionFinished += this.OnEnergyCalibrationAcquisitionFinished;
- this.controller.EnergyCalibrationFinished += this.OnEnergyCalibrationFinished;
- this.controller.PropertyChanged += this.OnControllerPropertyChanged;
- }
- /// <summary>
- /// The calibration routine has changed, update the settings
- /// </summary>
- /// <param name="sender">The sender</param>
- /// <param name="e">The event args</param>
- private void RoutineCombobox_SelectionChanged(object sender, SelectionChangedEventArgs e)
- {
- if (this.RoutineCombobox.SelectedIndex == 0)
- {
- this.SettingsButton.Visibility = Visibility.Hidden;
- this.settings.CalibrationMode = QuantCalibrationMode.EnergyCalibration;
- }
- else
- {
- this.SettingsButton.Visibility = Visibility.Visible;
- this.settings.CalibrationMode = QuantCalibrationMode.BeamMeasurement;
- }
- }
- /// <summary>
- /// Handle quant calibration settings property changed notifications
- /// </summary>
- /// <param name="sender">The sender</param>
- /// <param name="e">The event args</param>
- private void OnSettingsPropertyChanged(object sender, PropertyChangedEventArgs e)
- {
- if (e.PropertyName == nameof(this.settings.CalibrationElementAtomicNumber))
- {
- this.CurrentCalibrationElement = this.settings.CalibrationElementAtomicNumber;
- }
- else if (e.PropertyName == nameof(this.settings.CalibrationMode))
- {
- if (this.settings.CalibrationMode == QuantCalibrationMode.EnergyCalibration)
- {
- this.RoutineCombobox.SelectedIndex = 0;
- }
- else if (this.settings.CalibrationMode == QuantCalibrationMode.BeamMeasurement)
- {
- this.RoutineCombobox.SelectedIndex = 1;
- }
- }
- }
- /// <summary>
- /// Handle quant calibration capabilites property changed notifications
- /// </summary>
- /// <param name="sender">The sender</param>
- /// <param name="e">The event args</param>
- private void OnCapabilitiesPropertyChanged(object sender, PropertyChangedEventArgs e)
- {
- if (e.PropertyName == nameof(this.settings.Capabilities.AllowedCalibrationElements))
- {
- this.AllowedCalibrationElements = this.settings.Capabilities.AllowedCalibrationElements;
- this.CurrentCalibrationElement = this.settings.CalibrationElementAtomicNumber;
- }
- }
- /// <summary>
- /// Handle property changed notifications from the controller
- /// </summary>
- /// <param name="sender">sender</param>
- /// <param name="e">PropertyChangedEventArgs</param>
- private void OnControllerPropertyChanged(object sender, PropertyChangedEventArgs e)
- {
- switch (e.PropertyName)
- {
- case nameof(this.controller.CurrentCalibrationSpectrum):
- // execute on UI thread
- this.Dispatcher.BeginInvoke(() =>
- {
- this.spectrumViewer.Spectrum = this.controller.CurrentCalibrationSpectrum;
- });
- break;
- case nameof(this.controller.PercentageComplete):
- // execute on UI thread
- this.Dispatcher.BeginInvoke(() =>
- {
- this.CalibrateProgressBar.Value = this.controller.PercentageComplete;
- this.EstimateTimeLabel.Content = this.controller.EstimatedTimeToCompletion.Ticks == 0 ? string.Empty : this.controller.EstimatedTimeToCompletion.ToString(@"hh\:mm\:ss", CultureInfo.CurrentCulture);
- });
- break;
- case nameof(this.controller.CurrentEnergyWindow):
- var window = this.controller.CurrentEnergyWindow;
- if (window != null)
- {
- var windowColor = Color.FromArgb(255, 255, 0, 119);
- var windows = new EnergyWindow[]
- {
- new EnergyWindow(window.LowerEnergy, window.UpperEnergy, windowColor),
- };
- // execute on UI thread
- this.Dispatcher.BeginInvoke(() =>
- {
- this.spectrumViewer.EnergyWindowsSource = windows;
- });
- }
- break;
- case nameof(this.controller.IsIdle):
- // execute on UI thread
- this.Dispatcher.BeginInvoke(() =>
- {
- if (this.controller.IsIdle)
- {
- this.CurrentStatusTextbox.Text = @"Data acquisition is Idle.";
- }
- else
- {
- this.CurrentStatusTextbox.Text = @"Data is currently acquiring.";
- }
- });
- break;
- }
- }
- /// <summary>
- /// Validate the settings and start the calibration routine
- /// </summary>
- /// <param name="sender">The sender</param>
- /// <param name="e">The event args</param>
- private void StartCalibrateButton_Click(object sender, EventArgs e)
- {
- this.settings.CalibrationElementAtomicNumber = this.CurrentCalibrationElement;
- var results = this.settings.Validate();
- if (!results.IsValid)
- {
- string message = string.Format(CultureInfo.CurrentCulture, @"The settings are not valid{0}", Environment.NewLine);
- message += string.Join(Environment.NewLine, results.ValidationErrors);
- MessageBox.Show(message, @"Invalid settings");
- return;
- }
- this.CalibrateProgressBar.Value = 0;
- this.controller.StartCalibration(this.settings);
- this.userWarnedOnCalibrationPeakInsignificant = false;
- }
- /// <summary>
- /// Stops the calibration routine
- /// </summary>
- /// <param name="sender">The sender</param>
- /// <param name="e">The event args</param>
- private void StopCalibrateButton_Click(object sender, EventArgs e)
- {
- this.controller.StopCalibration();
- }
- /// <summary>
- /// The beam measurement acquisition has started
- /// </summary>
- /// <param name="sender">The sender</param>
- /// <param name="e">The event args</param>
- private void OnBeamMeasurementAcquisitionStarted(object sender, EventArgs e)
- {
- this.EnableCalibrationControls(false);
- }
- /// <summary>
- /// The beam measurement acquisition has finished
- /// </summary>
- /// <param name="sender">The sender</param>
- /// <param name="e">The event args</param>
- private void OnBeamMeasurementAcquisitionFinished(object sender, CalibrationAcquisitionFinishedEventArgs e)
- {
- if (!e.Success)
- {
- // Acquisition was stopped by the user, or an error occured
- if (e.Error != null)
- {
- string message = string.Format(CultureInfo.CurrentCulture, @"Beam measurement acquisition did not complete successfully {0} {1}", Environment.NewLine, e.Error.Message);
- MessageBox.Show(message, @"Beam measurement");
- }
- e.Cancel = true; // should already be set to true
- this.EnableCalibrationControls(true);
- }
- }
- /// <summary>
- /// The beam measurement has been compared to the previous measurement
- /// </summary>
- /// <param name="sender">The sender</param>
- /// <param name="e">The event args</param>
- private void OnBeamMeasurementResult(object sender, BeamMeasurementResultEventArgs e)
- {
- string content = string.Empty;
- if (e.Status == BeamMeasurementResultStatus.MeasurementDifference)
- {
- content = string.Format(CultureInfo.CurrentCulture, @"The beam current is {0:0.00}% of the last value", e.Percent);
- }
- else if (e.Status == BeamMeasurementResultStatus.MeasurementOK)
- {
- content = @"Measurement OK";
- }
- else
- {
- throw new InvalidOperationException("Unexpected result status");
- }
- string message = string.Format(CultureInfo.CurrentCulture, @"Do you want to save the beam measurement? {0}{0}{1}", Environment.NewLine, content);
- if (MessageBox.Show(message, @"Beam measurement", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.No)
- {
- e.Cancel = true;
- this.EnableCalibrationControls(true);
- }
- }
- /// <summary>
- /// The beam measurement has been saved
- /// </summary>
- /// <param name="sender">The sender</param>
- /// <param name="e">The event args</param>
- private void OnBeamMeasurementFinished(object sender, CalibrationFinishedEventArgs e)
- {
- if (e.Error != null)
- {
- MessageBox.Show(string.Format(CultureInfo.CurrentCulture, @"Failed to perform beam measurement:{0}{0}{1}", Environment.NewLine, e.Error.Message), @"Beam measurement", MessageBoxButton.OK, MessageBoxImage.Exclamation);
- }
- this.EnableCalibrationControls(true);
- }
- /// <summary>
- /// The calibration peak is not significant.
- /// Can occur during both Beam measurement and Energy calibration
- /// </summary>
- /// <param name="sender">The sender</param>
- /// <param name="e">The event args</param>
- private void OnCalibrationPeakInsignificant(object sender, CalibrationPeakInsignificantEventArgs e)
- {
- if (this.userWarnedOnCalibrationPeakInsignificant)
- {
- return;
- }
- var message = new StringBuilder();
- message.AppendFormat(
- CultureInfo.CurrentCulture,
- @"The calibration peak is not significantly greater than the background:{0}Peak counts: {1}{0}Low energy background: {2}{0}high energy background: {3}{0}{0}",
- Environment.NewLine,
- e.PeakCounts,
- e.LowEnergyBackgroundCounts,
- e.HighEnergyBackgroundCounts);
- message.AppendFormat(CultureInfo.CurrentCulture, @"The calibration process has been running for {0:hh\:mm\:ss}", e.ElapsedTime);
- if (e.EstimatedTimeToCompletion.TotalSeconds > 0)
- {
- message.AppendFormat(CultureInfo.CurrentCulture, @" and an estimated time to completion is {0:hh\:mm\:ss}. ", e.EstimatedTimeToCompletion);
- }
- message.AppendFormat(CultureInfo.CurrentCulture, @"{0}{0}The wrong element may have been selected. Would you like to continue?", Environment.NewLine);
- if (MessageBox.Show(message.ToString(), @"Quant optimization", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.No)
- {
- this.controller.StopCalibration();
- }
- this.userWarnedOnCalibrationPeakInsignificant = true;
- }
- /// <summary>
- /// The energy calibration acquisition has started
- /// </summary>
- /// <param name="sender">The sender</param>
- /// <param name="e">The event args</param>
- private void OnEnergyCalibrationAcquisitionStarted(object sender, EventArgs e)
- {
- this.EnableCalibrationControls(false);
- }
- /// <summary>
- /// The energy calibration acquisition has finished
- /// </summary>
- /// <param name="sender">The sender</param>
- /// <param name="e">The event args</param>
- private void OnEnergyCalibrationAcquisitionFinished(object sender, CalibrationAcquisitionFinishedEventArgs e)
- {
- if (e.Success)
- {
- string message = @"Perform Energy calibration using the acquired spectra?";
- if (MessageBox.Show(message, @"Energy calibration", MessageBoxButton.YesNo) == MessageBoxResult.No)
- {
- e.Cancel = true;
- this.EnableCalibrationControls(true);
- }
- }
- else
- {
- // Acquisition was stopped by the user, or an error occured
- if (e.Error != null)
- {
- string message = string.Format(CultureInfo.CurrentCulture, @"Energy calibration acquisition did not complete successfully {0} {1}", Environment.NewLine, e.Error.Message);
- MessageBox.Show(message, @"Energy calibration");
- }
- e.Cancel = true; // should already be set to true
- this.EnableCalibrationControls(true);
- }
- }
- /// <summary>
- /// The Energy calibration has been saved
- /// </summary>
- /// <param name="sender">The sender</param>
- /// <param name="e">The event args</param>
- private void OnEnergyCalibrationFinished(object sender, CalibrationFinishedEventArgs e)
- {
- if (e.Error != null)
- {
- MessageBox.Show(string.Format(CultureInfo.CurrentCulture, @"Failed to perform energy calibration:{0}{0}{1}", Environment.NewLine, e.Error.Message), @"Energy calibration", MessageBoxButton.OK, MessageBoxImage.Exclamation);
- }
- this.EnableCalibrationControls(true);
- }
- /// <summary>
- /// Display the settings for Beam measurement
- /// </summary>
- /// <param name="sender">The sender</param>
- /// <param name="e">The event args</param>
- private void SettingsButton_Click(object sender, RoutedEventArgs e)
- {
- new BeamMeasurementSettings { WindowStartupLocation = WindowStartupLocation.CenterScreen }.Show();
- }
- /// <summary>
- /// Unsubscribe from the events
- /// </summary>
- /// <param name="e">The event args</param>
- protected override void OnClosing(CancelEventArgs e)
- {
- this.settings.PropertyChanged -= this.OnSettingsPropertyChanged;
- this.settings.Capabilities.PropertyChanged -= this.OnCapabilitiesPropertyChanged;
- this.controller.BeamMeasurementAcquisitionStarted -= this.OnBeamMeasurementAcquisitionStarted;
- this.controller.BeamMeasurementAcquisitionFinished -= this.OnBeamMeasurementAcquisitionFinished;
- this.controller.BeamMeasurementResult -= this.OnBeamMeasurementResult;
- this.controller.BeamMeasurementFinished -= this.OnBeamMeasurementFinished;
- this.controller.CalibrationPeakInsignificant -= this.OnCalibrationPeakInsignificant;
- this.controller.EnergyCalibrationAcquisitionStarted -= this.OnEnergyCalibrationAcquisitionStarted;
- this.controller.EnergyCalibrationAcquisitionFinished -= this.OnEnergyCalibrationAcquisitionFinished;
- this.controller.EnergyCalibrationFinished -= this.OnEnergyCalibrationFinished;
- this.controller.PropertyChanged -= this.OnControllerPropertyChanged;
- base.OnClosing(e);
- }
- /// <summary>
- /// Enable/disable the controls for starting the acquisition
- /// </summary>
- /// <param name="enable">Whether to enable or not</param>
- private void EnableCalibrationControls(bool enable)
- {
- this.Dispatcher.BeginInvoke(
- () =>
- {
- this.StartCalibrateButton.IsEnabled = enable;
- this.RoutineCombobox.IsEnabled = enable;
- this.SettingsButton.IsEnabled = enable;
- this.CalibrateElementCombo.IsEnabled = enable;
- this.StopCalibrateButton.IsEnabled = !enable;
- if (enable)
- {
- this.EstimateTimeLabel.Content = string.Empty;
- }
- });
- }
- #region INotifyPropertyChanged Members
- /// <summary>
- /// PropertyChanged event
- /// </summary>
- public event PropertyChangedEventHandler PropertyChanged;
- private void OnPropertyChanged(string propertyName)
- {
- this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
- }
- #endregion
- }
- }
|