예제 #1
0
        public HrvResults ProcessData(HrvRawData rawHrvData)
        {
            base.ProcessData(rawHrvData);

            double[] valid_intervals_durations    = null;
            List <CardioInterval> valid_intervals = null;

            // recorded data contains cardio intervals
            // this is the case when the inspection was performed
            // using a cardio intervals sensor
            // (e.g. Bluetooth HR sensor with RR intervals)
            if (InputDataContainsCardioIntervals(rawHrvData))
            {
                var heartRythmData = ReadCardioIntervalsFromResultSet(rawHrvData);
                valid_intervals           = heartRythmData.Item1;
                HrvResults.RATED_HR_MARKS = heartRythmData.Item2.ToArray();
            }
            else
            {
                ChannelData data = null, adc_data = null;
                double[]    hrv_marks = null;

                SelectAndProcessSignal(m_settings.RejectLowQualitySignalAreas, rawHrvData, out hrv_marks, out data, out adc_data);

                if ((null == data) || (null == adc_data))
                {
                    throw new DataProcessingException(strings.NoSignalInSourceData);
                }

                HrvResults.CRV_CARDIO_SIGNAL = new PhysioSignalView(
                    data.GetDataAsFloat(),
                    (int)data.BitsPerSample,
                    (float)data.SamplingRate,
                    data.PhysioSignalType
                    );

                HrvResults.CRV_CARDIO_SIGNAL_ADC = new PhysioSignalView(
                    adc_data.GetDataAsFloat(),
                    (int)adc_data.BitsPerSample,
                    (float)adc_data.SamplingRate,
                    adc_data.PhysioSignalType
                    );

                // отметки пульса с оценкой достоверности
                var hc_marks_to_rate = new List <RatedContractionMark>(hrv_marks.Length);
                for (int i = 0; i < hrv_marks.Length; ++i)
                {
                    var mark = new RatedContractionMark
                    {
                        Position = hrv_marks[i],
                        Valid    = false
                    };
                    hc_marks_to_rate.Add(mark);
                }

                // получаем достоверные интервалы в миллисекундах,
                // "хорошие" сокращения будут помечены как хорошие (по обоим параметрам),
                var converted_peaks =
                    PeaksFilter.ConvertPeaksToIntervalsWithRejectionAndRatePeaks(
                        hc_marks_to_rate,
                        data.SamplingRate,
                        m_settings.GetApplicableMinIntervalLength(),
                        m_settings.GetApplicableMaxIntervalLength(),
                        m_settings.GetApplicableMaxIntervalDeltaRelative(),
                        adc_data);

                valid_intervals = converted_peaks.extracted_intervals;
                if (converted_peaks.extracted_intervals.Count < 5)
                {
                    throw new DataProcessingException(string.Format(strings.too_few_intervals_detected_in_signal, valid_intervals.Count));
                }

                // это все отметки пульса
                HrvResults.CRV_HR_MARKS = hrv_marks;

                // это отметки пульса с оценками качества
                HrvResults.RATED_HR_MARKS = converted_peaks.rated_heart_contraction_marks.ToArray();

                // Спектр сигнала ФПГ
                HrvResults.SignalSpectrum = PpgSpectrumAnalyzer.CalculateSpectrum(data.Data, data.SamplingRate);
            }

            // только длительности интервалов
            valid_intervals_durations = (from interval in valid_intervals select interval.duration).ToArray();

            var peakAmoDistrib = default(MinMaxModeDescriptor);

            // кардио-интервалы подготовлены
            try
            {
                var mathStatData = new StatData();
                // считаем статистику по кардио-интервалам
                Calculator.CalcStatistics(valid_intervals_durations, mathStatData);
                Calculator.MakeProbabilityDensity(valid_intervals_durations, mathStatData, 440, 2000, 4);

                // The standard approach
                Calculator.MakeDistribution(valid_intervals_durations, mathStatData, 0, 2500, 50);

                // Find the maximized & minimized mode amplitude values
                peakAmoDistrib = MinMaxModeAmpFinder.GetPeakAmoDistrib(valid_intervals_durations, 50, 0, 2500, 1);

                HrvResults.CRV_STAT = _mapper.Map <Methods.ObjectModel.Statistics.StatData>(mathStatData);
            }
            catch (ArgumentException)
            {
                throw new DataProcessingException(
                          string.Format(strings.too_few_valid_intervals_detected_in_signal, valid_intervals_durations.Length));
            }

            HrvResults.Indicators.HRV_Triangular_Index = CalcHrvTriangularIndex(valid_intervals_durations);

            double AMo = Statistics.distribution.mode_amplitude; // Безразмерная -- в долях от 1
            double Mo  = Statistics.distribution.mode / 1000;    // В секундах!!!
            //double AMo = peakAmoDistrib.ModeAmp;   // Безразмерная -- в долях от 1
            //double Mo = peakAmoDistrib.Mode / 1000;       // В секундах!!!
            double M     = Statistics.m / 1000;                        // В секундах!!!
            double dNN   = Statistics.varRange / 1000;                 // В секундах!!!
            double Sigma = Statistics.sigma / 1000;                    // В секундах!!!

            var _AMo = Statistics.distribution.mode_amplitude;         // Безразмерная -- в долях от 1
            var _Mo  = Statistics.distribution.mode / 1000;            // В секундах!!!

            var AmoMax = peakAmoDistrib.MaxModeDescriptor.ModeAmp;     // maximized Mode Amplitude
            var MoMax  = peakAmoDistrib.MaxModeDescriptor.Mode / 1000; // Mode when the Mode amplitude is maximized

            var AmoMin = peakAmoDistrib.MinModeDescriptor.ModeAmp;     // minimized Mode Amplitude
            var MoMin  = peakAmoDistrib.MinModeDescriptor.Mode / 1000; // Mode when the Mode amplitude is minimized

            var AmoMid = peakAmoDistrib.MidModeDescriptor.ModeAmp;     // mean Mode Amplitude
            var MoMid  = peakAmoDistrib.MidModeDescriptor.Mode / 1000; // Mode when the Mode amplitude is close to mean

            // Вычислим индексы Баевского
            // умножаем на 100, т.к. "по Баевскому" АМо указывается в %%.
            HrvResults.Indicators.IN = AMo * 100 / (2.0 * Mo * dNN);

            HrvResults.Indicators.IN_Max     = AmoMax * 100 / (2.0 * MoMax * dNN);
            HrvResults.Indicators.IN_MaxMode = MoMax;

            HrvResults.Indicators.IN_Min     = AmoMin * 100 / (2.0 * MoMin * dNN);
            HrvResults.Indicators.IN_MinMode = MoMin;

            HrvResults.Indicators.IN_Mid     = AmoMid * 100 / (2.0 * MoMid * dNN);
            HrvResults.Indicators.IN_MidMode = MoMid;

            // TODO: выяснить, что правильно, что нет: m_BaevskyStatistics._VPR = 1.f / (fM * fX);
            HrvResults.Indicators.VPR  = 1.0 / (Mo * dNN);
            HrvResults.Indicators.PAPR = AMo * 100 / Mo;
            HrvResults.Indicators.IVR  = AMo * 100 / dNN;

            // Психофизиологическая цена [адаптации]
            // АМ [%%] / ( Мат. ожидание [с] * сигма [с] )
            // умножаем на 100, т.к. АМо д.б. в %%.
            HrvResults.Indicators.PPPA = AMo * 100 / (M * Sigma);

            // Передать в результаты теста также и сами кардиоинтервалы
            // с моментами их появления в записи
            HrvResults.CRV_INTERVALS = valid_intervals.ToArray();

            // Спектр кардиоинтервалов
            HrvResults.IntervalsSpectrum = HrvSpectrumAnalyzer.MakeCardioIntervalsSpectrum(valid_intervals);

            double sum = 0.0;
            double n50 = (valid_intervals[0].duration > 50) ? 1 : 0;

            for (int i = 1; i < valid_intervals.Count; i++)
            {
                double diff = valid_intervals[i].duration - valid_intervals[i - 1].duration;
                sum += Math.Pow(diff, 2);
                if (diff > 50)
                {
                    n50++;
                }
            }

            HrvResults.Indicators.pNN50 = 100.0 * n50 / (valid_intervals.Count - 1);
            HrvResults.Indicators.RMSSD = Math.Sqrt(sum);

            HrvResults.CRV_SCATTEROGRAMM_PARAMETERS = GetScatterParams(valid_intervals_durations);

            HrvResults.ResultsReliability = GetResultsReliability(HrvResults);

            return((HrvResults)ProcessorOutputData);
        }