namespace OINA.Extender.WPF.Testharness { using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Threading; using OINA.Extender.Acquisition; using OINA.Extender.Acquisition.Ed; using OINA.Extender.Data.Ed; using OINA.Extender.Data.Image; using OINA.Extender.Processing; using OINA.Extender.Processing.Ed; /// /// Interaction logic for MapAcquisition.xaml /// public partial class MapAcquisition : UserControl, INotifyPropertyChanged { private readonly List enabledDetectors; private EdHardwareId primaryHardwareId; private List secondaryHardwareIds; private IEdMapAcquisitionController controller; private IEdSpectrum spectrum; private ObservableCollection acquiredMaps; private IEdMap selectedMap; private IReadOnlyList elementMaps; private double progressPercentage; private IEdMapAcquisitionData mapData; private IEdMapProcessor mapProcessor; private IAutoIdSettings autoIdSettings; private IEdSpectrumProcessing spectrumProcessing; public MapAcquisition() { this.InitializeComponent(); this.DataContext = this; this.autoIdSettings = ProcessingFactory.CreateAutoIdSettings(); this.spectrumProcessing = ProcessingFactory.CreateSpectrumProcessing(); this.Settings = AcquireFactory.CreateEdMapSettings(); // pixel size is the number of data pixels in x double pixelSize = 1.0 / 128; this.Settings.ScanSettings.AcquisitionRegion.CreateFullFieldRegion(pixelSize); this.Settings.ScanSettings.FrameCount = 1; this.enabledDetectors = this.Settings.EdSettings.IsHardwareEnabled .Select(i => new DetectorEnableModel(i.Key, i.Value)).ToList(); this.PrimaryHardwareId = this.Settings.EdSettings.PrimaryHardwareId; this.controller = AcquireFactory.CreateEdMapServer(); this.controller.ExperimentStarted += this.OnExperimentStarted; this.controller.ExperimentFinished += this.OnExperimentFinished; this.acquiredMaps = new ObservableCollection(); } /// /// Event that notifies that the processing progress has changed /// public event PropertyChangedEventHandler PropertyChanged; private void RaisePropertyChanged(string propertyName) { this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } private void StartButton_Click(object sender, System.Windows.RoutedEventArgs e) { this.ElementMaps = null; this.ProgressPercentage = 0; var edSettings = this.Settings.EdSettings; var scanSettings = this.Settings.ScanSettings; foreach (var detectorEnabled in this.secondaryHardwareIds) { edSettings.EnableDevice(detectorEnabled.EdHardwareId, detectorEnabled.IsDetectorEnabled); } edSettings.PrimaryHardwareId = this.primaryHardwareId; edSettings.AcquisitionMode = EdAcquireMode.LiveTime; // 1ms pixel dwell time edSettings.AcquisitionTime = TimeSpan.FromMilliseconds(1); edSettings.TimeMode = EdTimeMode.Pixel; var results = this.Settings.Validate(); if (!results.IsValid) { string errors = string.Join(Environment.NewLine, results.ValidationErrors); MessageBox.Show(errors, @"Invalid acquisition settings"); return; } this.controller.StartAcquisition(this.Settings); } private void StopButton_Click(object sender, System.Windows.RoutedEventArgs e) { this.controller.StopAcquisition(); } private void OnExperimentStarted(object sender, AcquisitionStartedEventArgs e) { this.Spectrum = e.Value.EdSpectrum; this.mapData = e.Value; } private void OnExperimentFinished(object sender, AcquisitionFinishedEventArgs e) { var edMap = e.Value?.EdMap; if (edMap != null) { this.Dispatcher.BeginInvoke(() => { this.acquiredMaps.Add(edMap); this.SelectedMap = edMap; }); } } public IEdSpectrum Spectrum { get { return this.spectrum; } set { this.spectrum = value; this.RaisePropertyChanged(nameof(this.Spectrum)); } } public IEdMapSettings Settings { get; } public EdHardwareId PrimaryHardwareId { get { return this.primaryHardwareId; } set { if (this.primaryHardwareId == value) { return; } this.primaryHardwareId = value; this.RaisePropertyChanged(nameof(this.PrimaryHardwareId)); this.SecondaryHardwareIds = this.enabledDetectors.Where(i => i.EdHardwareId != value).ToList(); } } public IReadOnlyList SecondaryHardwareIds { get { return this.secondaryHardwareIds; } set { this.secondaryHardwareIds = value.ToList(); this.RaisePropertyChanged(nameof(this.SecondaryHardwareIds)); } } /// /// Gets the acquired maps /// public ObservableCollection AcquiredMaps { get { return this.acquiredMaps; } } /// /// Gets or sets the selected map /// public IEdMap SelectedMap { get { return this.selectedMap; } set { this.selectedMap = value; this.RaisePropertyChanged(nameof(this.SelectedMap)); } } /// /// Deletes the selected map /// private void DeleteMapButton_Click(object sender, RoutedEventArgs e) { // Maps should be deleted when they are no longer required as the data is saved in the // AppData\Local\Oxford Instruments NanoAnalysis\Extender\TempProject folder of the current user // Note these projects cannot be used with AZtec. var edMap = this.selectedMap; if (edMap != null) { this.controller.Delete(edMap); edMap.Dispose(); this.acquiredMaps.Remove(edMap); this.SelectedMap = this.acquiredMaps.LastOrDefault(); } } #region FLS Processing /// /// Starts FLS map processing /// /// The map data private void StartFLSProcessing(IEdMapAcquisitionData mapData) { this.PerformAutoId(mapData); var processor = ProcessingFactory.CreateEdMapFLSProcessor(); var settings = ProcessingFactory.CreateEdMapFLSSettings(); try { this.MapProcessor = processor; this.ElementMaps = processor.StartProcessing(mapData, settings); } catch (Exception ex) { MessageBox.Show(ex.Message, @"Error starting FLS processing"); } } #endregion #region window integral processing /// /// Starts window integral map processing /// /// The map data private void StartWindowIntegralProcessing(IEdMapAcquisitionData mapData) { this.PerformAutoId(mapData); var processor = ProcessingFactory.CreateEdMapWindowIntegralProcessor(); var settings = ProcessingFactory.CreateEdMapWindowIntegralSettings(); try { this.MapProcessor = processor; this.ElementMaps = processor.StartProcessing(mapData, settings); } catch (Exception ex) { MessageBox.Show(ex.Message, @"Error starting window integral processing"); } } #endregion #region common map processing /// /// Gets or sets the Ed Map processor /// private IEdMapProcessor MapProcessor { get { return this.mapProcessor; } set { if (this.mapProcessor == value) { return; } var processor = this.mapProcessor; if (processor != null) { processor.CancelProcessing(); processor.ProgressChanged -= this.OnProcessingProgressChanged; processor.Dispose(); } this.mapProcessor = value; if (value != null) { value.ProgressChanged += this.OnProcessingProgressChanged; } } } private void OnProcessingProgressChanged(object sender, ProcessingProgressEventArgs e) { this.ProgressPercentage = e.ProgressPercentage; if (e.State == ProcessingProgressState.Completed) { this.elementMaps.ToList().ForEach(i => i.AutoBrightness()); // calculate total counts in the first element map var elementMap = this.elementMaps.OfType().FirstOrDefault(); if (elementMap != null) { int pixels = elementMap.Height * elementMap.Width; float[] countsPerSecond = new float[pixels]; elementMap.GetData(countsPerSecond); float[] liveTimes = new float[pixels]; this.mapData.EdMap.GetLiveTimes(elementMap.BinFactor, liveTimes); double totalCounts = Enumerable.Range(0, pixels).Sum(i => countsPerSecond[i] * liveTimes[i]); } } } /// /// Gets or sets the processing percentage (0 - 100) /// public double ProgressPercentage { get { return this.progressPercentage; } set { this.progressPercentage = value; this.RaisePropertyChanged(nameof(this.ProgressPercentage)); } } /// /// Gets or sets the element maps /// public IReadOnlyList ElementMaps { get { return this.elementMaps; } set { if (this.elementMaps == value) { return; } var elementMaps = this.elementMaps; elementMaps?.ToList().ForEach(i => i.Dispose()); this.elementMaps = value; this.RaisePropertyChanged(nameof(this.ElementMaps)); } } private void PerformAutoId(IEdMapAcquisitionData mapData) { try { // Identify the elements in the sum spectrum var elements = this.spectrumProcessing.IdentifyElements(mapData.EdSpectrum, this.autoIdSettings); if (elements.Any()) { // Update the identified elements in the map. Used to create the element maps. mapData.EdMap.ClearIdentifiedElements(); mapData.EdMap.SetIdentifiedElements(elements, true); // Update the peak labels this.spectrumProcessing.UpdatePeakLabels(mapData.EdSpectrum, null); } } catch (Exception ex) { MessageBox.Show(ex.Message, @"Error processing spectrum"); } } private void CancelButton_Click(object sender, RoutedEventArgs e) { this.MapProcessor?.CancelProcessing(); } #endregion private void WindowIntegral_Click(object sender, RoutedEventArgs e) { if (this.mapData != null) { this.StartWindowIntegralProcessing(this.mapData); } } private void FLS_Click(object sender, RoutedEventArgs e) { if (this.mapData != null) { this.StartFLSProcessing(this.mapData); } } } }