namespace OINA.Extender.WPF.Testharness { using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; using System.ComponentModel; using System.Drawing; using System.Drawing.Imaging; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.Serialization; using System.Text; using System.Threading; using System.Windows; using System.Windows.Controls; using System.Windows.Resources; using System.Windows.Threading; using OINA.Extender.Acquisition; using OINA.Extender.Acquisition.Ed; using OINA.Extender.Controls; using OINA.Extender.Controls.Spectrum; using OINA.Extender.Data.Ed; using OINA.Extender.Data.Image; using OINA.Extender.Processing; using OINA.Extender.Processing.Quant; using WindowsMedia = System.Windows.Media; /// /// Interaction logic for MainWindow.xaml /// public partial class MainWindow : Window, INotifyPropertyChanged { /// /// List of ElectronImage objects /// private readonly List electronImageList = new List(); /// /// StringBuilder object /// private StringBuilder sb = new StringBuilder(); /// /// The element dictionary /// private Dictionary elementDictionary; /// /// The current spectrum acquisitions /// private Dictionary currentSpectrumAcquisitions; /// /// Acquisition status timer /// private DispatcherTimer acquisitionStatusTimer = null; /// /// Identify elements timer /// private DispatcherTimer identifyElementsTimer = null; /// /// The compare spectra ids /// private ObservableCollection compareSpectra; /// /// The comparison spectra /// private List comparisonSpectra; /// /// Gets the comparison spectra. /// /// /// The comparison spectra. /// public IList ComparisonSpectra { get { return this.comparisonSpectra; } } /// /// Gets the compare spectra ids. /// /// /// The compare spectra ids. /// public ObservableCollection CompareSpectra { get { return this.compareSpectra; } } /// /// Gets the element dictionary. /// /// /// The element dictionary. /// public Dictionary ElementDictionary { get { return this.elementDictionary; } } /// /// Gets a value indicating whether this instance is acquiring spectrum. /// /// /// true if this instance is acquiring spectrum; otherwise, false. /// public bool IsAcquiringSpectrum { get { return OIHelper.EdSpectrumAcquisitionController.IsAcquiring; } } /// /// The currently selected Exclusion element /// private int currentExclusionElement; /// /// Gets or sets currently selected Exclusion element /// public int CurrentExclusionElement { get { return this.currentExclusionElement; } set { if (value == this.currentExclusionElement) { return; } this.currentExclusionElement = value; this.PropertyChanged(this, new PropertyChangedEventArgs("CurrentExclusionElement")); } } /// /// The currently selected Deconvolution element /// private int currentDeconvolutionElement; /// /// Gets or sets currently selected Deconvolution element /// public int CurrentDeconvolutionElement { get { return this.currentDeconvolutionElement; } set { if (value == this.currentDeconvolutionElement) { return; } this.currentDeconvolutionElement = value; this.PropertyChanged(this, new PropertyChangedEventArgs("CurrentDeconvolutionElement")); } } /// /// MainWindow Constructor /// public MainWindow() { Application.Current.DispatcherUnhandledException += this.OnCurrentOnDispatcherUnhandledException; this.compareSpectra = new ObservableCollection(); this.currentSpectrumAcquisitions = new Dictionary(); this.InitializeComponent(); this.ExcludeElementCombo.DataContext = this; this.DeconvolutionElementCombo.DataContext = this; this.LoadComparisonSpectra(); // Binding spectrum acquisition controller events OIHelper.EdSpectrumAcquisitionController.ExperimentStarted += this.OnEdSpectrumExperimentStarted; OIHelper.EdSpectrumAcquisitionController.ExperimentFinished += this.OnEdSpectrumExperimentFinished; // Binding image acquisition controller events OIHelper.ImageAcquisitionController.ExperimentStarted += this.OnImageExperimentStarted; OIHelper.ImageAcquisitionController.ExperimentFinished += this.OnImageExperimentFinished; // Set OutputRate and DeadTime DataContext this.tbOutputRate.DataContext = OIHelper.MonitoringController.EdStatus.Values.First(); this.tbDeadTime.DataContext = OIHelper.MonitoringController.EdStatus.Values.First(); // Initial UI contents this.InitialSpectrumSettingsContent(); this.InitialSpectrumViewer(); this.InitialImageSettingsContent(); this.InitialTimers(); this.InitialProcessingSettingsContent(); this.InitialiseElementDictionary(); this.IncludedListBox.DataContext = this.PeriodicTable; this.UnsetListBox.DataContext = this.PeriodicTable; this.ExcludedListBox.DataContext = this.PeriodicTable; this.TableBackColorCombo.DataContext = this.PeriodicTable; var clearCompareSpectra = new MenuItem { Header = @"Clear Compare Spectra", Visibility = Visibility.Visible }; clearCompareSpectra.Click += this.OnClearCompareSpectra; this.spectrumViewer.ContextMenu.Items.Add(clearCompareSpectra); this.spectrumViewer.ContextMenu.UpdateLayout(); this.compareSpectrumColor.SelectedColor = GetRandomColor(); this.SortListBox(); } /// /// Handles the DispatcherUnhandledException. /// Specifically, here it handles the LicenseCheckExceptions which are wrapped in the DispatcherUnhandledException. /// Shutdowns application when a invalid or missing licence has been found in LicenseCheck.cs. /// /// Object /// Event private void OnCurrentOnDispatcherUnhandledException(object obj, DispatcherUnhandledExceptionEventArgs args) { LicenseCheckException ex = args.Exception.InnerException as LicenseCheckException; if (ex != null) { MessageBox.Show(@"This application will shutdown, as a valid license is not available." + Environment.NewLine + ex.Message, @"Error Message", MessageBoxButton.OK, MessageBoxImage.Error); args.Handled = true; Application.Current.Shutdown(); } } /// /// Gets the random color. /// /// A random color private static WindowsMedia.Color GetRandomColor() { Random randomGen = new Random(); byte[] values = new byte[3]; randomGen.NextBytes(values); PropertyInfo[] info = typeof(WindowsMedia.Colors).GetProperties(); PropertyInfo colorInfo = info[randomGen.Next(info.Count())]; WindowsMedia.Color randomColor = (WindowsMedia.Color)WindowsMedia.ColorConverter.ConvertFromString(colorInfo.Name); return randomColor; } #region Event handlers /// /// Called when [clear compare spectra menu item is selected]. /// /// The sender. /// The instance containing the event data. private void OnClearCompareSpectra(object sender, RoutedEventArgs e) { this.spectrumViewer.ClearComparisonSpectra(); this.compareSpectra.Clear(); } /// /// Acquisition status timer event handler /// /// sender object /// EventArgs private void OnAcquisitionStatusTimer_Tick(object sender, EventArgs e) { if (OIHelper.EdSpectrumAcquisitionController.IsAcquiring || OIHelper.ImageAcquisitionController.IsAcquiring) { this.lbAcquisitionStatus.Visibility = System.Windows.Visibility.Visible; } else { this.lbAcquisitionStatus.Visibility = System.Windows.Visibility.Hidden; } } /// /// Indentify elements timer event handler /// /// sender object /// EventArgs private void OnIdentifyElementsTimer_Tick(object sender, EventArgs e) { this.DoAutoID(); } /// /// Called when [ed spectrum experiment started]. /// /// The sender. /// The instance containing the event data. private void OnEdSpectrumExperimentStarted(object sender, AcquisitionStartedEventArgs e) { var edSpectrum = e.Value; // execute on ui thread this.Dispatcher.BeginInvoke((Action)delegate { this.spectrumViewer.Spectrum = edSpectrum; // Clear periodic table elements this.PeriodicTable.ClearAll(); // Update Known Elements this.PeriodicTable.IncludeElements(OIHelper.AutoIdSettings.KnownElements.ToArray()); }); this.identifyElementsTimer.Tick += this.OnIdentifyElementsTimer_Tick; this.identifyElementsTimer.Start(); edSpectrum.PropertyChanged += this.OnPropertyChanged; } /// /// Called when [image experiment started]. /// /// The sender. /// The instance containing the event data. private void OnImageExperimentStarted(object sender, AcquisitionStartedEventArgs e) { // execute on UI thread this.Dispatcher.BeginInvoke((Action)delegate { this.imageViewer.DisplayImage = e.Value[0]; }); } /// /// OnExperimentFinished /// /// sender object /// The instance containing the event data. private void OnEdSpectrumExperimentFinished(object sender, AcquisitionFinishedEventArgs e) { e.Value.PropertyChanged -= this.OnPropertyChanged; this.identifyElementsTimer.Tick -= this.OnIdentifyElementsTimer_Tick; this.identifyElementsTimer.Stop(); // execute on UI thread this.Dispatcher.BeginInvoke((Action)delegate { this.DoAutoID(); this.UpdatePeriodicTable(); this.DoQuant(); if (this.currentSpectrumAcquisitions.ContainsKey(e.Value)) { this.AcquisitionQueueListBox.Items.Remove(this.currentSpectrumAcquisitions[e.Value]); this.currentSpectrumAcquisitions.Remove(e.Value); } // *** If this is the last experiment, call EndMultipleAcquisition on the Acquisition // *** controller, to re-enable external scan switching if (!this.currentSpectrumAcquisitions.Any()) { OIHelper.EdSpectrumAcquisitionController.EndMultipleAcquisition(); } }); } /// /// Called when [image experiment finished]. /// /// The sender. /// The instance containing the event data. private void OnImageExperimentFinished(object sender, AcquisitionFinishedEventArgs e) { // execute on UI thread this.Dispatcher.BeginInvoke((Action)delegate { e.Value.ToList().ForEach(i => { this.electronImageList.Remove(i); this.ImageAcquisitionQueueListBox.Items.Remove(i.Label); }); }); } /// /// OnPropertyChanged /// /// Event source /// Event arguments private void OnPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { var edSpectrum = sender as IEdSpectrum; if (e.PropertyName == @"RealTimeSeconds") { this.Dispatcher.Invoke(new Action(delegate { this.textRealTimeSeconds.Text = Math.Round(edSpectrum.RealTimeSeconds, 3).ToString(CultureInfo.InvariantCulture); })); } else if (e.PropertyName == @"LiveTimeSeconds") { this.Dispatcher.Invoke(new Action(delegate { this.textLiveTimeSeconds.Text = Math.Round(edSpectrum.LiveTimeSeconds, 3).ToString(CultureInfo.InvariantCulture); })); } } /// /// Handles the CollectionChanged event of the IncludedElements. /// /// The source of the event. /// The instance containing the event data. private void IncludedElements_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { var spectrum = this.spectrumViewer.Spectrum; // Update peak labels for included elements if (spectrum != null) { switch (e.Action) { case NotifyCollectionChangedAction.Add: foreach (int i in e.NewItems.Cast()) { spectrum.SetIdentifiedElement(i, true); } break; case NotifyCollectionChangedAction.Remove: foreach (int i in e.OldItems.Cast()) { spectrum.SetIdentifiedElement(i, false); } break; default: break; } this.UpdateSpectrumPeakLabels(); } } /// /// Update current spectrum peak labels /// private void UpdateSpectrumPeakLabels() { try { OIHelper.EdSpectrumProcessing.UpdatePeakLabels(this.spectrumViewer.Spectrum, null); } catch (ArgumentNullException) { } catch (InvalidOperationException) { } } /// /// Sort Listbox /// private void SortListBox() { this.IncludedListBox.Items.SortDescriptions.Add(new SortDescription(string.Empty, ListSortDirection.Ascending)); this.ExcludedListBox.Items.SortDescriptions.Add(new SortDescription(string.Empty, ListSortDirection.Ascending)); } #endregion #region Update UI Status /// /// Initialise spectrum acquisition settings /// private void InitialSpectrumSettingsContent() { if (OIHelper.EdSpectrumSettings.EdCapabilities.HasHardwareConnection) { this.tbSpectrumLabel.Text = @"Spectrum 1"; this.cbAcquisitionMode.Items.Add(EdAcquireMode.LiveTime); this.cbAcquisitionMode.Items.Add(EdAcquireMode.RealTime); this.cbAcquisitionMode.SelectedIndex = 0; this.tbAcquisitionTime.Text = @"10000"; this.cbProcessTime.ItemsSource = OIHelper.EdSpectrumSettings.EdCapabilities.AllowedProcessTimes; this.cbProcessTime.SelectedIndex = 3; this.cbEnergyRange.ItemsSource = OIHelper.EdSpectrumSettings.EdCapabilities.AllowedEnergyRanges; this.cbEnergyRange.SelectedIndex = 1; this.cbNumOfChannels.ItemsSource = OIHelper.EdSpectrumSettings.EdCapabilities.AllowedNumberOfChannels; this.cbNumOfChannels.SelectedIndex = 1; } } /// /// Initialise SpectrumViewer /// private void InitialSpectrumViewer() { this.spectrumViewer.IsXAxisAutoScaleEnabled = false; this.spectrumViewer.IsYAxisAutoScaleEnabled = true; } /// /// InitialImageSettingsContent /// private void InitialImageSettingsContent() { var settings = OIHelper.ImageSettings; if (settings.ImageCapabilities.HasHardwareConnection) { this.cbImageScanSize.ItemsSource = OIHelper.GetScanSizes( settings.ScanCapabilities.MinimumPixelSize, settings.ScanCapabilities.MaximumPixelSize); this.cbImageScanSize.SelectedIndex = this.cbImageScanSize.Items.Count > 4 ? 4 : this.cbImageScanSize.Items.Count - 1; this.cbInputSignal.ItemsSource = settings.ImageCapabilities.AllowedInputSources; this.cbInputSignal.SelectedIndex = 0; this.tbNumberOfFrames.Text = @"1"; this.tbDwellTime.Text = @"40"; } } /// /// Initialize Processing settings /// private void InitialProcessingSettingsContent() { this.ExcludedListBox.DataContext = this; ((INotifyCollectionChanged)this.PeriodicTable.IncludedElements).CollectionChanged += this.IncludedElements_CollectionChanged; this.AllElementsRadioButton.IsChecked = true; this.CombinedElementTextBox.IsEnabled = false; this.CombinedElementTextBox.Text = @"8"; this.NumberOfIonsTextBox.IsEnabled = false; this.NumberOfIonsTextBox.Text = @"3.0"; this.IsCoatedCheckBox.IsChecked = OIHelper.SEMQuantSettings.SampleCoating.IsCoated; this.CoatingElementTextBox.IsEnabled = OIHelper.SEMQuantSettings.SampleCoating.IsCoated; this.CoatingElementTextBox.Text = OIHelper.SEMQuantSettings.SampleCoating.CoatingElement.ToString(CultureInfo.InvariantCulture); this.DensityTextBox.IsEnabled = OIHelper.SEMQuantSettings.SampleCoating.IsCoated; this.DensityTextBox.Text = OIHelper.SEMQuantSettings.SampleCoating.Density.ToString(CultureInfo.InvariantCulture); this.ThicknessTextBox.IsEnabled = OIHelper.SEMQuantSettings.SampleCoating.IsCoated; this.ThicknessTextBox.Text = OIHelper.SEMQuantSettings.SampleCoating.Thickness.ToString(CultureInfo.InvariantCulture); foreach (int i in OIHelper.SEMQuantSettings.DeconvolutionElements) { this.DeconvolutionElementListTextBox.Text += i.ToString(CultureInfo.InvariantCulture) + System.Environment.NewLine; } this.ThresholdingCheckBox.IsChecked = false; this.SigmaLevelTextBox.IsEnabled = false; this.SigmaLevelTextBox.Text = @"3.0"; } /// /// Initialises the element dictionary. /// private void InitialiseElementDictionary() { this.elementDictionary = new Dictionary(); for (int elementNo = 1; elementNo <= 103; elementNo++) { this.elementDictionary.Add(elementNo, this.PeriodicTable.LookupElementInfo(elementNo).ElementName); } this.EnableElementsList.DataContext = this; } /// /// Initialise acquisition timer /// private void InitialTimers() { this.acquisitionStatusTimer = new DispatcherTimer(); this.acquisitionStatusTimer.Tick += new EventHandler(this.OnAcquisitionStatusTimer_Tick); this.acquisitionStatusTimer.Interval = TimeSpan.FromMilliseconds(100); this.acquisitionStatusTimer.Start(); this.identifyElementsTimer = new DispatcherTimer(); this.identifyElementsTimer.Interval = TimeSpan.FromMilliseconds(1000); } /// /// Update the Periodic Table content after acquisition finished /// private void UpdatePeriodicTable() { this.PeriodicTable.IncludeElements(this.spectrumViewer.Spectrum.IdentifiedElements.ToArray()); } #endregion #region Menu items actions /// /// Exit application /// /// sender object /// RoutedEventArgs private void AppExit(object sender, RoutedEventArgs e) { Application.Current.Shutdown(); } /// /// Show detector control panel /// /// sender object /// RoutedEventArgs private void DetectorControl_Click(object sender, RoutedEventArgs e) { new DetectorControlPanel(OIHelper.EDDetectorControl) { Owner = this }.Show(); } /// /// Show microscope control panel /// /// sender object /// RoutedEventArgs private void MicroscopeControl_Click(object sender, RoutedEventArgs e) { new MicroscopeControlPanel { Owner = this }.Show(); } /// /// Calibrate Click event handler. /// /// sender /// RoutedEventArgs private void Calibrate_Click(object sender, RoutedEventArgs e) { new Calibrate { Owner = this }.Show(); } /// /// Auto ID settings Window /// /// sender object /// RoutedEventArgs private void AutoIdSetting_Click(object sender, RoutedEventArgs e) { new AutoIdSettings { Owner = this }.Show(); } /// /// Handles the Click event of the PeriodicTableSettings menu item. /// /// The source of the event. /// The instance containing the event data. private void PeriodicTableSettings_Click(object sender, RoutedEventArgs e) { new PeriodicTableVisualSettings { Owner = this, ShowInTaskbar = false }.Show(); } /// /// Handles the Click event of the SpectrumViewerSettings menu item. /// /// The source of the event. /// The instance containing the event data. private void SpectrumViewerSettings_Click(object sender, RoutedEventArgs e) { new SpectrumViewerVisualSettings { Owner = this, ShowInTaskbar = false }.Show(); } /// /// Handles the Click event of the ImageViewerSettings menu item. /// /// The source of the event. /// The instance containing the event data. private void ImageViewerSettings_Click(object sender, RoutedEventArgs e) { new ImageViewerVisualSettings { Owner = this, ShowInTaskbar = false }.Show(); } /// /// Handles the Click event of the ElementComboSettings menu item. /// /// The source of the event. /// The instance containing the event data. private void ElementComboSettings_Click(object sender, RoutedEventArgs e) { new ElementComboVisualSettings { Owner = this, ShowInTaskbar = false }.Show(); } /// /// Handles the Click event of the BC Dialog settings menu item. /// /// The source of the event. /// The instance containing the event data. private void BCDialogSettings_Click(object sender, RoutedEventArgs e) { new BCDialogVisualSettings { Owner = this, ShowInTaskbar = false }.Show(); } /// /// Handles the Click event of the DetailDialogsVisualStyles control. /// /// The source of the event. /// The instance containing the event data. private void DetailsDialogVisualStyles_Click(object sender, RoutedEventArgs e) { new DetailDialogVisualSettings { Owner = this, ShowInTaskbar = false }.Show(); } /// /// Handles the Click event of the elementComboVisualSettingsToolStripMenuItem control. /// /// The source of the event. /// instance containing the event data. private void ExportSpectrumAs_Click(object sender, RoutedEventArgs e) { try { short width = (short)this.spectrumViewer.ActualWidth; short height = (short)this.spectrumViewer.ActualHeight; Bitmap bitmap = OIHelper.EdSpectrumProcessing.CreateBitmap(this.spectrumViewer.Spectrum, width, height); using (System.Windows.Forms.SaveFileDialog exportSpectrumDialog = new System.Windows.Forms.SaveFileDialog()) { exportSpectrumDialog.Filter = @"Bitmap (*.bmp)|*.bmp|PNG (*.png)|*.png|TIFF (*.tif)|*.tif|JPEG (*.jpg)|*.jpg"; exportSpectrumDialog.Title = @"Export Spectrum As..."; if (exportSpectrumDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) { switch (exportSpectrumDialog.FilterIndex) { case 1: bitmap.Save(exportSpectrumDialog.FileName, ImageFormat.Bmp); break; case 2: bitmap.Save(exportSpectrumDialog.FileName, ImageFormat.Png); break; case 3: bitmap.Save(exportSpectrumDialog.FileName, ImageFormat.Tiff); break; case 4: bitmap.Save(exportSpectrumDialog.FileName, ImageFormat.Jpeg); break; default: bitmap.Save(exportSpectrumDialog.FileName, ImageFormat.Bmp); break; } } } } catch (ArgumentException) { } } /// /// LoadSpectrumData menuitem click event /// /// sender object /// RoutedEventArgs private void LoadSpectrumData_Click(object sender, RoutedEventArgs e) { using (var of_dlg = new System.Windows.Forms.OpenFileDialog()) { of_dlg.Title = @"Select a file"; of_dlg.Filter = @"Esd(*.esd)|*.esd|Iex(*.iex)|*.iex"; of_dlg.FilterIndex = 1; if (of_dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK) { if (!File.Exists(of_dlg.FileName)) { throw new InvalidOperationException("File does not exists!"); } this.spectrumViewer.ClearComparisonSpectra(); switch (of_dlg.FilterIndex) { case 1: this.spectrumViewer.Spectrum = DataFactory.LoadEdSpectrum(OIHelper.FileToByteArray(of_dlg.FileName)); break; case 2: this.spectrumViewer.Spectrum = DataFactory.LoadEdSpectrumFromIex(of_dlg.FileName); break; } // Initial Periodic table to show the element state this.PeriodicTable.ClearAll(); this.PeriodicTable.IncludeElements(this.spectrumViewer.Spectrum.IdentifiedElements.ToArray()); } } } /// /// SaveSpectrumData menuitem click event /// /// sender object /// RoutedEventArgs private void SaveSpectrumData_Click(object sender, RoutedEventArgs e) { var spectrum = this.spectrumViewer.Spectrum; if (spectrum != null) { try { using (var sf_dlg = new System.Windows.Forms.SaveFileDialog()) { sf_dlg.Title = @"Save spectrum as"; sf_dlg.Filter = @"Esd(*.esd)|*.esd|Iex(*.iex)|*.iex"; sf_dlg.FilterIndex = 1; if (sf_dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK) { switch (sf_dlg.FilterIndex) { case 1: byte[] spectrumData = spectrum.Save(); OIHelper.ByteArrayToFile(sf_dlg.FileName, spectrumData); break; case 2: OIHelper.EdSpectrumProcessing.CreateIexSpectrum(sf_dlg.FileName, spectrum); break; } } } } catch (ArgumentException) { } } } /// /// LoadImageData_Click /// /// sender object /// RoutedEventArgs private void LoadImageData_Click(object sender, RoutedEventArgs e) { try { using (System.Windows.Forms.OpenFileDialog of_dlg = new System.Windows.Forms.OpenFileDialog()) { of_dlg.Title = @"Select a file"; of_dlg.Filter = @"Img(*.img)|*.img"; of_dlg.FilterIndex = 1; if (of_dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK) { if (!File.Exists(of_dlg.FileName)) { throw new System.InvalidOperationException("File does not exists!"); } this.imageViewer.DisplayImage = DataFactory.LoadElectronImage(OIHelper.FileToByteArray(of_dlg.FileName)); } } } catch (SerializationException) { } } /// /// SaveImageData_Click /// /// sender object /// RoutedEventArgs private void SaveImageData_Click(object sender, RoutedEventArgs e) { string filter = @"Img(*.img)|*.img"; string title = @"Save image as"; if (this.imageViewer.DisplayImage != null) { try { var electronImage = this.imageViewer.DisplayImage; using (System.Windows.Forms.SaveFileDialog sf_dlg = new System.Windows.Forms.SaveFileDialog()) { sf_dlg.Filter = filter; sf_dlg.Title = title; sf_dlg.FilterIndex = 1; if (sf_dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK) { byte[] imageData = electronImage.Save(); OIHelper.ByteArrayToFile(sf_dlg.FileName, imageData); } } } catch (ArgumentException) { } } } /// /// MapAcquire_Click /// /// sender object /// RoutedEventArgs private void MapAcquire_Click(object sender, RoutedEventArgs e) { #if ENABLE_MAP_ACQUIRE Window edMapAcquireWindow = new EdMapAcquisition(); edMapAcquireWindow.ShowDialog(); #endif } #endregion #region Control from UI /// /// Start spectrum acquisition /// /// sender object /// RoutedEventArgs private void StartAcquisition(object sender, RoutedEventArgs e) { this.spectrumViewer.ClearComparisonSpectra(); this.AcquireSpectrum(false); } /// /// Resume spectrum acquisition /// /// sender object /// RoutedEventArgs private void ResumeAcquisitionButton_Click(object sender, RoutedEventArgs e) { if (this.spectrumViewer.Spectrum != null && !this.IsAcquiringSpectrum) { this.AcquireSpectrum(true); } } /// /// Adds a spectrum for comparison /// /// The source of the event. /// The instance containing the event data. private void OnAddCompareSpectraButtonClick(object sender, RoutedEventArgs e) { var spectrum = this.cbCompareSpectra.SelectedItem as IEdSpectrum; if (spectrum != null) { ////add current spectrum to compare spectrum this.spectrumViewer.AddComparisonSpectrum(spectrum, this.compareSpectrumColor.SelectedColor); this.compareSpectra.Add(spectrum); this.compareSpectrumColor.SelectedColor = GetRandomColor(); } } /// /// Acquires the spectrum. /// /// if set to true [is resume]. private void AcquireSpectrum(bool isResume) { IEdSpectrum edSpectrum = null; // Spectrum acquisition settings confirm var edSpectrumSettings = OIHelper.EdSpectrumSettings; var edSpectrumAcquisitionController = OIHelper.EdSpectrumAcquisitionController; edSpectrumSettings.EdSettings.AcquisitionMode = (EdAcquireMode)this.cbAcquisitionMode.SelectedItem; edSpectrumSettings.EdSettings.AcquisitionTime = TimeSpan.FromMilliseconds(int.Parse(this.tbAcquisitionTime.Text, CultureInfo.CurrentCulture)); if (edSpectrumSettings.EdSettings.AcquisitionTime > edSpectrumSettings.EdCapabilities.MaximumAcquisitionTime) { edSpectrumSettings.EdSettings.AcquisitionTime = edSpectrumSettings.EdCapabilities.MaximumAcquisitionTime; this.tbAcquisitionTime.Text = edSpectrumSettings.EdSettings.AcquisitionTime.TotalMilliseconds.ToString(CultureInfo.CurrentCulture); } if (edSpectrumSettings.EdSettings.AcquisitionTime < edSpectrumSettings.EdCapabilities.MinimumAcquisitionTime) { edSpectrumSettings.EdSettings.AcquisitionTime = edSpectrumSettings.EdCapabilities.MinimumAcquisitionTime; this.tbAcquisitionTime.Text = edSpectrumSettings.EdSettings.AcquisitionTime.TotalSeconds.ToString(CultureInfo.CurrentCulture); } edSpectrumSettings.EdSettings.ProcessTime = (int)this.cbProcessTime.SelectedValue; edSpectrumSettings.EdSettings.EnergyRange = (int)this.cbEnergyRange.SelectedValue; edSpectrumSettings.EdSettings.NumberOfChannels = (int)this.cbNumOfChannels.SelectedValue; edSpectrumSettings.ScanSettings.AcquisitionRegion.CreateMicroscopeRegion(); this.spectrumViewer.MaximumEnergy = edSpectrumSettings.EdSettings.EnergyRange; // If Ed hardware is not ready, the software will crash. if (edSpectrumAcquisitionController.IsEdHardwareReady(OIHelper.EdSpectrumSettings)) { // *** If this is the first acquisition, call BeginMultipleAcquisition // *** on the AcquisitionController to suppress external scan switching if (!this.currentSpectrumAcquisitions.Any()) { edSpectrumAcquisitionController.BeginMultipleAcquisition(); } if (!isResume) { try { edSpectrum = edSpectrumAcquisitionController.StartAcquisition(edSpectrumSettings); edSpectrum.Label = string.Format(CultureInfo.CurrentCulture, @"{0} ({1:HH:mm:ss})", this.tbSpectrumLabel.Text, DateTime.Now); } catch (InvalidSettingsException invalidSettingsException) { MessageBox.Show(invalidSettingsException.Message); } catch (AcquisitionStartException acquisitionStartException) { MessageBox.Show(acquisitionStartException.Message); } } else { edSpectrumAcquisitionController.ResumeAcquisition(edSpectrumSettings, this.spectrumViewer.Spectrum); edSpectrum = this.spectrumViewer.Spectrum; } if (edSpectrum != null) { this.currentSpectrumAcquisitions.Add(edSpectrum, new AcquisitionItem(edSpectrum, OIHelper.EdSpectrumSettings.EdSettings.AcquisitionMode, OIHelper.EdSpectrumSettings.EdSettings.AcquisitionTime.TotalMilliseconds)); this.AcquisitionQueueListBox.Items.Add(this.currentSpectrumAcquisitions[edSpectrum]); } } } /// /// StopAcquisition /// /// sender object /// RoutedEventArgs private void StopAcquisition(object sender, RoutedEventArgs e) { if (OIHelper.EdSpectrumAcquisitionController.IsAcquiring == true) { OIHelper.EdSpectrumAcquisitionController.StopAcquisition(); } } /// /// Handles the Click event of btStartImageScan button. /// /// The source of the event. /// The instance containing the event data. private void StartImageScan_Click(object sender, EventArgs e) { // Image acquisition settings comfirm var imageSettings = OIHelper.ImageSettings.ImageSettings; var imageCapabilities = OIHelper.ImageSettings.ImageCapabilities; var scanSettings = OIHelper.ImageSettings.ScanSettings; var imageAcquisitionController = OIHelper.ImageAcquisitionController; this.tbImageData.Text = string.Empty; int value = int.Parse(this.tbDwellTime.Text, CultureInfo.InvariantCulture); if (value > imageCapabilities.MaximumImageDwellMicroseconds) { imageSettings.DwellTimeMicroSeconds = imageCapabilities.MaximumImageDwellMicroseconds; } if (value < imageCapabilities.MinimumImageDwellMicroseconds) { imageSettings.DwellTimeMicroSeconds = imageCapabilities.MinimumImageDwellMicroseconds; } else { imageSettings.DwellTimeMicroSeconds = value; } // *** Disable all input sources before enabling the one that the user has chosen imageSettings.InputSources.ToList().ForEach(i => imageSettings.EnableInputSource(i.Key, false)); imageSettings.EnableInputSource((ImageInputSources)this.cbInputSignal.SelectedItem, true); scanSettings.FrameCount = int.Parse(this.tbNumberOfFrames.Text, CultureInfo.InvariantCulture); var pixelSize = 1d / double.Parse(this.cbImageScanSize.Text, CultureInfo.InvariantCulture); scanSettings.AcquisitionRegion.CreateFullFieldRegion(pixelSize); var images = imageAcquisitionController.StartAcquisition(OIHelper.ImageSettings).ToList(); images.ForEach(i => { i.Label = string.Format(CultureInfo.CurrentCulture, @"{0} ({1:HH:mm:ss})", @"ElectronImage", DateTime.Now); this.electronImageList.Add(i); this.ImageAcquisitionQueueListBox.Items.Add(i.Label); }); } /// /// Handles the Click event of btStopImageScan button. /// /// The source of the event. /// The instance containing the event data. private void StopImageScan_Click(object sender, EventArgs e) { if (OIHelper.ImageAcquisitionController.IsAcquiring) { OIHelper.ImageAcquisitionController.StopAcquisition(); } } /// /// AutoID elements. /// /// sender object /// RoutedEventArgs private void AutoIdButton_Click(object sender, RoutedEventArgs e) { this.DoAutoID(); } /// /// Do AutoID /// private void DoAutoID() { var spectrum = this.spectrumViewer.Spectrum; if (spectrum != null) { this.IdentifiedElementTextBox.Clear(); IEnumerable elementList = OIHelper.EdSpectrumProcessing.IdentifyElements( spectrum, OIHelper.AutoIdSettings); foreach (int i in elementList) { this.IdentifiedElementTextBox.Text = this.IdentifiedElementTextBox.Text + ElementProperties.GetElementSymbol(i) + Environment.NewLine; } // Update spectrum peak label this.UpdateSpectrumPeakLabels(); } } /// /// Confirm excluded element /// /// sender object /// EventArgs private void AddElementButton_Click(object sender, RoutedEventArgs e) { try { this.PeriodicTable.ExcludeElements(this.CurrentExclusionElement); } catch (FormatException fe) { MessageBox.Show(@"Please enter valid element!" + fe.Message); } } /// /// Detete Excluded Elements /// /// sender object /// EventArgs private void RemoveElementButton_Click(object sender, RoutedEventArgs e) { try { this.PeriodicTable.Clear(this.CurrentExclusionElement); } catch (FormatException fe) { MessageBox.Show(@"Please enter valid element!" + fe.Message); } } /// /// Clear Excluded element list /// /// sender object /// EventArgs private void ClearButton_Click(object sender, RoutedEventArgs e) { this.PeriodicTable.ClearAll(); } /// /// Do quant button click handler. /// /// sender /// RoutedEventArgs private void QuantButton_Click(object sender, RoutedEventArgs e) { this.DoQuant(); } /// /// Do quantitative processing and display /// private void DoQuant() { switch (OIHelper.SEMQuantSettings.ProcessingOption) { case ProcessingOption.ElementByDifference: OIHelper.SEMQuantSettings.CombinedElement = int.Parse(this.CombinedElementTextBox.Text, CultureInfo.InvariantCulture); break; case ProcessingOption.ElementByStoichiometry: // While it is possible to choose other elements, Oxygen is the only supported element by stoichiometry. OIHelper.SEMQuantSettings.CombinedElement = 8; OIHelper.SEMQuantSettings.TypeOfIon = IonType.Anion; OIHelper.SEMQuantSettings.NumberOfIons = double.Parse(this.NumberOfIonsTextBox.Text, CultureInfo.InvariantCulture); break; case ProcessingOption.AllElements: default: break; } if (this.IsCoatedCheckBox.IsChecked == true) { OIHelper.SEMQuantSettings.SampleCoating.IsCoated = true; OIHelper.SEMQuantSettings.SampleCoating.Thickness = double.Parse(this.ThicknessTextBox.Text, CultureInfo.InvariantCulture); OIHelper.SEMQuantSettings.SampleCoating.Density = double.Parse(this.DensityTextBox.Text, CultureInfo.InvariantCulture); OIHelper.SEMQuantSettings.SampleCoating.CoatingElement = int.Parse(this.CoatingElementTextBox.Text, CultureInfo.InvariantCulture); } else { OIHelper.SEMQuantSettings.SampleCoating.IsCoated = false; this.ThicknessTextBox.IsEnabled = false; this.DensityTextBox.IsEnabled = false; } if (this.ThresholdingCheckBox.IsChecked == true) { OIHelper.SEMQuantSettings.Thresholding = true; OIHelper.SEMQuantSettings.SigmaLevel = double.Parse(this.SigmaLevelTextBox.Text, CultureInfo.InvariantCulture); } else { OIHelper.SEMQuantSettings.Thresholding = false; this.SigmaLevelTextBox.IsEnabled = false; } OIHelper.SEMQuantSettings.Normalised = this.NormalisedCheckBox.IsChecked.Value; this.QuantResultDataGrid.Items.Clear(); try { ISEMQuantStatus status = OIHelper.EdSpectrumProcessing.SEMQuantifySpectrum(this.spectrumViewer.Spectrum, OIHelper.SEMQuantSettings); this.quantStatus.DataContext = status; double totalWeightPercent = 0; double totalAtomicPercent = 0; foreach (ISEMQuantResult result in status.Results) { if (result.WeightPercent != 0) { var elementRow = new DataGridRow(); elementRow.Item = new { Element = ElementProperties.GetElementSymbol(result.AtomicNumber), Line = result.LineType, WtPcent = Math.Round(result.WeightPercent, 2), WtSigma = Math.Round(result.WeightPercentSigma, 6), AtPcent = Math.Round(result.AtomicPercent, 2) }; this.QuantResultDataGrid.Items.Add(elementRow); } totalWeightPercent += result.WeightPercent; totalAtomicPercent += result.AtomicPercent; } var totalRow = new DataGridRow(); totalRow.Item = new { Element = @"Total", WtPcent = Math.Round(totalWeightPercent, 2), AtPcent = Math.Round(totalAtomicPercent, 2) }; this.QuantResultDataGrid.Items.Add(totalRow); this.spectrumViewer.SEMQuantify(OIHelper.SEMQuantSettings); } catch (QuantificationException ex) { MessageBox.Show(ex.Message, @"Quantification Error", MessageBoxButton.OK, MessageBoxImage.Warning); } catch (ArgumentNullException) { } } /// /// Used when processing spectra from specimens in which all elements yield X-rays which can be readily detected. /// /// sender object /// EventArgs private void AllElementsRadioButton_Click(object sender, RoutedEventArgs e) { OIHelper.SEMQuantSettings.ProcessingOption = ProcessingOption.AllElements; this.NormalisedCheckBox.IsEnabled = true; this.CombinedElementTextBox.IsEnabled = false; this.NumberOfIonsTextBox.IsEnabled = false; } /// /// Calculated assuming that the difference between the analyzed total and 100% /// /// sender object /// EventArgs private void ElementByDifferenceRadioButton_Click(object sender, RoutedEventArgs e) { OIHelper.SEMQuantSettings.ProcessingOption = ProcessingOption.ElementByDifference; this.NormalisedCheckBox.IsChecked = false; this.NormalisedCheckBox.IsEnabled = false; this.CombinedElementTextBox.IsEnabled = true; this.NumberOfIonsTextBox.IsEnabled = false; } /// /// Concentration of oxygen to be calculated. /// /// sender object /// EventArgs private void ElementByStoichiometryRadioButton_Click(object sender, RoutedEventArgs e) { OIHelper.SEMQuantSettings.ProcessingOption = ProcessingOption.ElementByStoichiometry; this.NormalisedCheckBox.IsEnabled = true; this.CombinedElementTextBox.IsEnabled = false; this.NumberOfIonsTextBox.IsEnabled = true; } /// /// Add deconvolution element to list /// /// sender object /// EventArgs private void AddDeconvolutionButton_Click(object sender, RoutedEventArgs e) { this.DeconvolutionElementListTextBox.Clear(); try { OIHelper.SEMQuantSettings.SetDeconvolutionElement(this.CurrentDeconvolutionElement, true); foreach (int i in OIHelper.SEMQuantSettings.DeconvolutionElements) { this.DeconvolutionElementListTextBox.Text += i.ToString(CultureInfo.InvariantCulture) + Environment.NewLine; } } catch (FormatException fe) { this.DeconvolutionElementListTextBox.Text = fe.Message; } catch (ArgumentOutOfRangeException ae) { this.DeconvolutionElementListTextBox.Text = ae.Message; } } /// /// Remove 1 deconvolution element from elment list. /// /// sender /// RoutedEventArgs private void DeconvolutionRemoveButton_Click(object sender, RoutedEventArgs e) { this.DeconvolutionElementListTextBox.Clear(); try { OIHelper.SEMQuantSettings.SetDeconvolutionElement(this.CurrentDeconvolutionElement, false); foreach (int i in OIHelper.SEMQuantSettings.DeconvolutionElements) { this.DeconvolutionElementListTextBox.Text += i.ToString(CultureInfo.InvariantCulture) + Environment.NewLine; } } catch (FormatException fe) { this.DeconvolutionElementListTextBox.Text = fe.Message; } } /// /// Clear DeconvolutionElementList /// /// sender /// RoutedEventArgs private void DeconvolutionClearButton_Click(object sender, RoutedEventArgs e) { this.DeconvolutionElementListTextBox.Clear(); OIHelper.SEMQuantSettings.ClearDeconvolutionElements(); foreach (int i in OIHelper.SEMQuantSettings.DeconvolutionElements) { this.DeconvolutionElementListTextBox.Text += i.ToString(CultureInfo.InvariantCulture) + Environment.NewLine; } } /// /// ThicknessTextBox and DensityTextBox will be enabled when IsCoatedCheckBox_Checked /// /// sender /// RoutedEventArgs private void IsCoatedCheckBox_Click(object sender, RoutedEventArgs e) { this.CoatingElementTextBox.IsEnabled = (bool)this.IsCoatedCheckBox.IsChecked; this.DensityTextBox.IsEnabled = (bool)this.IsCoatedCheckBox.IsChecked; this.ThicknessTextBox.IsEnabled = (bool)this.IsCoatedCheckBox.IsChecked; } /// /// SigmaLevelTextBox will be enabled when ThresholdingCheckBox_Checked /// /// sender /// RoutedEventArgs private void ThresholdingCheckBox_Click(object sender, RoutedEventArgs e) { this.SigmaLevelTextBox.IsEnabled = (bool)this.ThresholdingCheckBox.IsChecked; } /// /// Handles the CheckedChanged event of the MultiselectCheckBox control. /// /// The source of the event. /// The instance containing the event data. private void MultiselectCheckBox_CheckedChanged(object sender, RoutedEventArgs e) { this.PeriodicTable.SelectionMode = this.MultiselectCheckBox.IsChecked.Value ? SelectionMode.Multiple : SelectionMode.Single; } /// /// Handles the Checked event of the ElementEnable control. /// /// The source of the event. /// The instance containing the event data. private void ElementEnable_Checked(object sender, RoutedEventArgs e) { CheckBox check = sender as CheckBox; this.PeriodicTable.EnableElements(true, (int)check.Tag); } /// /// Handles the Unchecked event of the ElementEnable control. /// /// The source of the event. /// The instance containing the event data. private void ElementEnable_Unchecked(object sender, RoutedEventArgs e) { CheckBox check = sender as CheckBox; this.PeriodicTable.EnableElements(false, (int)check.Tag); } /// /// Handles the click Calculate button event. /// /// The source of the event. /// The instance containing the event data. private void CalculatePeakParameterButton_Click(object sender, RoutedEventArgs e) { try { int atomicNum = ElementProperties.GetAtomicNumberByElementSymbol(this.IdentifiedElementTextBox.SelectedText); var peakParameters = OIHelper.EdSpectrumProcessing.CalculatePeakParameters(this.spectrumViewer.Spectrum, atomicNum); this.tbEnergy.Text = peakParameters.Centre.ToString(CultureInfo.InvariantCulture); this.tbFWHM.Text = peakParameters.FWHM.ToString(CultureInfo.InvariantCulture); } catch (NullReferenceException) { } catch (FormatException) { } catch (InvalidOperationException) { } } /// /// Handles the Click event of the GetPixelData button. /// /// The source of the event. /// instance containing the event data. private void GetPixelData_Click(object sender, RoutedEventArgs e) { if (OIHelper.ImageAcquisitionController.IsAcquiring != true && this.imageViewer.DisplayImage != null) { try { var electronImage = this.imageViewer.DisplayImage as IElectronImage; int x = int.Parse(this.tbPointX.Text, CultureInfo.InvariantCulture); int y = int.Parse(this.tbPointY.Text, CultureInfo.InvariantCulture); this.sb.Append(string.Format(CultureInfo.CurrentCulture, @" Point({0},{1}), Value: {2}", x, y, electronImage.GetData(new System.Drawing.Point(x, y)))); this.sb.Append(System.Environment.NewLine); this.tbImageData.Text = this.sb.ToString(); } catch (ArgumentOutOfRangeException) { //// stringBuilder - The length of the expanded string would exceed MaxCapacity. } catch (FormatException) { //// int.Parse - The x or y coordinates are not in the correct format. } } } /// /// The Window is closing. Cancel if acquiring a spectrum. /// /// The sender. /// The instance containing the event data. private void WindowClosing(object sender, CancelEventArgs e) { e.Cancel = this.IsAcquiringSpectrum; } #endregion /// /// Loads the comparison spectra. /// private void LoadComparisonSpectra() { byte[] data; Uri uri; StreamResourceInfo info; this.comparisonSpectra = new List(); uri = new Uri(@"/ComparisonSpectra/Nickel.spec", UriKind.Relative); info = Application.GetResourceStream(uri); data = new byte[info.Stream.Length]; info.Stream.Read(data, 0, (int)info.Stream.Length); this.comparisonSpectra.Add(DataFactory.LoadEdSpectrum(data)); uri = new Uri(@"/ComparisonSpectra/Preview spectrum.spec", UriKind.Relative); info = Application.GetResourceStream(uri); data = new byte[info.Stream.Length]; info.Stream.Read(data, 0, (int)info.Stream.Length); this.comparisonSpectra.Add(DataFactory.LoadEdSpectrum(data)); uri = new Uri(@"/ComparisonSpectra/Tungsten particle.spec", UriKind.Relative); info = Application.GetResourceStream(uri); data = new byte[info.Stream.Length]; info.Stream.Read(data, 0, (int)info.Stream.Length); this.comparisonSpectra.Add(DataFactory.LoadEdSpectrum(data)); this.cbCompareSpectra.DataContext = this; this.cbCompareSpectra.SelectedIndex = 0; } #region INotifyPropertyChanged Members /// /// PropertyChanged event /// public event PropertyChangedEventHandler PropertyChanged = delegate { }; #endregion /// /// The last element set /// private int lastElementSet = -1; /// /// Handles the PropertyChanged event of the ExcludeElementCombo control. /// /// The source of the event. /// The instance containing the event data. private void ExcludeElementCombo_PropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == @"CurrentElement") { this.UpdateHighlightedElementInTable(); } } /// /// Updates the highlighted element in table. /// private void UpdateHighlightedElementInTable() { if (this.lastElementSet != -1) { this.PeriodicTable.SetElementColor(this.lastElementSet, System.Windows.Media.Colors.Transparent); } System.Windows.Media.Color currentElementColor = System.Windows.Media.Color.FromArgb(255, 200, 255, 0); this.PeriodicTable.SetElementColor(this.ExcludeElementCombo.CurrentElement, currentElementColor); this.PeriodicTable.ShowElementColors = true; this.lastElementSet = this.ExcludeElementCombo.CurrentElement; } /// /// Handles the Click event of the exportTiffButton control. /// /// The source of the event. /// The instance containing the event data. private void ExportTiffButton_Click(object sender, RoutedEventArgs e) { // Export a tiff synchronously on the calling thread. var syncTiff = this.spectrumViewer.CreateImage(ExportImageType.Tiff); File.WriteAllBytes(Path.Combine(Path.GetTempPath(), @"zSpectrumSync.tiff"), syncTiff); // Export a tiff asynchronously on a background thread. // The thread must be created with an apartment state set to STA. // Calls to CreateImage() must be made on the same thread that created the viewer. var spectrum = this.spectrumViewer.Spectrum; var thread = new System.Threading.Thread(() => { // For optimum performance, create a single spectrum viewer and change the spectrum // and viewer settings where required for all spectra that you need images for. var backgroundViewer = new SpectrumViewer(); // A height and width must be set to provide the image dimensions in pixels. backgroundViewer.Width = 500; backgroundViewer.Height = 500; backgroundViewer.IsYAxisAutoScaleEnabled = true; backgroundViewer.YAxisType = ScaleType.Logarithmic; backgroundViewer.MaximumEnergy = 8; backgroundViewer.Spectrum = spectrum; var asyncTiff = backgroundViewer.CreateImage(ExportImageType.Tiff); File.WriteAllBytes(Path.Combine(Path.GetTempPath(), @"zSpectrumAsync.tiff"), asyncTiff); backgroundViewer.Dispatcher.InvokeShutdown(); }); thread.IsBackground = true; thread.SetApartmentState(ApartmentState.STA); thread.Start(); } } }