Commit 200879f4 authored by Francesco Carraro's avatar Francesco Carraro
Browse files

refactoring for spectrum alignment; alignment is now available by selecting any segment as ref

parent ee967abe
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -86,6 +86,7 @@ namespace INAF.Apps.Uwp.SLabDataManager
                .AddSingleton<Logger>(logger)
                .AddSingleton<RecentFilesHelper>()
                .AddSingleton<SettingsHelper>()
                .AddSingleton<SpectraContainer>()
                .AddSingleton<StorageItemsSettingsHelper>()
                .AddSingleton<StorageItemsAccessHelper>()
                .AddSingleton<UpdateUIHelper>()
+16 −2
Original line number Diff line number Diff line
@@ -10,9 +10,13 @@ namespace INAF.Apps.Uwp.SLabDataManager.Charts
        {
            XMin = 0d;
            XMax = 0d;

            IsReady = false;
        }

        #region properties
        public bool IsReady { get; private set; }

        private string selectedSegmentText;
        public string SelectedSegmentText
        {
@@ -24,14 +28,24 @@ namespace INAF.Apps.Uwp.SLabDataManager.Charts
        public double XMax
        {
            get { return xMax; }
            private set { SetProperty(ref xMax, value); }
            private set
            {
                SetProperty(ref xMax, value);
                if (XMin != 0 && XMax != 0)
                    IsReady = true;
            }
        }

        private double xMin;
        public double XMin
        {
            get { return xMin; }
            private set { SetProperty(ref xMin, value); }
            private set
            {
                SetProperty(ref xMin, value);
                if (XMin != 0 && XMax != 0)
                    IsReady = true;
            }
        }
        #endregion

+131 −9
Original line number Diff line number Diff line
using INAF.Libraries.NetStandard.ScienceModels.Spectra;
using Microsoft.Toolkit.Mvvm.ComponentModel;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
using static INAF.Libraries.NetStandard.ScienceModels.Enums.Enums;
using INAF.Libraries.NetStandard.ScienceModels.Extensions;
using Microsoft.Extensions.DependencyInjection;
using INAF.Apps.Uwp.SLabDataManager.Extensions;
using INAF.Libraries.Uwp.Logging;

namespace INAF.Apps.Uwp.SLabDataManager.Charts
{
    public class SpectraContainer : ObservableObject
    {
        public SpectraContainer(string yAxisTitle)
        private readonly Logger logger;

        public SpectraContainer(IServiceProvider serviceProvider,
                                Logger logger)
        {
            YAxisTitle = yAxisTitle;
            this.logger = logger;

            SpectrumAlignmentConfig = serviceProvider.GetRequiredService<SpectrumAlignmentConfigModel>();

            Spectra = new ObservableCollection<SpectrumModel>();

@@ -21,6 +31,15 @@ namespace INAF.Apps.Uwp.SLabDataManager.Charts
            XAxisMajorStepValues.Add(Constants.Constants.X_AXIS_MAJOR_STEP_100);
        }

        public string ErrorMessage { get; private set; }

        private bool isError;
        public bool IsError
        {
            get { return isError; }
            set { SetProperty(ref isError, value); }
        }

        public SelectedRefBand SelectedRefBand { get; private set; } = new SelectedRefBand();

        private ObservableCollection<SpectrumModel> spectra;
@@ -30,6 +49,8 @@ namespace INAF.Apps.Uwp.SLabDataManager.Charts
            private set { SetProperty(ref spectra, value); }
        }

        public SpectrumAlignmentConfigModel SpectrumAlignmentConfig { get; private set; }

        #region spectrums min/max
        private AxisBoundariesModel xAxisBoundaries;
        public AxisBoundariesModel XAxisBoundaries
@@ -45,7 +66,7 @@ namespace INAF.Apps.Uwp.SLabDataManager.Charts
            private set { SetProperty(ref yAxisBoundaries, value); }
        }

        public string YAxisTitle { get; set; }
        public string YAxisTitle { get; private set; }

        #region x axis major step
        private double selectedXAxisMajorStep;
@@ -56,6 +77,13 @@ namespace INAF.Apps.Uwp.SLabDataManager.Charts
        }

        public List<double> XAxisMajorStepValues { get; private set; }

        private double selectedYAxisMajorStep;
        public double SelectedYAxisMajorStep
        {
            get { return selectedYAxisMajorStep; }
            private set { SetProperty(ref selectedYAxisMajorStep, value); }
        }
        #endregion
        #endregion

@@ -95,8 +123,9 @@ namespace INAF.Apps.Uwp.SLabDataManager.Charts
                foreach (var spectrum in spectra)
                    xvalues.AddRange(spectrum.Elements.Select(x => x.X));

                xMin = xvalues.Min();
                xMax = xvalues.Max();
                (double xMin, double xMax) xresult = xvalues.GetBoundaries();
                xMin = xresult.xMin;
                xMax = xresult.xMax;
            }));
            tasks.Add(Task.Run(() =>
            {
@@ -104,13 +133,16 @@ namespace INAF.Apps.Uwp.SLabDataManager.Charts
                foreach (var spectrum in spectra)
                    yvalues.AddRange(spectrum.Elements.Select(x => x.Y));

                yMin = yvalues.Min();
                yMax = yvalues.Max();
                (double yMin, double yMax) yresult = yvalues.GetBoundaries();
                yMin = yresult.yMin;
                yMax = yresult.yMax;
            }));

            await Task.WhenAll(tasks);

            return (xMin * 0.9, xMax * 1.1, yMin * 0.9, yMax * 1.1);
            System.Diagnostics.Debug.WriteLine($"x: [{xMin},{xMax}], y: [{yMin},{yMax}]");

            return (xMin, xMax, yMin, yMax);
        }

        public SpectrumModel getSpectrumOfType(SpectrumType spectrumType)
@@ -132,7 +164,6 @@ namespace INAF.Apps.Uwp.SLabDataManager.Charts

            XAxisBoundaries = new AxisBoundariesModel("x", result.xMin, result.xMax, spectra[0].Elements[0].MeasureUnit);
            YAxisBoundaries = new AxisBoundariesModel("y", result.yMin, result.yMax);
            System.Diagnostics.Debug.WriteLine($"x: ({result.xMin},{result.xMax}) - y: ({result.yMin},{result.yMax})");
        }

        private void setXAxisMajorStep(WavelengthMeasureUnit wavelengthMeasureUnit)
@@ -148,11 +179,102 @@ namespace INAF.Apps.Uwp.SLabDataManager.Charts
            }
        }

        public void setYAxisTitle(string title)
        {
            YAxisTitle = title;
        }

        public void switchXAxisMeasureUnit(WavelengthMeasureUnit wavelengthMeasureUnit)
        {
            Spectra.All(x => { x.switchToMeasureUnit(wavelengthMeasureUnit); return true; });
            XAxisBoundaries.switchToMeasureUnit(wavelengthMeasureUnit);
            //setXAxisMajorStep(wavelengthMeasureUnit);
        }

        #region alignment
        private SpectrumModel createAligningSpectrum()
        {
            var aligningSpectrum = (SpectrumModel)getSpectrumOfType(SpectrumType.Raw).Clone();
            aligningSpectrum.setType(SpectrumType.Aligned);
            aligningSpectrum.updateTitle();
            return aligningSpectrum;
        }

        public async Task alignRawSpectrumAsync()
        {
            IsError = false;
            ErrorMessage = string.Empty;

            SpectrumModel aligningSpectrum = null;

            string exMsg = string.Empty;
            await Task.Run(() =>
            {
                try
                {
                    aligningSpectrum = createAligningSpectrum();

                    /* 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 = aligningSpectrum.GetCenterSegmentElements(refLowSeparator.CurrentValue, refHighSeparator.CurrentValue);

                    double refSegmentLeftMean = refSegment.GetSegmentLeftMeanValue(SpectrumAlignmentConfig.NumOfPointsForAlignment);
                    double refSegmentRightMean = refSegment.GetSegmentRightMeanValue(SpectrumAlignmentConfig.NumOfPointsForAlignment);


                    /* retrieve segments on the left of selected one for later alignment */
                    var leftSeparators = SpectrumAlignmentConfig.WavelengthSeparators
                                                                .Where(x => x.MinValue < refLowSeparator.MinValue)
                                                                .OrderByDescending(x => x.MinValue);
                    List<IEnumerable<ElementModel>> leftSegments = new List<IEnumerable<ElementModel>>();
                    double rightSeparatorCurrentValue = refLowSeparator.CurrentValue;
                    double refLeftValue = refSegmentLeftMean;
                    foreach (var leftSeparator in leftSeparators)
                    {
                        var elements = aligningSpectrum
                                        .GetLeftSegmentElements(leftSeparator.CurrentValue, rightSeparatorCurrentValue)
                                        .FixLeftSegment(refLeftValue, SpectrumAlignmentConfig.NumOfPointsForAlignment);

                        leftSegments.Add(elements);

                        rightSeparatorCurrentValue = leftSeparator.CurrentValue;
                        refLeftValue = elements.GetSegmentLeftMeanValue(SpectrumAlignmentConfig.NumOfPointsForAlignment);
                    }

                    /* retrieve segments on the right of the selected one for later alignment */
                    var rightSeparators = SpectrumAlignmentConfig.WavelengthSeparators.Where(x => x.MinValue > refHighSeparator.MinValue);
                    List<IEnumerable<ElementModel>> rightSegments = new List<IEnumerable<ElementModel>>();
                    double leftSeparatorCurrentValue = refHighSeparator.CurrentValue;
                    double refRightValue = refSegmentRightMean;
                    foreach (var rightSeparator in rightSeparators)
                    {
                        var elements = aligningSpectrum
                                        .GetRightSegmentElements(leftSeparatorCurrentValue, rightSeparator.CurrentValue)
                                        .FixRightSegment(refRightValue, SpectrumAlignmentConfig.NumOfPointsForAlignment);

                        rightSegments.Add(elements);

                        leftSeparatorCurrentValue = rightSeparator.CurrentValue;
                        refRightValue = elements.GetSegmentRightMeanValue(SpectrumAlignmentConfig.NumOfPointsForAlignment);
                    }
                }
                catch (Exception ex)
                {
                    logger.Write<SpectraContainer>($"{nameof(alignRawSpectrumAsync)} - ex: {ex.Message}", Serilog.Events.LogEventLevel.Error);
                    exMsg = ex.Message;
                }
            });

            if (string.IsNullOrEmpty(exMsg))
                Spectra.Add(aligningSpectrum);
            else
            {
                ErrorMessage = exMsg;
                IsError = true;
            }
        }
        #endregion
    }
}
+46 −15
Original line number Diff line number Diff line
@@ -23,12 +23,10 @@ namespace INAF.Apps.Uwp.SLabDataManager.Charts
            if (!tryReadAreSeparatorsVisible())
                AreSeparatorsVisible = true;

            tryReadNumOfPointsForAlignment();
            if (!tryReadNumOfPointsForAlignment())
                NumOfPointsForAlignment = 3;

            tryReadWavelengthModel(0);
            tryReadWavelengthModel(1);
            tryReadWavelengthModel(2);
            tryReadWavelengthModel(3);
            tryReadWavelengthModels();
        }

        #region properties
@@ -46,7 +44,7 @@ namespace INAF.Apps.Uwp.SLabDataManager.Charts
            set { numOfPointsForAlignment = value; System.Diagnostics.Debug.WriteLine($"numOfPointsForAlignment: {numOfPointsForAlignment}"); saveNumOfPointsForAlignment(value); RaisePropertyChanged(nameof(AreSeparatorsVisible)); }
        }

        public ObservableCollection<WavelengthModel> WavelengthSeparators { get; set; }
        public ObservableCollection<WavelengthModel> WavelengthSeparators { get; private set; }
        #endregion

        #region save/read settings
@@ -93,8 +91,10 @@ namespace INAF.Apps.Uwp.SLabDataManager.Charts
            return isFound;
        }

        private void tryReadWavelengthModel(int index)
        private bool tryReadWavelengthModel(int index)
        {
            bool isFound = false;

            if (settingsHelper.contains($"index{index}"))
            {
                WavelengthSerializableModel wavelengthSerializableModel = settingsHelper.get<WavelengthSerializableModel>($"index{index}");
@@ -106,7 +106,25 @@ namespace INAF.Apps.Uwp.SLabDataManager.Charts
                                                              wavelengthSerializableModel.MeasureUnit,
                                                              "WavelengthLabel".GetText());
                addSeparatorWavelength(separatorWavelength);
                isFound = true;
            }

            return isFound;
        }

        private void tryReadWavelengthModels()
        {
            bool continueLoop = true;
            int index = 0;

            while (continueLoop)
            {
                continueLoop = tryReadWavelengthModel(index);
                if (continueLoop)
                    index++;
            }

            orderSeparators();
        }
        #endregion

@@ -137,16 +155,29 @@ namespace INAF.Apps.Uwp.SLabDataManager.Charts

        public (double xMin, double xMax) getSelectedSegmentBoundaries(double xLow, double xHigh)
        {
            if (separatorWavelength0.CurrentValue <= xLow && separatorWavelength1.CurrentValue >= xHigh)
                return (separatorWavelength0.CurrentValue, separatorWavelength1.CurrentValue);

            if (separatorWavelength1.CurrentValue <= xLow && separatorWavelength2.CurrentValue >= xHigh)
                return (separatorWavelength1.CurrentValue, separatorWavelength2.CurrentValue);
            int index = 0;
            int separatorsNum = WavelengthSeparators.Count;
            for (int i = 0; i < separatorsNum - 1; i++)
            {
                if (WavelengthSeparators[i].CurrentValue <= xLow && WavelengthSeparators[i + 1].CurrentValue >= xHigh)
                {
                    index = i;
                    break;
                }
            }

            if (separatorWavelength2.CurrentValue <= xLow && separatorWavelength3.CurrentValue >= xHigh)
                return (separatorWavelength2.CurrentValue, separatorWavelength3.CurrentValue);
            return (WavelengthSeparators[index].CurrentValue, WavelengthSeparators[index + 1].CurrentValue);
        }

            return (0, 0);
        public void orderSeparators()
        {
            var orderedSeparators = WavelengthSeparators.OrderBy(x => x.MinValue);
            int index = 0;
            foreach (var separator in orderedSeparators)
            {
                separator.Index = index;
                index++;
            }
        }

        public void switchToMeasureUnit(WavelengthMeasureUnit newMeasureUnit)
+22 −0
Original line number Diff line number Diff line
@@ -77,6 +77,28 @@ namespace INAF.Apps.Uwp.SLabDataManager.Converters
        }
    }

    public sealed class HalfWidthConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, string language)
        {
            try
            {
                double width = (double)value;

                return width / 2d;
            }
            catch (Exception)
            {
                return 0;
            }
        }

        public object ConvertBack(object value, Type targetType, object parameter, string language)
        {
            throw new NotImplementedException();
        }
    }

    public sealed class ShortFilepathConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, string language)
Loading