Loading INAF.Apps.Uwp.SLabDataManager/App.xaml.cs +3 −2 Original line number Diff line number Diff line Loading @@ -100,7 +100,7 @@ namespace INAF.Apps.Uwp.SLabDataManager Ioc.Default.ConfigureServices( new ServiceCollection() /* singletons */ .AddSingleton<CustomAnnotationsRepository>() .AddSingleton<CustomLinesAnnotationsRepository>() .AddSingleton<SelectedRefBand>() .AddSingleton<SpectrumAlignmentConfigModel>() .AddSingleton<SpectrumChartOptionsModel>() Loading @@ -121,10 +121,11 @@ namespace INAF.Apps.Uwp.SLabDataManager .AddTransient<RemoteOperationsManager>() .AddTransient<RemoteOperationsXmlReader>() .AddTransient<SpectrumModelFactory>() .AddTransient<SpectrumProcessingHelper>() .AddTransient<SpectrumReader>() .AddTransient<XmlHelper>() /* view models */ .AddTransient<ChartViewModel>() .AddSingleton<ChartViewModel>() .AddTransient<LoginViewModel>() .AddTransient<LoginCheckViewModel>() .AddSingleton<MainViewModel>() Loading INAF.Apps.Uwp.SLabDataManager/Charts/SpectraContainer.cs +58 −211 Original line number Diff line number Diff line using INAF.Apps.Uwp.SLabDataManager.Extensions; using INAF.Apps.Uwp.SLabDataManager.Helpers; using INAF.Apps.Uwp.SLabDataManager.Helpers; using INAF.Apps.Uwp.SLabDataManager.Models; using INAF.Libraries.NetStandard.ScienceModels.Extensions; using INAF.Libraries.NetStandard.ScienceModels.Spectra; Loading @@ -19,13 +18,9 @@ namespace INAF.Apps.Uwp.SLabDataManager.Charts { public class SpectraContainer : ObservableObject { private readonly Logger logger; public SpectraContainer(IServiceProvider serviceProvider, Logger logger) { this.logger = logger; SpectrumAlignmentConfig = serviceProvider.GetRequiredService<SpectrumAlignmentConfigModel>(); SelectedRefBand = serviceProvider.GetRequiredService<SelectedRefBand>(); Loading @@ -42,19 +37,8 @@ namespace INAF.Apps.Uwp.SLabDataManager.Charts } #region properties public string DialogMessage { get; private set; } public DialogMessageType DialogMessageType { get; private set; } public bool IsAlignedSpectrumSaved { get; set; } private bool isDialogRequired; public bool IsDialogRequired { get { return isDialogRequired; } set { SetProperty(ref isDialogRequired, value); } } private bool isAnySummaryUpdated; public bool IsAnySummaryUpdated { Loading @@ -62,8 +46,6 @@ namespace INAF.Apps.Uwp.SLabDataManager.Charts set { SetProperty(ref isAnySummaryUpdated, value); } } public bool IsSpectrumAligned { get; set; } private bool isAnySpectrumLoaded; public bool IsAnySpectrumLoaded { Loading @@ -86,7 +68,19 @@ namespace INAF.Apps.Uwp.SLabDataManager.Charts } } public SelectedRefBand SelectedRefBand { get; private set; } private bool isSpectrumAligned; public bool IsSpectrumAligned { get { return isSpectrumAligned; } set { SetProperty(ref isSpectrumAligned, value); } } private bool isSpectrumContinuumRemoved; public bool IsSpectrumContinuumRemoved { get { return isSpectrumContinuumRemoved; } set { SetProperty(ref isSpectrumContinuumRemoved, value); } } private ObservableCollection<SpectrumModel> spectra; public ObservableCollection<SpectrumModel> Spectra Loading @@ -95,6 +89,10 @@ namespace INAF.Apps.Uwp.SLabDataManager.Charts private set { SetProperty(ref spectra, value); } } public SelectedRefBand SelectedRefBand { get; private set; } public SpectrumAlignmentConfigModel SpectrumAlignmentConfig { get; private set; } private ObservableCollection<SpectrumSummaryModel> summaries; public ObservableCollection<SpectrumSummaryModel> Summaries { Loading @@ -102,8 +100,6 @@ namespace INAF.Apps.Uwp.SLabDataManager.Charts private set { SetProperty(ref summaries, value); } } public SpectrumAlignmentConfigModel SpectrumAlignmentConfig { get; private set; } #region spectrums min/max private AxisBoundariesModel xAxisBoundaries; public AxisBoundariesModel XAxisBoundaries Loading Loading @@ -146,42 +142,6 @@ namespace INAF.Apps.Uwp.SLabDataManager.Charts Spectra.Clear(); } private async Task<(double xMin, double xMax, double yMin, double yMax)> getSpectrumAxesBoundariesAsync() { List<Task> tasks = new List<Task>(); double xMin = 0d; double xMax = 0d; double yMin = 0d; double yMax = 0d; tasks.Add(Task.Run(() => { List<double> xvalues = new List<double>(); foreach (var spectrum in spectra) xvalues.AddRange(spectrum.Elements.Select(x => x.X)); (double xMin, double xMax) xresult = xvalues.GetBoundaries(); xMin = xresult.xMin; xMax = xresult.xMax; })); tasks.Add(Task.Run(() => { List<double> yvalues = new List<double>(); foreach (var spectrum in spectra) yvalues.AddRange(spectrum.Elements.Select(x => x.Y)); (double yMin, double yMax) yresult = yvalues.GetBoundaries(); yMin = yresult.yMin; yMax = yresult.yMax; })); await Task.WhenAll(tasks); System.Diagnostics.Debug.WriteLine($"x: [{xMin},{xMax}], y: [{yMin},{yMax}]"); return (xMin, xMax, yMin, yMax); } private void init() { Spectra = new ObservableCollection<SpectrumModel>(); Loading Loading @@ -253,6 +213,11 @@ namespace INAF.Apps.Uwp.SLabDataManager.Charts spectrum.PropertyChanged += Spectrum_PropertyChanged; } public bool isAnySpectrumOfType(SpectrumType spectrumType) { return Spectra.Any(x => x.Type == spectrumType); } public void removeAlignedSpectrum() { removeSpectrumOfTypeAsync(SpectrumType.Aligned); Loading @@ -266,7 +231,7 @@ namespace INAF.Apps.Uwp.SLabDataManager.Charts } #endregion private void addSpectrum(SpectrumModel spectrum) public void addSpectrum(SpectrumModel spectrum) { spectrum.setColor(); Spectra.Add(spectrum); Loading Loading @@ -323,174 +288,56 @@ namespace INAF.Apps.Uwp.SLabDataManager.Charts #endregion #region boundaries private async Task setBoundariesAsync() { (double xMin, double xMax, double yMin, double yMax) result = await getSpectrumAxesBoundariesAsync(); XAxisBoundaries = new AxisBoundariesModel("x", result.xMin, result.xMax, spectra[0].Elements[0].MeasureUnit); YAxisBoundaries = new AxisBoundariesModel("y", result.yMin, result.yMax); } public async Task updateBoundariesAsync() { (double xMin, double xMax, double yMin, double yMax) result = await getSpectrumAxesBoundariesAsync(); XAxisBoundaries.updateAxisBoundaries(result.xMin, result.xMax); YAxisBoundaries.updateAxisBoundaries(result.yMin, result.yMax); } #endregion #region alignment private SpectrumModel createAlignedSpectrum() { var aligningSpectrum = (SpectrumModel)tryGetSpectrumOfType(SpectrumType.Raw).Clone(); aligningSpectrum.setType(SpectrumType.Aligned); aligningSpectrum.updateTitle(); return aligningSpectrum; } public async Task alignRawSpectrumAsync() { IsDialogRequired = false; DialogMessage = string.Empty; SpectrumModel alignedSpectrum = null; string exMsg = string.Empty; await Task.Run(() => { try { alignedSpectrum = createAlignedSpectrum(); /* try to retrieve the ref white max value for normalizing raw spectrum during alignment process */ double refWhiteMaxY = 1d; var refWhiteSpectrum = tryGetSpectrumOfType(SpectrumType.RefWhite); if (refWhiteSpectrum == null) { UpdateUIHelper.UpdateUIAsync(() => private async Task<(double xMin, double xMax, double yMin, double yMax)> getSpectrumAxesBoundariesAsync() { DialogMessageType = DialogMessageType.Warning; DialogMessage = "RefWhiteSpectrumNotAvailable".GetText(); IsDialogRequired = true; }); } else refWhiteMaxY = refWhiteSpectrum.Elements.Max(x => x.Y); List<Task> tasks = new List<Task>(); /* try to retrieve ref spectrum for normalizing raw spectrum during alignment process */ var refSpectrum = tryGetSpectrumOfType(SpectrumType.Ref); if (refSpectrum == null) { UpdateUIHelper.UpdateUIAsync(() => double xMin = 0d; double xMax = 0d; double yMin = 0d; double yMax = 0d; tasks.Add(Task.Run(() => { DialogMessageType = DialogMessageType.Warning; DialogMessage = "NoNormalizationAvailableMessage".GetText(); IsDialogRequired = true; }); } List<double> xvalues = new List<double>(); foreach (var spectrum in spectra) xvalues.AddRange(spectrum.Elements.Select(x => x.X)); /* normalize spectrum, if possible */ if (refWhiteSpectrum != null && refSpectrum != null) (double xMin, double xMax) xresult = xvalues.GetBoundaries(); xMin = xresult.xMin; xMax = xresult.xMax; })); tasks.Add(Task.Run(() => { multiplyByRef(ref alignedSpectrum, refWhiteMaxY, refSpectrum); } /* retrieve the reference segment and calculate the mean values at the borders of the segment for aligning other segments */ var refLowSeparator = SpectrumAlignmentConfig.WavelengthSeparators.FirstOrDefault(x => x.CurrentValue >= SelectedRefBand.XMin && x.CurrentValue <= SelectedRefBand.XMax); var refHighSeparator = SpectrumAlignmentConfig.WavelengthSeparators.FirstOrDefault(x => x.CurrentValue > refLowSeparator.CurrentValue); var refSegment = alignedSpectrum.GetCenterSegmentElements(refLowSeparator.CurrentValue, refHighSeparator.CurrentValue); double refSegmentLeftMean = refSegment.GetSegmentLeftMeanValue(SpectrumAlignmentConfig.NumOfPointsForAlignment); double refSegmentRightMean = refSegment.GetSegmentRightMeanValue(SpectrumAlignmentConfig.NumOfPointsForAlignment); List<double> yvalues = new List<double>(); foreach (var spectrum in spectra) yvalues.AddRange(spectrum.Elements.Select(x => x.Y)); (double yMin, double yMax) yresult = yvalues.GetBoundaries(); yMin = yresult.yMin; yMax = yresult.yMax; })); /* retrieve segments on the left of selected one for later alignment */ alignLeftSide(ref alignedSpectrum, refLowSeparator, refSegmentLeftMean); await Task.WhenAll(tasks); /* retrieve segments on the right of the selected one for later alignment */ alignRightSide(ref alignedSpectrum, refHighSeparator, refSegmentRightMean); } catch (Exception ex) { logger.Write<SpectraContainer>($"{nameof(alignRawSpectrumAsync)} - ex: {ex.Message}", Serilog.Events.LogEventLevel.Error); exMsg = ex.Message; } }); System.Diagnostics.Debug.WriteLine($"x: [{xMin},{xMax}], y: [{yMin},{yMax}]"); if (string.IsNullOrEmpty(exMsg)) { IsSpectrumAligned = true; addSpectrum(alignedSpectrum); } else { DialogMessage = exMsg; IsDialogRequired = true; } return (xMin, xMax, yMin, yMax); } private void alignLeftSide(ref SpectrumModel aligningSpectrum, WavelengthModel refLowSeparator, double refSegmentLeftMean) { var leftSeparators = SpectrumAlignmentConfig.WavelengthSeparators .Where(x => x.MinValue < refLowSeparator.MinValue) .OrderByDescending(x => x.MinValue); double rightSeparatorCurrentValue = refLowSeparator.CurrentValue; double refLeftValue = refSegmentLeftMean; foreach (var leftSeparator in leftSeparators) private async Task setBoundariesAsync() { var elements = aligningSpectrum .GetLeftSegmentElements(leftSeparator.CurrentValue, rightSeparatorCurrentValue) .FixLeftSegment(refLeftValue, SpectrumAlignmentConfig.NumOfPointsForAlignment); aligningSpectrum.UpdateElements(elements); (double xMin, double xMax, double yMin, double yMax) result = await getSpectrumAxesBoundariesAsync(); rightSeparatorCurrentValue = leftSeparator.CurrentValue; refLeftValue = elements.GetSegmentLeftMeanValue(SpectrumAlignmentConfig.NumOfPointsForAlignment); } XAxisBoundaries = new AxisBoundariesModel("x", result.xMin, result.xMax, spectra[0].Elements[0].MeasureUnit); YAxisBoundaries = new AxisBoundariesModel("y", result.yMin, result.yMax); } private void alignRightSide(ref SpectrumModel aligningSpectrum, WavelengthModel refHighSeparator, double refSegmentRightMean) { var rightSeparators = SpectrumAlignmentConfig.WavelengthSeparators.Where(x => x.MinValue > refHighSeparator.MinValue); double leftSeparatorCurrentValue = refHighSeparator.CurrentValue; double refRightValue = refSegmentRightMean; foreach (var rightSeparator in rightSeparators) public async Task updateBoundariesAsync() { var elements = aligningSpectrum .GetRightSegmentElements(leftSeparatorCurrentValue, rightSeparator.CurrentValue) .FixRightSegment(refRightValue, SpectrumAlignmentConfig.NumOfPointsForAlignment); aligningSpectrum.UpdateElements(elements); leftSeparatorCurrentValue = rightSeparator.CurrentValue; refRightValue = elements.GetSegmentRightMeanValue(SpectrumAlignmentConfig.NumOfPointsForAlignment); } } (double xMin, double xMax, double yMin, double yMax) result = await getSpectrumAxesBoundariesAsync(); private void multiplyByRef(ref SpectrumModel aligningSpectrum, double refWhiteMaxY, SpectrumModel refSpectrum) { aligningSpectrum.Elements .AsParallel() .ForAll(x => { var refElement = refSpectrum.Elements.FirstOrDefault(y => y.X == x.X); x.updateY(x.Y * refElement.Y / refWhiteMaxY); }); XAxisBoundaries.updateAxisBoundaries(result.xMin, result.xMax); YAxisBoundaries.updateAxisBoundaries(result.yMin, result.yMax); } #endregion } Loading INAF.Apps.Uwp.SLabDataManager/Converters/Converters.cs +26 −0 Original line number Diff line number Diff line Loading @@ -2,17 +2,43 @@ using INAF.Apps.Uwp.SLabDataManager.Helpers; using INAF.Apps.Uwp.SLabDataManager.Models; using INAF.Libraries.NetStandard.Extensions; using INAF.Libraries.NetStandard.ScienceModels.Extensions; using Microsoft.Toolkit.Mvvm.DependencyInjection; using System; using System.Collections.Generic; using System.IO; using Telerik.Charting; using Windows.UI.Xaml; using Windows.UI.Xaml.Data; using Windows.UI.Xaml.Media; using static INAF.Libraries.NetStandard.SLabCommonModels.Enums.Enums; namespace INAF.Apps.Uwp.SLabDataManager.Converters { public sealed class IsSpectrumAvailablelWithParameterConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, string language) { try { string _spectrumType = (string)parameter; SpectrumType spectrumType = _spectrumType.ToSpectrumType(); SpectraContainer spectraContainer = Ioc.Default.GetService<SpectraContainer>(); return spectraContainer.isAnySpectrumOfType(spectrumType); } catch (Exception) { return false; } } public object ConvertBack(object value, Type targetType, object parameter, string language) { throw new NotImplementedException(); } } public sealed class ChartDataPointConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, string language) Loading INAF.Apps.Uwp.SLabDataManager/Helpers/UI/Chart/ChartAnnotationsHelper.cs +19 −6 Original line number Diff line number Diff line Loading @@ -13,17 +13,17 @@ namespace INAF.Apps.Uwp.SLabDataManager.Helpers.UI.Chart { public sealed class ChartAnnotationsHelper { private readonly CustomAnnotationsRepository customAnnotationsRepository; private readonly CustomLinesAnnotationsRepository customAnnotationsRepository; private readonly Logger logger; public ChartAnnotationsHelper(CustomAnnotationsRepository customAnnotationsRepository, public ChartAnnotationsHelper(CustomLinesAnnotationsRepository customAnnotationsRepository, Logger logger) { this.customAnnotationsRepository = customAnnotationsRepository; this.logger = logger; } public void addOrRemoveTappedPoint(RadCartesianChart chart, public void addOrRemoveTappedPointForContinuum(RadCartesianChart chart, Point mousePosition, DataTemplate tappedPointTemplate) { Loading @@ -33,7 +33,9 @@ namespace INAF.Apps.Uwp.SLabDataManager.Helpers.UI.Chart System.Diagnostics.Debug.WriteLine($"point: {point.Item1}, {point.Item2}"); /* if a point in selected position already exists, then remove it... */ var existantItem = chart.Annotations.FirstOrDefault(x => x is CartesianCustomAnnotation && Convert.ToDouble((x as CartesianCustomAnnotation).HorizontalValue) >= ((double)point.Item1 - 12d) && (Convert.ToDouble((x as CartesianCustomAnnotation).HorizontalValue) <= (double)point.Item1 + 12)); var existantItem = chart.Annotations.FirstOrDefault(x => x is CartesianCustomAnnotation && (Convert.ToDouble((x as CartesianCustomAnnotation).HorizontalValue) >= ((double)point.Item1 - 12d)) && (Convert.ToDouble((x as CartesianCustomAnnotation).HorizontalValue) <= ((double)point.Item1 + 12d))); if (existantItem != null) chart.Annotations.Remove(existantItem); else Loading Loading @@ -113,5 +115,16 @@ namespace INAF.Apps.Uwp.SLabDataManager.Helpers.UI.Chart logger.Write<ChartAnnotationsHelper>($"{nameof(tryCreateLines)} - ex: {ex.Message}", Serilog.Events.LogEventLevel.Error); } } public void removePointsForContinuum(RadCartesianChart chart) { int annotationsNum = chart.Annotations.Count(); for (int i = annotationsNum - 1; i >= 0; i--) { if (chart.Annotations.ElementAt(i).GetType() == typeof(CartesianCustomAnnotation) || chart.Annotations.ElementAt(i).GetType() == typeof(CartesianCustomLineAnnotation)) chart.Annotations.Remove(chart.Annotations.ElementAt(i)); } } } } INAF.Apps.Uwp.SLabDataManager/Helpers/UI/Chart/CustomAnnotationsRepository.cs→INAF.Apps.Uwp.SLabDataManager/Helpers/UI/Chart/CustomLinesAnnotationsRepository.cs +25 −2 Original line number Diff line number Diff line using INAF.Libraries.NetStandard.ScienceModels.Lines; using System.Collections.Generic; using System.Linq; namespace INAF.Apps.Uwp.SLabDataManager.Helpers.UI.Chart { public class CustomAnnotationsRepository public class CustomLinesAnnotationsRepository { public CustomAnnotationsRepository() public CustomLinesAnnotationsRepository() { CustomLineAnnotations = new List<StraightLineModel>(); } Loading @@ -15,11 +16,33 @@ namespace INAF.Apps.Uwp.SLabDataManager.Helpers.UI.Chart public void add(StraightLineModel annotation) { CustomLineAnnotations.Add(annotation); CustomLineAnnotations = CustomLineAnnotations .OrderBy(t => t.P1.X) .ToList(); } public void clear() { CustomLineAnnotations.Clear(); } public StraightLineModel getLine(double x) { var line = CustomLineAnnotations.FirstOrDefault(t => x >= t.P1.X && x <= t.P2.X); if (line == null) { if (x < CustomLineAnnotations.First().P1.X) line = CustomLineAnnotations.First(); else if (x > CustomLineAnnotations.Last().P2.X) line = CustomLineAnnotations.Last(); } return line; } public bool isAnyLineAvailable() { return CustomLineAnnotations.Count >= 1; } } } Loading
INAF.Apps.Uwp.SLabDataManager/App.xaml.cs +3 −2 Original line number Diff line number Diff line Loading @@ -100,7 +100,7 @@ namespace INAF.Apps.Uwp.SLabDataManager Ioc.Default.ConfigureServices( new ServiceCollection() /* singletons */ .AddSingleton<CustomAnnotationsRepository>() .AddSingleton<CustomLinesAnnotationsRepository>() .AddSingleton<SelectedRefBand>() .AddSingleton<SpectrumAlignmentConfigModel>() .AddSingleton<SpectrumChartOptionsModel>() Loading @@ -121,10 +121,11 @@ namespace INAF.Apps.Uwp.SLabDataManager .AddTransient<RemoteOperationsManager>() .AddTransient<RemoteOperationsXmlReader>() .AddTransient<SpectrumModelFactory>() .AddTransient<SpectrumProcessingHelper>() .AddTransient<SpectrumReader>() .AddTransient<XmlHelper>() /* view models */ .AddTransient<ChartViewModel>() .AddSingleton<ChartViewModel>() .AddTransient<LoginViewModel>() .AddTransient<LoginCheckViewModel>() .AddSingleton<MainViewModel>() Loading
INAF.Apps.Uwp.SLabDataManager/Charts/SpectraContainer.cs +58 −211 Original line number Diff line number Diff line using INAF.Apps.Uwp.SLabDataManager.Extensions; using INAF.Apps.Uwp.SLabDataManager.Helpers; using INAF.Apps.Uwp.SLabDataManager.Helpers; using INAF.Apps.Uwp.SLabDataManager.Models; using INAF.Libraries.NetStandard.ScienceModels.Extensions; using INAF.Libraries.NetStandard.ScienceModels.Spectra; Loading @@ -19,13 +18,9 @@ namespace INAF.Apps.Uwp.SLabDataManager.Charts { public class SpectraContainer : ObservableObject { private readonly Logger logger; public SpectraContainer(IServiceProvider serviceProvider, Logger logger) { this.logger = logger; SpectrumAlignmentConfig = serviceProvider.GetRequiredService<SpectrumAlignmentConfigModel>(); SelectedRefBand = serviceProvider.GetRequiredService<SelectedRefBand>(); Loading @@ -42,19 +37,8 @@ namespace INAF.Apps.Uwp.SLabDataManager.Charts } #region properties public string DialogMessage { get; private set; } public DialogMessageType DialogMessageType { get; private set; } public bool IsAlignedSpectrumSaved { get; set; } private bool isDialogRequired; public bool IsDialogRequired { get { return isDialogRequired; } set { SetProperty(ref isDialogRequired, value); } } private bool isAnySummaryUpdated; public bool IsAnySummaryUpdated { Loading @@ -62,8 +46,6 @@ namespace INAF.Apps.Uwp.SLabDataManager.Charts set { SetProperty(ref isAnySummaryUpdated, value); } } public bool IsSpectrumAligned { get; set; } private bool isAnySpectrumLoaded; public bool IsAnySpectrumLoaded { Loading @@ -86,7 +68,19 @@ namespace INAF.Apps.Uwp.SLabDataManager.Charts } } public SelectedRefBand SelectedRefBand { get; private set; } private bool isSpectrumAligned; public bool IsSpectrumAligned { get { return isSpectrumAligned; } set { SetProperty(ref isSpectrumAligned, value); } } private bool isSpectrumContinuumRemoved; public bool IsSpectrumContinuumRemoved { get { return isSpectrumContinuumRemoved; } set { SetProperty(ref isSpectrumContinuumRemoved, value); } } private ObservableCollection<SpectrumModel> spectra; public ObservableCollection<SpectrumModel> Spectra Loading @@ -95,6 +89,10 @@ namespace INAF.Apps.Uwp.SLabDataManager.Charts private set { SetProperty(ref spectra, value); } } public SelectedRefBand SelectedRefBand { get; private set; } public SpectrumAlignmentConfigModel SpectrumAlignmentConfig { get; private set; } private ObservableCollection<SpectrumSummaryModel> summaries; public ObservableCollection<SpectrumSummaryModel> Summaries { Loading @@ -102,8 +100,6 @@ namespace INAF.Apps.Uwp.SLabDataManager.Charts private set { SetProperty(ref summaries, value); } } public SpectrumAlignmentConfigModel SpectrumAlignmentConfig { get; private set; } #region spectrums min/max private AxisBoundariesModel xAxisBoundaries; public AxisBoundariesModel XAxisBoundaries Loading Loading @@ -146,42 +142,6 @@ namespace INAF.Apps.Uwp.SLabDataManager.Charts Spectra.Clear(); } private async Task<(double xMin, double xMax, double yMin, double yMax)> getSpectrumAxesBoundariesAsync() { List<Task> tasks = new List<Task>(); double xMin = 0d; double xMax = 0d; double yMin = 0d; double yMax = 0d; tasks.Add(Task.Run(() => { List<double> xvalues = new List<double>(); foreach (var spectrum in spectra) xvalues.AddRange(spectrum.Elements.Select(x => x.X)); (double xMin, double xMax) xresult = xvalues.GetBoundaries(); xMin = xresult.xMin; xMax = xresult.xMax; })); tasks.Add(Task.Run(() => { List<double> yvalues = new List<double>(); foreach (var spectrum in spectra) yvalues.AddRange(spectrum.Elements.Select(x => x.Y)); (double yMin, double yMax) yresult = yvalues.GetBoundaries(); yMin = yresult.yMin; yMax = yresult.yMax; })); await Task.WhenAll(tasks); System.Diagnostics.Debug.WriteLine($"x: [{xMin},{xMax}], y: [{yMin},{yMax}]"); return (xMin, xMax, yMin, yMax); } private void init() { Spectra = new ObservableCollection<SpectrumModel>(); Loading Loading @@ -253,6 +213,11 @@ namespace INAF.Apps.Uwp.SLabDataManager.Charts spectrum.PropertyChanged += Spectrum_PropertyChanged; } public bool isAnySpectrumOfType(SpectrumType spectrumType) { return Spectra.Any(x => x.Type == spectrumType); } public void removeAlignedSpectrum() { removeSpectrumOfTypeAsync(SpectrumType.Aligned); Loading @@ -266,7 +231,7 @@ namespace INAF.Apps.Uwp.SLabDataManager.Charts } #endregion private void addSpectrum(SpectrumModel spectrum) public void addSpectrum(SpectrumModel spectrum) { spectrum.setColor(); Spectra.Add(spectrum); Loading Loading @@ -323,174 +288,56 @@ namespace INAF.Apps.Uwp.SLabDataManager.Charts #endregion #region boundaries private async Task setBoundariesAsync() { (double xMin, double xMax, double yMin, double yMax) result = await getSpectrumAxesBoundariesAsync(); XAxisBoundaries = new AxisBoundariesModel("x", result.xMin, result.xMax, spectra[0].Elements[0].MeasureUnit); YAxisBoundaries = new AxisBoundariesModel("y", result.yMin, result.yMax); } public async Task updateBoundariesAsync() { (double xMin, double xMax, double yMin, double yMax) result = await getSpectrumAxesBoundariesAsync(); XAxisBoundaries.updateAxisBoundaries(result.xMin, result.xMax); YAxisBoundaries.updateAxisBoundaries(result.yMin, result.yMax); } #endregion #region alignment private SpectrumModel createAlignedSpectrum() { var aligningSpectrum = (SpectrumModel)tryGetSpectrumOfType(SpectrumType.Raw).Clone(); aligningSpectrum.setType(SpectrumType.Aligned); aligningSpectrum.updateTitle(); return aligningSpectrum; } public async Task alignRawSpectrumAsync() { IsDialogRequired = false; DialogMessage = string.Empty; SpectrumModel alignedSpectrum = null; string exMsg = string.Empty; await Task.Run(() => { try { alignedSpectrum = createAlignedSpectrum(); /* try to retrieve the ref white max value for normalizing raw spectrum during alignment process */ double refWhiteMaxY = 1d; var refWhiteSpectrum = tryGetSpectrumOfType(SpectrumType.RefWhite); if (refWhiteSpectrum == null) { UpdateUIHelper.UpdateUIAsync(() => private async Task<(double xMin, double xMax, double yMin, double yMax)> getSpectrumAxesBoundariesAsync() { DialogMessageType = DialogMessageType.Warning; DialogMessage = "RefWhiteSpectrumNotAvailable".GetText(); IsDialogRequired = true; }); } else refWhiteMaxY = refWhiteSpectrum.Elements.Max(x => x.Y); List<Task> tasks = new List<Task>(); /* try to retrieve ref spectrum for normalizing raw spectrum during alignment process */ var refSpectrum = tryGetSpectrumOfType(SpectrumType.Ref); if (refSpectrum == null) { UpdateUIHelper.UpdateUIAsync(() => double xMin = 0d; double xMax = 0d; double yMin = 0d; double yMax = 0d; tasks.Add(Task.Run(() => { DialogMessageType = DialogMessageType.Warning; DialogMessage = "NoNormalizationAvailableMessage".GetText(); IsDialogRequired = true; }); } List<double> xvalues = new List<double>(); foreach (var spectrum in spectra) xvalues.AddRange(spectrum.Elements.Select(x => x.X)); /* normalize spectrum, if possible */ if (refWhiteSpectrum != null && refSpectrum != null) (double xMin, double xMax) xresult = xvalues.GetBoundaries(); xMin = xresult.xMin; xMax = xresult.xMax; })); tasks.Add(Task.Run(() => { multiplyByRef(ref alignedSpectrum, refWhiteMaxY, refSpectrum); } /* retrieve the reference segment and calculate the mean values at the borders of the segment for aligning other segments */ var refLowSeparator = SpectrumAlignmentConfig.WavelengthSeparators.FirstOrDefault(x => x.CurrentValue >= SelectedRefBand.XMin && x.CurrentValue <= SelectedRefBand.XMax); var refHighSeparator = SpectrumAlignmentConfig.WavelengthSeparators.FirstOrDefault(x => x.CurrentValue > refLowSeparator.CurrentValue); var refSegment = alignedSpectrum.GetCenterSegmentElements(refLowSeparator.CurrentValue, refHighSeparator.CurrentValue); double refSegmentLeftMean = refSegment.GetSegmentLeftMeanValue(SpectrumAlignmentConfig.NumOfPointsForAlignment); double refSegmentRightMean = refSegment.GetSegmentRightMeanValue(SpectrumAlignmentConfig.NumOfPointsForAlignment); List<double> yvalues = new List<double>(); foreach (var spectrum in spectra) yvalues.AddRange(spectrum.Elements.Select(x => x.Y)); (double yMin, double yMax) yresult = yvalues.GetBoundaries(); yMin = yresult.yMin; yMax = yresult.yMax; })); /* retrieve segments on the left of selected one for later alignment */ alignLeftSide(ref alignedSpectrum, refLowSeparator, refSegmentLeftMean); await Task.WhenAll(tasks); /* retrieve segments on the right of the selected one for later alignment */ alignRightSide(ref alignedSpectrum, refHighSeparator, refSegmentRightMean); } catch (Exception ex) { logger.Write<SpectraContainer>($"{nameof(alignRawSpectrumAsync)} - ex: {ex.Message}", Serilog.Events.LogEventLevel.Error); exMsg = ex.Message; } }); System.Diagnostics.Debug.WriteLine($"x: [{xMin},{xMax}], y: [{yMin},{yMax}]"); if (string.IsNullOrEmpty(exMsg)) { IsSpectrumAligned = true; addSpectrum(alignedSpectrum); } else { DialogMessage = exMsg; IsDialogRequired = true; } return (xMin, xMax, yMin, yMax); } private void alignLeftSide(ref SpectrumModel aligningSpectrum, WavelengthModel refLowSeparator, double refSegmentLeftMean) { var leftSeparators = SpectrumAlignmentConfig.WavelengthSeparators .Where(x => x.MinValue < refLowSeparator.MinValue) .OrderByDescending(x => x.MinValue); double rightSeparatorCurrentValue = refLowSeparator.CurrentValue; double refLeftValue = refSegmentLeftMean; foreach (var leftSeparator in leftSeparators) private async Task setBoundariesAsync() { var elements = aligningSpectrum .GetLeftSegmentElements(leftSeparator.CurrentValue, rightSeparatorCurrentValue) .FixLeftSegment(refLeftValue, SpectrumAlignmentConfig.NumOfPointsForAlignment); aligningSpectrum.UpdateElements(elements); (double xMin, double xMax, double yMin, double yMax) result = await getSpectrumAxesBoundariesAsync(); rightSeparatorCurrentValue = leftSeparator.CurrentValue; refLeftValue = elements.GetSegmentLeftMeanValue(SpectrumAlignmentConfig.NumOfPointsForAlignment); } XAxisBoundaries = new AxisBoundariesModel("x", result.xMin, result.xMax, spectra[0].Elements[0].MeasureUnit); YAxisBoundaries = new AxisBoundariesModel("y", result.yMin, result.yMax); } private void alignRightSide(ref SpectrumModel aligningSpectrum, WavelengthModel refHighSeparator, double refSegmentRightMean) { var rightSeparators = SpectrumAlignmentConfig.WavelengthSeparators.Where(x => x.MinValue > refHighSeparator.MinValue); double leftSeparatorCurrentValue = refHighSeparator.CurrentValue; double refRightValue = refSegmentRightMean; foreach (var rightSeparator in rightSeparators) public async Task updateBoundariesAsync() { var elements = aligningSpectrum .GetRightSegmentElements(leftSeparatorCurrentValue, rightSeparator.CurrentValue) .FixRightSegment(refRightValue, SpectrumAlignmentConfig.NumOfPointsForAlignment); aligningSpectrum.UpdateElements(elements); leftSeparatorCurrentValue = rightSeparator.CurrentValue; refRightValue = elements.GetSegmentRightMeanValue(SpectrumAlignmentConfig.NumOfPointsForAlignment); } } (double xMin, double xMax, double yMin, double yMax) result = await getSpectrumAxesBoundariesAsync(); private void multiplyByRef(ref SpectrumModel aligningSpectrum, double refWhiteMaxY, SpectrumModel refSpectrum) { aligningSpectrum.Elements .AsParallel() .ForAll(x => { var refElement = refSpectrum.Elements.FirstOrDefault(y => y.X == x.X); x.updateY(x.Y * refElement.Y / refWhiteMaxY); }); XAxisBoundaries.updateAxisBoundaries(result.xMin, result.xMax); YAxisBoundaries.updateAxisBoundaries(result.yMin, result.yMax); } #endregion } Loading
INAF.Apps.Uwp.SLabDataManager/Converters/Converters.cs +26 −0 Original line number Diff line number Diff line Loading @@ -2,17 +2,43 @@ using INAF.Apps.Uwp.SLabDataManager.Helpers; using INAF.Apps.Uwp.SLabDataManager.Models; using INAF.Libraries.NetStandard.Extensions; using INAF.Libraries.NetStandard.ScienceModels.Extensions; using Microsoft.Toolkit.Mvvm.DependencyInjection; using System; using System.Collections.Generic; using System.IO; using Telerik.Charting; using Windows.UI.Xaml; using Windows.UI.Xaml.Data; using Windows.UI.Xaml.Media; using static INAF.Libraries.NetStandard.SLabCommonModels.Enums.Enums; namespace INAF.Apps.Uwp.SLabDataManager.Converters { public sealed class IsSpectrumAvailablelWithParameterConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, string language) { try { string _spectrumType = (string)parameter; SpectrumType spectrumType = _spectrumType.ToSpectrumType(); SpectraContainer spectraContainer = Ioc.Default.GetService<SpectraContainer>(); return spectraContainer.isAnySpectrumOfType(spectrumType); } catch (Exception) { return false; } } public object ConvertBack(object value, Type targetType, object parameter, string language) { throw new NotImplementedException(); } } public sealed class ChartDataPointConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, string language) Loading
INAF.Apps.Uwp.SLabDataManager/Helpers/UI/Chart/ChartAnnotationsHelper.cs +19 −6 Original line number Diff line number Diff line Loading @@ -13,17 +13,17 @@ namespace INAF.Apps.Uwp.SLabDataManager.Helpers.UI.Chart { public sealed class ChartAnnotationsHelper { private readonly CustomAnnotationsRepository customAnnotationsRepository; private readonly CustomLinesAnnotationsRepository customAnnotationsRepository; private readonly Logger logger; public ChartAnnotationsHelper(CustomAnnotationsRepository customAnnotationsRepository, public ChartAnnotationsHelper(CustomLinesAnnotationsRepository customAnnotationsRepository, Logger logger) { this.customAnnotationsRepository = customAnnotationsRepository; this.logger = logger; } public void addOrRemoveTappedPoint(RadCartesianChart chart, public void addOrRemoveTappedPointForContinuum(RadCartesianChart chart, Point mousePosition, DataTemplate tappedPointTemplate) { Loading @@ -33,7 +33,9 @@ namespace INAF.Apps.Uwp.SLabDataManager.Helpers.UI.Chart System.Diagnostics.Debug.WriteLine($"point: {point.Item1}, {point.Item2}"); /* if a point in selected position already exists, then remove it... */ var existantItem = chart.Annotations.FirstOrDefault(x => x is CartesianCustomAnnotation && Convert.ToDouble((x as CartesianCustomAnnotation).HorizontalValue) >= ((double)point.Item1 - 12d) && (Convert.ToDouble((x as CartesianCustomAnnotation).HorizontalValue) <= (double)point.Item1 + 12)); var existantItem = chart.Annotations.FirstOrDefault(x => x is CartesianCustomAnnotation && (Convert.ToDouble((x as CartesianCustomAnnotation).HorizontalValue) >= ((double)point.Item1 - 12d)) && (Convert.ToDouble((x as CartesianCustomAnnotation).HorizontalValue) <= ((double)point.Item1 + 12d))); if (existantItem != null) chart.Annotations.Remove(existantItem); else Loading Loading @@ -113,5 +115,16 @@ namespace INAF.Apps.Uwp.SLabDataManager.Helpers.UI.Chart logger.Write<ChartAnnotationsHelper>($"{nameof(tryCreateLines)} - ex: {ex.Message}", Serilog.Events.LogEventLevel.Error); } } public void removePointsForContinuum(RadCartesianChart chart) { int annotationsNum = chart.Annotations.Count(); for (int i = annotationsNum - 1; i >= 0; i--) { if (chart.Annotations.ElementAt(i).GetType() == typeof(CartesianCustomAnnotation) || chart.Annotations.ElementAt(i).GetType() == typeof(CartesianCustomLineAnnotation)) chart.Annotations.Remove(chart.Annotations.ElementAt(i)); } } } }
INAF.Apps.Uwp.SLabDataManager/Helpers/UI/Chart/CustomAnnotationsRepository.cs→INAF.Apps.Uwp.SLabDataManager/Helpers/UI/Chart/CustomLinesAnnotationsRepository.cs +25 −2 Original line number Diff line number Diff line using INAF.Libraries.NetStandard.ScienceModels.Lines; using System.Collections.Generic; using System.Linq; namespace INAF.Apps.Uwp.SLabDataManager.Helpers.UI.Chart { public class CustomAnnotationsRepository public class CustomLinesAnnotationsRepository { public CustomAnnotationsRepository() public CustomLinesAnnotationsRepository() { CustomLineAnnotations = new List<StraightLineModel>(); } Loading @@ -15,11 +16,33 @@ namespace INAF.Apps.Uwp.SLabDataManager.Helpers.UI.Chart public void add(StraightLineModel annotation) { CustomLineAnnotations.Add(annotation); CustomLineAnnotations = CustomLineAnnotations .OrderBy(t => t.P1.X) .ToList(); } public void clear() { CustomLineAnnotations.Clear(); } public StraightLineModel getLine(double x) { var line = CustomLineAnnotations.FirstOrDefault(t => x >= t.P1.X && x <= t.P2.X); if (line == null) { if (x < CustomLineAnnotations.First().P1.X) line = CustomLineAnnotations.First(); else if (x > CustomLineAnnotations.Last().P2.X) line = CustomLineAnnotations.Last(); } return line; } public bool isAnyLineAvailable() { return CustomLineAnnotations.Count >= 1; } } }