123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534 |
- 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.Acquisition.XSync;
- using OINA.Extender.Data.Ed;
- using OINA.Extender.Data.Image;
- using OINA.Extender.Processing;
- using OINA.Extender.Processing.Ed;
- /// <summary>
- /// Interaction logic for XSyncMapAcquisition.xaml
- /// </summary>
- public partial class XSyncMapAcquisition : UserControl, INotifyPropertyChanged
- {
- private readonly List<DetectorEnableModel> enabledDetectors;
- private EdHardwareId primaryHardwareId;
- private List<DetectorEnableModel> secondaryHardwareIds;
- private IXSyncEdMapAcquisitionController controller;
- private IEdSpectrum spectrum;
- private bool isPaused;
- private string pauseResumeState;
- private int completedFrames;
- private ObservableCollection<IEdMap> acquiredMaps;
- private IEdMap selectedMap;
- private IReadOnlyList<IEdMapImage> elementMaps;
- private double progressPercentage;
- private IEdMapAcquisitionData mapData;
- private IEdMapProcessor mapProcessor;
- private IAutoIdSettings autoIdSettings;
- private IEdSpectrumProcessing spectrumProcessing;
- public XSyncMapAcquisition()
- {
- this.InitializeComponent();
- this.DataContext = this;
- this.autoIdSettings = ProcessingFactory.CreateAutoIdSettings();
- this.spectrumProcessing = ProcessingFactory.CreateSpectrumProcessing();
- this.Settings = AcquireFactory.CreateXSyncEdMapSettings();
- this.Settings.XSyncSettings.SynchronizationMode = XSyncMode.CASLineSync;
- // pixel size is the number of data pixels in x
- double pixelSize = 1.0 / 120;
- // assume that there are also 120 data pixels in y
- Size size = new Size(1.0, 1.0);
- this.Settings.XSyncSettings.AcquisitionRegion.CreateRectangleRegion(new Rect(size), pixelSize);
- this.Settings.XSyncSettings.FrameCount = 1;
- // assume that there are 2040 lines scanned, this gives a binning factor of 17
- this.Settings.XSyncSettings.LineSync.BinFactorY = 17;
- this.Settings.XSyncSettings.LineSync.LinesPerFrame = 2040; // = (120 * 17)
- // set the calibrated field width to set the image viewer scale bar
- this.Settings.XSyncSettings.CalibratedFieldWidthmm = 180;
- this.enabledDetectors = this.Settings.EdSettings.IsHardwareEnabled
- .Select(i => new DetectorEnableModel(i.Key, i.Value)).ToList();
- this.PrimaryHardwareId = this.Settings.EdSettings.PrimaryHardwareId;
- this.controller = AcquireFactory.CreateXSyncEdMapServer();
- this.controller.ExperimentStarted += this.OnExperimentStarted;
- this.controller.ExperimentFinished += this.OnExperimentFinished;
- this.controller.PauseRequested += this.OnPauseRequested;
- this.controller.ResumeRequested += this.OnResumeRequested;
- this.controller.FrameCompleted += this.OnFrameCompleted;
- this.acquiredMaps = new ObservableCollection<IEdMap>();
- }
- /// <summary>
- /// Event that notifies that the processing progress has changed
- /// </summary>
- 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.PauseResumeState = string.Empty;
- this.IsPaused = false;
- this.CompletedFrames = 0;
- this.ElementMaps = null;
- this.ProgressPercentage = 0;
- var edSettings = this.Settings.EdSettings;
- var xsyncSettings = this.Settings.XSyncSettings;
- foreach (var detectorEnabled in this.secondaryHardwareIds)
- {
- edSettings.EnableDevice(detectorEnabled.EdHardwareId, detectorEnabled.IsDetectorEnabled);
- }
- edSettings.PrimaryHardwareId = this.primaryHardwareId;
- if (xsyncSettings.SynchronizationMode == XSyncMode.CASLineSync)
- {
- edSettings.AcquisitionMode = EdAcquireMode.RealTime;
- edSettings.AcquisitionTime = TimeSpan.FromTicks((long)(xsyncSettings.LineSync.DwellTimeMicroSeconds * TimeSpan.TicksPerMillisecond / 1000));
- 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<IEdMapAcquisitionData> e)
- {
- this.Spectrum = e.Value.EdSpectrum;
- this.mapData = e.Value;
- }
- private void OnExperimentFinished(object sender, AcquisitionFinishedEventArgs<IEdMapAcquisitionData> 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 IXSyncEdMapSettings 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<DetectorEnableModel> SecondaryHardwareIds
- {
- get
- {
- return this.secondaryHardwareIds;
- }
- set
- {
- this.secondaryHardwareIds = value.ToList();
- this.RaisePropertyChanged(nameof(this.SecondaryHardwareIds));
- }
- }
- #region Pause / Resume
- private void OnPauseRequested(object sender, PauseScanEventArgs e)
- {
- this.PauseResumeState = @"Pause requested";
- }
- private void OnResumeRequested(object sender, ResumeScanEventArgs e)
- {
- this.PauseResumeState = @"Resume requested";
- }
- /// <summary>
- /// Gets or sets a value indicating whether the external scan hardware is paused
- /// </summary>
- public bool IsPaused
- {
- get
- {
- return this.isPaused;
- }
- set
- {
- if (this.isPaused == value)
- {
- return;
- }
- this.isPaused = value;
- this.RaisePropertyChanged(nameof(this.IsPaused));
- this.controller.NotifyPauseResume(value);
- }
- }
- /// <summary>
- /// Gets or sets a value indicating whether a pause or resume is requested
- /// </summary>
- public string PauseResumeState
- {
- get
- {
- return this.pauseResumeState;
- }
- set
- {
- if (this.pauseResumeState == value)
- {
- return;
- }
- this.pauseResumeState = value;
- this.RaisePropertyChanged(nameof(this.PauseResumeState));
- }
- }
- #endregion
- private void OnFrameCompleted(object sender, FrameCompletedEventArgs e)
- {
- this.CompletedFrames = e.FrameNumber;
- }
- /// <summary>
- /// Gets or sets the number of completed frames
- /// </summary>
- public int CompletedFrames
- {
- get
- {
- return this.completedFrames;
- }
- set
- {
- if (this.completedFrames == value)
- {
- return;
- }
- this.completedFrames = value;
- this.RaisePropertyChanged(nameof(this.CompletedFrames));
- }
- }
- /// <summary>
- /// Gets the acquired maps
- /// </summary>
- public ObservableCollection<IEdMap> AcquiredMaps
- {
- get
- {
- return this.acquiredMaps;
- }
- }
- /// <summary>
- /// Gets or sets the selected map
- /// </summary>
- public IEdMap SelectedMap
- {
- get
- {
- return this.selectedMap;
- }
- set
- {
- this.selectedMap = value;
- this.RaisePropertyChanged(nameof(this.SelectedMap));
- }
- }
- /// <summary>
- /// Deletes the selected map
- /// </summary>
- 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
- /// <summary>
- /// Starts FLS map processing
- /// </summary>
- /// <param name="mapData">The map data</param>
- 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
- /// <summary>
- /// Starts window integral map processing
- /// </summary>
- /// <param name="mapData">The map data</param>
- 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
- /// <summary>
- /// Gets or sets the Ed Map processor
- /// </summary>
- 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<IEdMapImage>().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]);
- }
- }
- }
- /// <summary>
- /// Gets or sets the processing percentage (0 - 100)
- /// </summary>
- public double ProgressPercentage
- {
- get
- {
- return this.progressPercentage;
- }
- set
- {
- this.progressPercentage = value;
- this.RaisePropertyChanged(nameof(this.ProgressPercentage));
- }
- }
- /// <summary>
- /// Gets or sets the element maps
- /// </summary>
- public IReadOnlyList<IEdMapImage> 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);
- }
- }
- }
- }
|