/// <summary>
 /// Initializes a new instance of the <see cref="ObservedPeak"/> class with peak and its calculated statistics.
 /// </summary>
 /// <param name="group">
 /// The group.
 /// </param>
 /// <param name="peak">
 /// The peak.
 /// </param>
 /// <param name="statistics">
 /// The Statistics.
 /// </param>
 public ObservedPeak(VoltageGroup group, StandardImsPeak peak, PeakScores statistics)
 {
     this.VoltageGroup = group;
     this.Peak = peak;
     this.Statistics = statistics;
     this.ObservationType = ObservationType.Peak;
     this.mobilityPoint = null;
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="ObservedPeak"/> class that is an virtual observation like source/sink.
 /// </summary>
 public ObservedPeak()
 {
     this.ObservationType = ObservationType.Virtual;
     this.Peak = null;
     this.Statistics = null;
     this.VoltageGroup = null;
     this.mobilityPoint = null;
 }
 /// <summary>
 /// The cooks distance.
 /// </summary>
 /// <param name="point">
 /// The point.
 /// </param>
 /// <param name="ssh">
 /// The ssh.
 /// </param>
 /// <param name="meanX">
 /// The mean X.
 /// </param>
 /// <param name="pointsCount">
 /// The points count.
 /// </param>
 /// <returns>
 /// The <see cref="double"/>.
 /// </returns>
 protected double CooksDistance(ContinuousXYPoint point, double ssh, double meanX, int pointsCount, out double leverage)
 {
     double distance;
     double residuel = this.ComputeResidual(point);
     double p = 3;
     double mse = this.CalculateMSE();
     distance = residuel * residuel / p / mse;
     // Get the Hii from the hat matrix
     double hii = 1.0 / pointsCount + (point.X - meanX) * (point.X - meanX) / ssh;
     distance = distance * hii / ((1 - hii) * (1 - hii));
     leverage = hii;
     return distance;
 }
 /// <summary>
 /// Compute the residual of a fit point.
 /// </summary>
 /// <param name="point">
 /// The point.
 /// </param>
 /// <returns>
 /// The <see cref="double"/>.
 /// </returns>
 /// <exception cref="ArgumentException">
 /// </exception>
 protected double ComputeResidual(ContinuousXYPoint point)
 {
     if (this.state >= FitlineState.ModelComplete)
     {
         if (this.fitPointCollection.FirstOrDefault(x => point.Equals(point)) != null)
         {
             return point.Y - this.ModelPredictX2Y(point.X);
         }
         else
         {
             throw new ArgumentException("Point given is not inside Fitline point list");
         }
     }
     else
     {
         throw new Exception("Has to complete model first, cannot diagnose regression");
     }
 }
 public void RemovePoint(ContinuousXYPoint point)
 {
     this.fitPointCollection.Remove(new FitlinePoint(point));
     this.state = FitlineState.Observing;
 }
        /// <summary>
        /// The to continuous xy point.
        /// </summary>
        /// <returns>
        /// The <see cref="ContinuousXYPoint"/>.
        /// </returns>
        public ContinuousXYPoint ToContinuousXyPoint(bool useAverageTemperature, double globalMeanTemperatureInKelvin)
        {
            if (this.mobilityPoint == null)
            {
                // convert drift time to SI unit seconds
                double y = this.Peak.PeakApex.DriftTimeCenterInMs;
                double temperature = useAverageTemperature ? Metrics.KelvinToNondimensionalized(globalMeanTemperatureInKelvin) : this.VoltageGroup.MeanTemperatureNondimensionalized;

                // P/(T*V) value in pascal per (volts * kelvin)
                double x = this.VoltageGroup.MeanPressureNondimensionalized /
                    this.VoltageGroup.MeanVoltageInVolts / temperature;

                this.mobilityPoint = new ContinuousXYPoint(x, y);
            }

            return this.mobilityPoint;
        }