Loading INAF.Apps.Uwp.SLabDataManager/Charts/Containers/SpectraContainer.cs +6 −0 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ using INAF.Libraries.Uwp.Logging; using Microsoft.Extensions.DependencyInjection; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Threading.Tasks; Loading Loading @@ -87,6 +88,11 @@ namespace INAF.Apps.Uwp.SLabDataManager.Charts.Containers IsAlignedSpectrumSaved = false; } public IEnumerable<SpectrumModel> tryGetSpectraOfTypeOtherThan(IEnumerable<SpectrumType> spectrumTypes) { return Spectra.Where(x => !spectrumTypes.Contains(x.Type)); } public SpectrumModel tryGetSpectrumOfType(SpectrumType spectrumType) { return Spectra.FirstOrDefault(x => x.Type == spectrumType); Loading INAF.Apps.Uwp.SLabDataManager/Helpers/UI/Chart/ChartAnnotationsHelper.cs +22 −14 Original line number Diff line number Diff line Loading @@ -44,17 +44,18 @@ namespace INAF.Apps.Uwp.SLabDataManager.Helpers.UI.Chart try { var segmentsFitModelContainer = serviceProvider.GetRequiredService<SegmentsFitModelContainer>(); /* retrieve coord on chart from mouse coords on screen */ var point = chart.ConvertPointToData(mousePosition); System.Diagnostics.Debug.WriteLine($"point: {point.Item1}, {point.Item2}"); /* recover tapped-point y-value on spectrum */ /* find mouse position boundaris on spectrum */ /* find closest points on spectrum to mouse position */ var spectrum = workingItems.SpectraContainer.tryGetSpectrumOfType(SpectrumType.Raw); (PointModel lowBoundary, PointModel highBoundary) boundaries = getSegmentBoundaries(spectrum, (double)point.Item1, (double)point.Item2); //var lowerBoundaryPoint = spectrum.Elements.Where(x => x.X <= (double)point.Item1).LastOrDefault().ToPointModel(); //var higherBoundaryPoint = spectrum.Elements.Where(x => x.X >= (double)point.Item1).FirstOrDefault().ToPointModel(); var lowerBoundaryPoint = boundaries.lowBoundary; var higherBoundaryPoint = boundaries.highBoundary; Loading @@ -70,17 +71,21 @@ namespace INAF.Apps.Uwp.SLabDataManager.Helpers.UI.Chart /* if already existant, then remove point from chart */ chart.Annotations.Remove(existantItem); /* also remove segments having current point as boundary point */ var segmentsFitModelContainer = serviceProvider.GetRequiredService<SegmentsFitModelContainer>(); segmentsFitModelContainer.removeSegmentsWithBoundaryPoint(((CartesianCustomAnnotation)existantItem).ToPointModel()); segmentsFitModelContainer.removeOldSegmentsAndAddNewOne(((CartesianCustomAnnotation)existantItem).ToPointModel()); } else { /* create line with recovered points */ var line = new StraightLineModel(lowerBoundaryPoint, higherBoundaryPoint); //addCustomLineAnnotation(line); /* calculate y on spectrum */ var line = new StraightLineModel(lowerBoundaryPoint, higherBoundaryPoint); var yOnSpectrum = line.calculateY((double)point.Item1); /* create new point to be used for new segment(s) */ var pointModel = new PointModel((double)point.Item1, yOnSpectrum); /* if new point belongs to an existant segment, then it is removed and 2 new segments are created */ if (segmentsFitModelContainer.isPointContainedInExistingSegment(pointModel)) segmentsFitModelContainer.removeOldSegmentAndAddNewOnes(pointModel); /* ...otherwise add a new point */ chart.Annotations.Add(getCustomAnnotation((double)point.Item1, yOnSpectrum, tappedPointTemplate)); } Loading @@ -93,7 +98,7 @@ namespace INAF.Apps.Uwp.SLabDataManager.Helpers.UI.Chart return; /* try to create lines connecting selected points */ await createLinesAsync(chart); addNewSegments(chart); } catch (Exception ex) { Loading @@ -101,7 +106,7 @@ namespace INAF.Apps.Uwp.SLabDataManager.Helpers.UI.Chart } } private async Task createLinesAsync(RadCartesianChart chart) private void addNewSegments(RadCartesianChart chart) { /* recover points on chart and order them for creating segments */ var orderedPoints = chart.Annotations Loading @@ -119,14 +124,17 @@ namespace INAF.Apps.Uwp.SLabDataManager.Helpers.UI.Chart for (int i = 0; i < pointsNum - 1; i++) { /* try adding new segment, only the new segment is returned, if segment is already existant, then method returns null */ var testNewSegment = segmentsFitModelContainer.tryAddSegment(orderedPoints.ElementAt(i).ToPointModel(), orderedPoints.ElementAt(i + 1).ToPointModel()); var testNewSegment = segmentsFitModelContainer.tryAddOrInsertSegment(orderedPoints.ElementAt(i).ToPointModel(), orderedPoints.ElementAt(i + 1).ToPointModel()); if (testNewSegment != null) newSegment = testNewSegment; } /* fit new segment(s) */ var viewModel = serviceProvider.GetRequiredService<ChartViewModel>(); await viewModel.fitSelectedSegmentAsync(newSegment); } segmentsFitModelContainer.SegmentsFitModels .Where(x => !x.IsShown) .ToList() .ForEach(async x => await viewModel.fitSelectedSegmentAsync(x)); } public void removePointsForContinuum(RadCartesianChart chart) { Loading INAF.Apps.Uwp.SLabDataManager/Helpers/UI/LegendItemsHelper.cs +63 −0 Original line number Diff line number Diff line using INAF.Apps.Uwp.SLabDataManager.Charts.Containers; using INAF.Apps.Uwp.SLabDataManager.Helpers.UI.Chart; using INAF.Apps.Uwp.SLabDataManager.Models.Spectrum; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Threading.Tasks; Loading Loading @@ -50,6 +51,45 @@ namespace INAF.Apps.Uwp.SLabDataManager.Helpers.UI } public static async Task HandleChartLegendItemTappedAsync(RadCartesianChart spectrumChart, RadLegendControl chartLegend, LegendItem tappedLegendItem, SpectraContainerBase spectraContainerBase, Visibility? requestedVisibility = null) { LegendItem legendItem = tappedLegendItem; var series = spectrumChart.Series; var selectedSeries = series.FirstOrDefault(x => (x.DataContext as SpectrumModel).Title.Equals(legendItem.Title)); if (selectedSeries == null) return; /* target visibility is opposite of current spectrum visibility */ Visibility targetVisibility = (selectedSeries.Visibility == Visibility.Visible) ? Visibility.Collapsed : Visibility.Visible; if (requestedVisibility != null) targetVisibility = (Visibility)requestedVisibility; switch (targetVisibility) { case Visibility.Visible: selectedSeries.Visibility = Visibility.Visible; ((selectedSeries.DataContext) as SpectrumModel).IsVisible = true; (chartLegend.LegendItems.FirstOrDefault(x => x.Title.Equals(legendItem.Title)) as LegendItemExtension).Opacity = 1; break; case Visibility.Collapsed: selectedSeries.Visibility = Visibility.Collapsed; ((selectedSeries.DataContext) as SpectrumModel).IsVisible = false; (chartLegend.LegendItems.FirstOrDefault(x => x.Title.Equals(legendItem.Title)) as LegendItemExtension).Opacity = 0.5; break; } /* refresh boundaries to match only visible spectra */ await spectraContainerBase.updateBoundariesAsync(); await Task.Delay(500); spectrumChart.InvalidateUI(); } public static async Task HandleChartLegendItemTappedAsyncOld(RadCartesianChart spectrumChart, RadLegendControl chartLegend, LegendItem tappedLegendItem, SpectraContainerBase spectraContainerBase) Loading Loading @@ -95,5 +135,28 @@ namespace INAF.Apps.Uwp.SLabDataManager.Helpers.UI await Task.Delay(500); spectrumChart.InvalidateUI(); } public static async Task HandletFocusEnablingAsync(RadCartesianChart spectrumChart, RadLegendControl chartLegend, IEnumerable<SpectrumModel> spectraToBeChanged, SpectraContainerBase spectraContainerBase, bool isFocusRequired) { if (chartLegend.LegendItems?.Count() > 0 && spectraToBeChanged?.Count() > 0) { IEnumerable<string> titlesToBeHidden = spectraToBeChanged.Select(x => x.Title); int legendItemsToBeHiddenNum = chartLegend.LegendItems.Count(); for (int i = 0; i < legendItemsToBeHiddenNum; i++) { if (titlesToBeHidden.Contains(chartLegend.LegendItems[i].Title)) await HandleChartLegendItemTappedAsync(spectrumChart, chartLegend, chartLegend.LegendItems[i], spectraContainerBase, (isFocusRequired ? Visibility.Collapsed : Visibility.Visible)); } } } } } INAF.Apps.Uwp.SLabDataManager/Models/Fit/SegmentFitModel.cs +5 −1 Original line number Diff line number Diff line Loading @@ -19,11 +19,15 @@ namespace INAF.Apps.Uwp.SLabDataManager.Models.Fit FitMethods = new ObservableCollection<FitMethodModel>(fitMethods); IsShown = false; if (FitMethods?.Count > 0) SelectedFitMethod = FitMethods[0]; selectedFitMethod = FitMethods[0]; } #region proeprties public bool IsShown { get; set; } private PointModel p1; public PointModel P1 { Loading INAF.Apps.Uwp.SLabDataManager/Models/Fit/SegmentsFitModelContainer.cs +56 −4 Original line number Diff line number Diff line Loading @@ -47,7 +47,26 @@ namespace INAF.Apps.Uwp.SLabDataManager.Models.Fit AreSegmentsAvailable = false; } public void removeSegmentsWithBoundaryPoint(PointModel p) public bool isPointContainedInExistingSegment(PointModel p) { return (SegmentsFitModels.Any(x => x.P1.X <= p.X && x.P2.X >= p.X)); } public void removeOldSegmentAndAddNewOnes(PointModel p) { var oldSegment = SegmentsFitModels.FirstOrDefault(x => x.P1.X <= p.X && x.P2.X >= p.X); if (oldSegment == null) return; /* remove the old segment... */ SegmentsFitModels.Remove(oldSegment); /* ...and add the 2 new ones */ tryAddOrInsertSegment(oldSegment.P1, p); tryAddOrInsertSegment(p, oldSegment.P2); } public void removeOldSegmentsAndAddNewOne(PointModel p) { if (SegmentsFitModels.Any(x => x.P1.X == p.X || x.P2.X == p.X)) { Loading @@ -67,11 +86,11 @@ namespace INAF.Apps.Uwp.SLabDataManager.Models.Fit } /* add new segment in place of removed ones */ tryAddSegment(p1, p2); tryAddOrInsertSegment(p1, p2); } } public SegmentFitModel tryAddSegment(PointModel p1, PointModel p2) public SegmentFitModel tryAddOrInsertSegment(PointModel p1, PointModel p2) { SegmentFitModel newSegment = null; Loading @@ -79,9 +98,42 @@ namespace INAF.Apps.Uwp.SLabDataManager.Models.Fit { /* if not already existant, then add a new one... */ newSegment = segmentFitModelsFactory.createSegmentFitModel(p1, p2); /* if new starting-point p1 is in the middle of existing segments, then insert the new segment, * otherwise add at the end */ var segmentsStartPoints = SegmentsFitModels .Select(x => x.P1) .ToList(); int index = -1; if (segmentsStartPoints?.Count > 0) { int segmentsStartPointsNum = segmentsStartPoints.Count; for (int i = 0; i < segmentsStartPointsNum; i++) { if (p1.X < segmentsStartPoints[i].X) { index = i; break; } } } if (index == -1) SegmentsFitModels.Add(newSegment); else SegmentsFitModels.Insert(index, newSegment); //SegmentsFitModels = new ObservableCollection<SegmentFitModel>(SegmentsFitModels.OrderBy(x => x.P1.X).ToList()); AreSegmentsAvailable = true; } else { var item = SegmentsFitModels.FirstOrDefault(x => x.P1.X == p1.X && x.P2.X == p2.X); item.IsShown = true; } return newSegment; } Loading Loading
INAF.Apps.Uwp.SLabDataManager/Charts/Containers/SpectraContainer.cs +6 −0 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ using INAF.Libraries.Uwp.Logging; using Microsoft.Extensions.DependencyInjection; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Threading.Tasks; Loading Loading @@ -87,6 +88,11 @@ namespace INAF.Apps.Uwp.SLabDataManager.Charts.Containers IsAlignedSpectrumSaved = false; } public IEnumerable<SpectrumModel> tryGetSpectraOfTypeOtherThan(IEnumerable<SpectrumType> spectrumTypes) { return Spectra.Where(x => !spectrumTypes.Contains(x.Type)); } public SpectrumModel tryGetSpectrumOfType(SpectrumType spectrumType) { return Spectra.FirstOrDefault(x => x.Type == spectrumType); Loading
INAF.Apps.Uwp.SLabDataManager/Helpers/UI/Chart/ChartAnnotationsHelper.cs +22 −14 Original line number Diff line number Diff line Loading @@ -44,17 +44,18 @@ namespace INAF.Apps.Uwp.SLabDataManager.Helpers.UI.Chart try { var segmentsFitModelContainer = serviceProvider.GetRequiredService<SegmentsFitModelContainer>(); /* retrieve coord on chart from mouse coords on screen */ var point = chart.ConvertPointToData(mousePosition); System.Diagnostics.Debug.WriteLine($"point: {point.Item1}, {point.Item2}"); /* recover tapped-point y-value on spectrum */ /* find mouse position boundaris on spectrum */ /* find closest points on spectrum to mouse position */ var spectrum = workingItems.SpectraContainer.tryGetSpectrumOfType(SpectrumType.Raw); (PointModel lowBoundary, PointModel highBoundary) boundaries = getSegmentBoundaries(spectrum, (double)point.Item1, (double)point.Item2); //var lowerBoundaryPoint = spectrum.Elements.Where(x => x.X <= (double)point.Item1).LastOrDefault().ToPointModel(); //var higherBoundaryPoint = spectrum.Elements.Where(x => x.X >= (double)point.Item1).FirstOrDefault().ToPointModel(); var lowerBoundaryPoint = boundaries.lowBoundary; var higherBoundaryPoint = boundaries.highBoundary; Loading @@ -70,17 +71,21 @@ namespace INAF.Apps.Uwp.SLabDataManager.Helpers.UI.Chart /* if already existant, then remove point from chart */ chart.Annotations.Remove(existantItem); /* also remove segments having current point as boundary point */ var segmentsFitModelContainer = serviceProvider.GetRequiredService<SegmentsFitModelContainer>(); segmentsFitModelContainer.removeSegmentsWithBoundaryPoint(((CartesianCustomAnnotation)existantItem).ToPointModel()); segmentsFitModelContainer.removeOldSegmentsAndAddNewOne(((CartesianCustomAnnotation)existantItem).ToPointModel()); } else { /* create line with recovered points */ var line = new StraightLineModel(lowerBoundaryPoint, higherBoundaryPoint); //addCustomLineAnnotation(line); /* calculate y on spectrum */ var line = new StraightLineModel(lowerBoundaryPoint, higherBoundaryPoint); var yOnSpectrum = line.calculateY((double)point.Item1); /* create new point to be used for new segment(s) */ var pointModel = new PointModel((double)point.Item1, yOnSpectrum); /* if new point belongs to an existant segment, then it is removed and 2 new segments are created */ if (segmentsFitModelContainer.isPointContainedInExistingSegment(pointModel)) segmentsFitModelContainer.removeOldSegmentAndAddNewOnes(pointModel); /* ...otherwise add a new point */ chart.Annotations.Add(getCustomAnnotation((double)point.Item1, yOnSpectrum, tappedPointTemplate)); } Loading @@ -93,7 +98,7 @@ namespace INAF.Apps.Uwp.SLabDataManager.Helpers.UI.Chart return; /* try to create lines connecting selected points */ await createLinesAsync(chart); addNewSegments(chart); } catch (Exception ex) { Loading @@ -101,7 +106,7 @@ namespace INAF.Apps.Uwp.SLabDataManager.Helpers.UI.Chart } } private async Task createLinesAsync(RadCartesianChart chart) private void addNewSegments(RadCartesianChart chart) { /* recover points on chart and order them for creating segments */ var orderedPoints = chart.Annotations Loading @@ -119,14 +124,17 @@ namespace INAF.Apps.Uwp.SLabDataManager.Helpers.UI.Chart for (int i = 0; i < pointsNum - 1; i++) { /* try adding new segment, only the new segment is returned, if segment is already existant, then method returns null */ var testNewSegment = segmentsFitModelContainer.tryAddSegment(orderedPoints.ElementAt(i).ToPointModel(), orderedPoints.ElementAt(i + 1).ToPointModel()); var testNewSegment = segmentsFitModelContainer.tryAddOrInsertSegment(orderedPoints.ElementAt(i).ToPointModel(), orderedPoints.ElementAt(i + 1).ToPointModel()); if (testNewSegment != null) newSegment = testNewSegment; } /* fit new segment(s) */ var viewModel = serviceProvider.GetRequiredService<ChartViewModel>(); await viewModel.fitSelectedSegmentAsync(newSegment); } segmentsFitModelContainer.SegmentsFitModels .Where(x => !x.IsShown) .ToList() .ForEach(async x => await viewModel.fitSelectedSegmentAsync(x)); } public void removePointsForContinuum(RadCartesianChart chart) { Loading
INAF.Apps.Uwp.SLabDataManager/Helpers/UI/LegendItemsHelper.cs +63 −0 Original line number Diff line number Diff line using INAF.Apps.Uwp.SLabDataManager.Charts.Containers; using INAF.Apps.Uwp.SLabDataManager.Helpers.UI.Chart; using INAF.Apps.Uwp.SLabDataManager.Models.Spectrum; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Threading.Tasks; Loading Loading @@ -50,6 +51,45 @@ namespace INAF.Apps.Uwp.SLabDataManager.Helpers.UI } public static async Task HandleChartLegendItemTappedAsync(RadCartesianChart spectrumChart, RadLegendControl chartLegend, LegendItem tappedLegendItem, SpectraContainerBase spectraContainerBase, Visibility? requestedVisibility = null) { LegendItem legendItem = tappedLegendItem; var series = spectrumChart.Series; var selectedSeries = series.FirstOrDefault(x => (x.DataContext as SpectrumModel).Title.Equals(legendItem.Title)); if (selectedSeries == null) return; /* target visibility is opposite of current spectrum visibility */ Visibility targetVisibility = (selectedSeries.Visibility == Visibility.Visible) ? Visibility.Collapsed : Visibility.Visible; if (requestedVisibility != null) targetVisibility = (Visibility)requestedVisibility; switch (targetVisibility) { case Visibility.Visible: selectedSeries.Visibility = Visibility.Visible; ((selectedSeries.DataContext) as SpectrumModel).IsVisible = true; (chartLegend.LegendItems.FirstOrDefault(x => x.Title.Equals(legendItem.Title)) as LegendItemExtension).Opacity = 1; break; case Visibility.Collapsed: selectedSeries.Visibility = Visibility.Collapsed; ((selectedSeries.DataContext) as SpectrumModel).IsVisible = false; (chartLegend.LegendItems.FirstOrDefault(x => x.Title.Equals(legendItem.Title)) as LegendItemExtension).Opacity = 0.5; break; } /* refresh boundaries to match only visible spectra */ await spectraContainerBase.updateBoundariesAsync(); await Task.Delay(500); spectrumChart.InvalidateUI(); } public static async Task HandleChartLegendItemTappedAsyncOld(RadCartesianChart spectrumChart, RadLegendControl chartLegend, LegendItem tappedLegendItem, SpectraContainerBase spectraContainerBase) Loading Loading @@ -95,5 +135,28 @@ namespace INAF.Apps.Uwp.SLabDataManager.Helpers.UI await Task.Delay(500); spectrumChart.InvalidateUI(); } public static async Task HandletFocusEnablingAsync(RadCartesianChart spectrumChart, RadLegendControl chartLegend, IEnumerable<SpectrumModel> spectraToBeChanged, SpectraContainerBase spectraContainerBase, bool isFocusRequired) { if (chartLegend.LegendItems?.Count() > 0 && spectraToBeChanged?.Count() > 0) { IEnumerable<string> titlesToBeHidden = spectraToBeChanged.Select(x => x.Title); int legendItemsToBeHiddenNum = chartLegend.LegendItems.Count(); for (int i = 0; i < legendItemsToBeHiddenNum; i++) { if (titlesToBeHidden.Contains(chartLegend.LegendItems[i].Title)) await HandleChartLegendItemTappedAsync(spectrumChart, chartLegend, chartLegend.LegendItems[i], spectraContainerBase, (isFocusRequired ? Visibility.Collapsed : Visibility.Visible)); } } } } }
INAF.Apps.Uwp.SLabDataManager/Models/Fit/SegmentFitModel.cs +5 −1 Original line number Diff line number Diff line Loading @@ -19,11 +19,15 @@ namespace INAF.Apps.Uwp.SLabDataManager.Models.Fit FitMethods = new ObservableCollection<FitMethodModel>(fitMethods); IsShown = false; if (FitMethods?.Count > 0) SelectedFitMethod = FitMethods[0]; selectedFitMethod = FitMethods[0]; } #region proeprties public bool IsShown { get; set; } private PointModel p1; public PointModel P1 { Loading
INAF.Apps.Uwp.SLabDataManager/Models/Fit/SegmentsFitModelContainer.cs +56 −4 Original line number Diff line number Diff line Loading @@ -47,7 +47,26 @@ namespace INAF.Apps.Uwp.SLabDataManager.Models.Fit AreSegmentsAvailable = false; } public void removeSegmentsWithBoundaryPoint(PointModel p) public bool isPointContainedInExistingSegment(PointModel p) { return (SegmentsFitModels.Any(x => x.P1.X <= p.X && x.P2.X >= p.X)); } public void removeOldSegmentAndAddNewOnes(PointModel p) { var oldSegment = SegmentsFitModels.FirstOrDefault(x => x.P1.X <= p.X && x.P2.X >= p.X); if (oldSegment == null) return; /* remove the old segment... */ SegmentsFitModels.Remove(oldSegment); /* ...and add the 2 new ones */ tryAddOrInsertSegment(oldSegment.P1, p); tryAddOrInsertSegment(p, oldSegment.P2); } public void removeOldSegmentsAndAddNewOne(PointModel p) { if (SegmentsFitModels.Any(x => x.P1.X == p.X || x.P2.X == p.X)) { Loading @@ -67,11 +86,11 @@ namespace INAF.Apps.Uwp.SLabDataManager.Models.Fit } /* add new segment in place of removed ones */ tryAddSegment(p1, p2); tryAddOrInsertSegment(p1, p2); } } public SegmentFitModel tryAddSegment(PointModel p1, PointModel p2) public SegmentFitModel tryAddOrInsertSegment(PointModel p1, PointModel p2) { SegmentFitModel newSegment = null; Loading @@ -79,9 +98,42 @@ namespace INAF.Apps.Uwp.SLabDataManager.Models.Fit { /* if not already existant, then add a new one... */ newSegment = segmentFitModelsFactory.createSegmentFitModel(p1, p2); /* if new starting-point p1 is in the middle of existing segments, then insert the new segment, * otherwise add at the end */ var segmentsStartPoints = SegmentsFitModels .Select(x => x.P1) .ToList(); int index = -1; if (segmentsStartPoints?.Count > 0) { int segmentsStartPointsNum = segmentsStartPoints.Count; for (int i = 0; i < segmentsStartPointsNum; i++) { if (p1.X < segmentsStartPoints[i].X) { index = i; break; } } } if (index == -1) SegmentsFitModels.Add(newSegment); else SegmentsFitModels.Insert(index, newSegment); //SegmentsFitModels = new ObservableCollection<SegmentFitModel>(SegmentsFitModels.OrderBy(x => x.P1.X).ToList()); AreSegmentsAvailable = true; } else { var item = SegmentsFitModels.FirstOrDefault(x => x.P1.X == p1.X && x.P2.X == p2.X); item.IsShown = true; } return newSegment; } Loading