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);
}
}
}
}