Represents a point in a ScatterSeries.
Inheritance: ICodeGenerating
Exemple #1
0
        public void AddSeries(IEnumerable<double> x, IEnumerable<double> y, string title, OxyColor fill)
        {
            var series = new ScatterSeries
            {
                MarkerFill = fill,
                MarkerSize = 2,
                MarkerStrokeThickness = 0,
                MarkerType = MarkerType.Diamond,
                Title = title
            };

            double[] xPoints = x as double[] ?? x.ToArray();
            double[] yPoints = y as double[] ?? y.ToArray();

            if (xPoints.Length != yPoints.Length)
                throw new Exception("The two data arrays must be of equal length.");

            for (int i = 0; i < xPoints.Length; i++)
            {
                var point = new ScatterPoint(xPoints[i], yPoints[i]);
                series.Points.Add(point);
            }

            Model.Series.Add(series);
        }
Exemple #2
0
        public void CreatePlot(IEnumerable<KeyValuePair <DateTime, Double>> paramCollection, String legendTitle)
        {
            //преобразует в dataPoint
            List<DataPoint> dpList = new List<DataPoint>(50);

            List<Double> pointsDate = new List<Double>(dpList.Count);

            var p = new List<ScatterPoint>();

            foreach(var v in paramCollection)
            {
                dpList.Add(new DataPoint(DateTimeAxis.ToDouble(v.Key), v.Value));

                pointsDate.Add(DateTimeAxis.ToDouble(v.Key));
            }

            //добавляет ось со значениями

            _plotModel.Axes.Add(new DateTimeAxis() { Position = AxisPosition.Bottom, StringFormat = "dd-MM hh-mm" });
            _plotModel.Axes.Add(new LinearAxis());
            LineSeries ls = new LineSeries();

            ScatterSeries css = new ScatterSeries();

            foreach (var v in paramCollection)
            {
                ScatterPoint sp = new ScatterPoint(DateTimeAxis.ToDouble(v.Key), v.Value);
                p.Add(sp);
            }

            css.ItemsSource = p;

            ls.ItemsSource = dpList;

            ls.CanTrackerInterpolatePoints = false;

             _plotModel.Series.Add(ls);
            _plotModel.Series.Add(css);

            //легенда:
            _plotModel.LegendPosition = LegendPosition.TopCenter;
            _plotModel.LegendTitle = legendTitle;

            //сетка:
            _plotModel.Axes[0].MajorGridlineStyle = LineStyle.None;
            _plotModel.Axes[0].ExtraGridlines = pointsDate.ToArray<Double>();
            _plotModel.Axes[0].ExtraGridlineStyle = LineStyle.Dot;

            _plotModel.Series[0].SelectionMode = SelectionMode.Single;

            _plotModel.Axes[1].MajorStep = 10;
            _plotModel.Axes[1].Maximum = dpList.Max<DataPoint>(point => point.Y) + 10;
            _plotModel.Axes[1].Minimum = dpList.Min<DataPoint>(dp => dp.Y) - 10;
        }
        private static ScatterSeries CreateRandomScatterSeries(Random r, int n, string title, MarkerType markerType)
        {
            var s1 = new ScatterSeries { Title = title, MarkerType = markerType, MarkerStroke = OxyColors.Black, MarkerStrokeThickness = 1.0 };
            for (int i = 0; i < n; i++)
            {
                double x = r.NextDouble() * 10;
                double y = r.NextDouble() * 10;
                var p = new ScatterPoint(x, y);
                s1.Points.Add(p);
            }

            return s1;
        }
        public static PlotModel RandomWithFit()
        {
            const int n = 20;
            var model = new PlotModel { Title = string.Format("Random data (n={0})", n), LegendPosition = LegendPosition.LeftTop };

            var s1 = new ScatterSeries { Title = "Measurements" };
            var random = new Random(7);
            double x = 0;
            double y = 0;
            for (int i = 0; i < n; i++)
            {
                x += 2 + (random.NextDouble() * 10);
                y += 1 + random.NextDouble();
                var p = new ScatterPoint(x, y);
                s1.Points.Add(p);
            }

            model.Series.Add(s1);
            double a, b;
            LeastSquaresFit(s1.Points, out a, out b);
            model.Annotations.Add(new LineAnnotation { Slope = a, Intercept = b, Text = "Least squares fit" });
            return model;
        }
Exemple #5
0
        public void TestSimpleCreation()
        {
            var random = new Random();
            var points = new List<int> {100, 1000, 10000, 100000};

            foreach (var totalPoints in points)
            {
                var start = DateTime.Now;
                var plotModel1 = new PlotModel {Subtitle = "No 'binning'", Title = "ScatterSeries (n=32768)"};

                var linearAxis1 = new LinearAxis {Position = AxisPosition.Bottom};
                plotModel1.Axes.Add(linearAxis1);

                var linearAxis2 = new LinearAxis();
                plotModel1.Axes.Add(linearAxis2);

                var scatterSeries1 = new ScatterSeries
                {
                    MarkerSize = 1,
                    MarkerStrokeThickness = 0,
                    MarkerType = MarkerType.Diamond,
                    Title = "Series 1" + totalPoints
                };

                var pointList = new List<ScatterPoint>();
                for (var i = 0; i < totalPoints; i++)
                {
                    var point = new ScatterPoint
                    {
                        X = random.NextDouble(),
                        Y = random.NextDouble()
                    };
                    pointList.Add(point);
                }
                Console.WriteLine();

                var end = DateTime.Now;
                Console.WriteLine("Creation Part of Test Took: {0:.00} seconds for {1} points",
                    end.Subtract(start).TotalSeconds, totalPoints);

                start = DateTime.Now;
                scatterSeries1.Points.AddRange(pointList);
                plotModel1.Series.Add(scatterSeries1);
                end = DateTime.Now;
                Console.WriteLine("Scatter Plot Part of Test Took: {0:.00} seconds for {1} points",
                    end.Subtract(start).TotalSeconds, totalPoints);

                start = DateTime.Now;
                var svg = new SvgExporter();
                var svgString = svg.ExportToString(plotModel1);

                var xml = new XmlDocument();
                xml.LoadXml(svgString);
                var x = SvgDocument.Open(xml); // Svg.SvgDocument();
                var bmp = x.Draw();
                var outputFilePath = GetPath(@"testResults\ScatterPlot\testScatter" + totalPoints + ".jpg");
                bmp.Save(outputFilePath);

                end = DateTime.Now;
                Console.WriteLine("Saving Part of Test Took: {0:.00} seconds for {1} points",
                    end.Subtract(start).TotalSeconds, totalPoints);
            }
        }
 /// <summary>
 /// Determines whether the specified point is valid.
 /// </summary>
 /// <param name="pt">
 /// The point.
 /// </param>
 /// <param name="xaxis">
 /// The x axis.
 /// </param>
 /// <param name="yaxis">
 /// The y axis.
 /// </param>
 /// <returns>
 /// <c>true</c> if the point is valid; otherwise, <c>false</c> .
 /// </returns>
 public virtual bool IsValidPoint(ScatterPoint pt, Axis xaxis, Axis yaxis)
 {
     return !double.IsNaN(pt.X) && !double.IsInfinity(pt.X) && !double.IsNaN(pt.Y) && !double.IsInfinity(pt.Y)
            && (xaxis != null && xaxis.IsValidValue(pt.X)) && (yaxis != null && yaxis.IsValidValue(pt.Y));
 }
Exemple #7
0
 /// <summary>
 /// Determines whether the specified point is valid.
 /// </summary>
 /// <param name="pt">
 /// The point.
 /// </param>
 /// <param name="xaxis">
 /// The x axis.
 /// </param>
 /// <param name="yaxis">
 /// The y axis.
 /// </param>
 /// <returns>
 /// <c>true</c> if the point is valid; otherwise, <c>false</c> .
 /// </returns>
 public virtual bool IsValidPoint(ScatterPoint pt, Axis xaxis, Axis yaxis)
 {
     return(!double.IsNaN(pt.X) && !double.IsInfinity(pt.X) && !double.IsNaN(pt.Y) && !double.IsInfinity(pt.Y) &&
            (xaxis != null && xaxis.IsValidValue(pt.X)) && (yaxis != null && yaxis.IsValidValue(pt.Y)));
 }
        public static void AddTransactionScatterPoints(IEnumerable<Tuple<DateTime, decimal, int>> groupedOrders, PlotModel model, bool addAnnotations, bool showSize)
        {
            model.Annotations.Clear();

            var buySeries = (ScatterSeries)model.Series[1];
            buySeries.Points.Clear();
            var sellSeries = (ScatterSeries)model.Series[2];
            sellSeries.Points.Clear();

            foreach (Tuple<DateTime, decimal, int> o in groupedOrders)
            {
                DateTime date = o.Item1;
                decimal price = o.Item2;
                int quantity = o.Item3;

                ScatterPoint point = new ScatterPoint(DateTimeAxis.ToDouble(date), (double)price);

                if (quantity > 0)
                {
                    buySeries.Points.Add(point);
                }
                else
                {
                    sellSeries.Points.Add(point);
                }

                if (addAnnotations)
                {
                    model.Annotations.Add(CreateAnnotation(date, price, quantity, showSize));
                }
            }
        }
Exemple #9
0
        private void updatePlotWithSignal(Signal signal)
        {
            this.UIThread(() => {
                ScatterSeries currentSerials = null;
                currentSpeed = 0;
                switch (signal.Type)
                {
                    case SignalType.ArcStart:
                        WriteToLogBox("\r\n焊接程序开始:\r\n");
                        currentSerials = arcScatterSeries;
                        break;
                    case SignalType.ArcEnd:
                        currentSerials = arcScatterSeries;
                        break;
                    case SignalType.SolderStart:
                        currentSerials = solderScatterSeries;
                        break;
                    case SignalType.SolderEnd:
                        currentSerials = solderScatterSeries;
                        break;
                    case SignalType.Acceleration:
                        currentSerials = accScatterSeries;
                        currentSpeed = signal.Step;
                        break;
                    case SignalType.Deceleration:
                        currentSerials = deaccScatterSeries;
                        currentSpeed = signal.Step; // TODO: Fixme, should be minus while reverse rotate.
                        break;
                    case SignalType.RotateStart:
                        currentSerials = rotateScatterSeries;
                        break;
                    case SignalType.RotateEnd:
                        currentSerials = rotateScatterSeries;
                        break;
                    case SignalType.RevolveStart:
                        currentSerials = reverseRotateScatterSeries;
                        break;
                    case SignalType.RevolveEnd:
                        currentSerials = reverseRotateScatterSeries;
                        break;
                    case SignalType.Unknown:
                        currentSerials = rotateScatterSeries; // TODO: Fix it.
                        break;
                    default:
                        currentSerials = rotateScatterSeries; // TODO: Fix it.
                        break;
                }

                WriteToLogBox("- " + signal.ToString());

                Plot.Model.InvalidatePlot(true);
                var signals = signalCache;
                var signalCount = signals.Count;

                if (signalCount == 1) // First point
                {
                    var point = new ScatterPoint(currentTime, currentSpeed, 3);
                    arcScatterSeries.Points.Add(point);
                }
                if (signalCount > 1)
                {
                    var previousSignal = signals[signalCount - 2];
                    var currentSignal = signals[signalCount - 1];

                    TimeSpan span = currentSignal.Timestamp - previousSignal.Timestamp;
                    currentTime += span.TotalSeconds;
                    var point = new ScatterPoint(currentTime, currentSpeed, 3);
                    Console.WriteLine("CurrentTime: " + currentTime);
                    if (Math.Ceiling(currentTime) >= 10)
                    {
                        axis1.Maximum = Math.Floor(currentTime + 5);
                    }
                    currentSerials.Points.Add(point);
                }
                // Create Line series
            });
        }
        /// <summary>
        /// The association hypothesis plot.
        /// </summary>
        /// <param name="hypothesis">
        /// The hypothesis.
        /// </param>
        /// <param name="datasetName">
        /// The dataset name.
        /// </param>
        /// <param name="targetDescriptor">
        /// The target descriptor.
        /// </param>
        /// <returns>
        /// The <see cref="PlotModel"/>.
        /// </returns>
        private PlotModel AssociationHypothesisPlot(AssociationHypothesis hypothesis, string datasetName, IImsTarget target, bool plotXAxisFromZero = false)
        {
            PlotModel model = new PlotModel();

            model.LegendBorderThickness = 0;
            model.LegendOrientation = LegendOrientation.Vertical;
            model.LegendPlacement = LegendPlacement.Inside;
            model.LegendPosition = LegendPosition.LeftTop;

            model.TitlePadding = 0;
            model.Title = "Optimal Association Hypothesis Plot";
            model.Subtitle = string.Format("Target: {0}, dataset: {1}", target.TargetDescriptor, datasetName) ;

            model.Axes.Add(
                new LinearAxis
                    {
                        Title = "IMS arrival time (milliseconds)",
                        MajorGridlineStyle = LineStyle.Solid,
                        Position = AxisPosition.Left,
                    });

            model.Axes.Add(
                new LinearAxis
                    {
                        Title = "P/(T*V) with P and T nondimensionalized (1/V)",
                        Position = AxisPosition.Bottom,
                        MajorGridlineStyle = LineStyle.Solid,
                    });

            // Add all the points
            IEnumerable<ObservedPeak> onTrackPeaks = hypothesis.OnTrackObservations;
            IEnumerable<ObservedPeak> offTrackPeaks = hypothesis.AllObservations.Where(x => !hypothesis.IsOnTrack(x));

            Func<ObservedPeak, ScatterPoint> fitPointMap = obj =>
            {
                ObservedPeak observation = obj;
                ContinuousXYPoint xyPoint = observation.ToContinuousXyPoint(false, 0);
                double size = MapToPointSize(observation);
                ScatterPoint sp = new ScatterPoint(xyPoint.X, xyPoint.Y, size);
                return sp;
            };

            var ontrackSeries= new ScatterSeries
            {
                Title = "[Peaks On Tracks]",
                MarkerFill = OxyColors.BlueViolet,
                MarkerType = MarkerType.Circle
            };

            var offtrackSeries= new ScatterSeries
            {
                Title = "[Peaks Off Tracks]",
                MarkerFill = OxyColors.Red,
                MarkerType = MarkerType.Circle
            };

            ontrackSeries.Points.AddRange(onTrackPeaks.Select(x => fitPointMap(x)));

            offtrackSeries.Points.AddRange(offTrackPeaks.Select(x => fitPointMap(x)));

            model.Series.Add(ontrackSeries);

            model.Series.Add(offtrackSeries);

            var allTracks = hypothesis.Tracks;

            // Add the tracks as linear axes
            int count = 1;
            foreach (var track in allTracks)
            {
                FitLine fitline = track.FitLine;
                LineAnnotation annotation = new LineAnnotation();
                annotation.Slope = fitline.Slope;
                annotation.Intercept = fitline.Intercept;
                annotation.TextPadding = 3;
                annotation.TextMargin = 2;
                annotation.Text = string.Format("Conformer {0} - mz: {1:F2}; ccs: {2:F2}, Isotopic Score: {3:F3}; Track Probability: {4:F2}; R2: {5:F5};",
                    count, track.AverageMzInDalton, track.GetMobilityInfoForTarget(target).CollisionCrossSectionArea, track.TrackStatistics.IsotopicScore, track.TrackProbability, track.FitLine.RSquared);
                count++;
                model.Annotations.Add(annotation);
                //Func<object, DataPoint> lineMap = obj =>
                //{
                //    ObservedPeak observation = (ObservedPeak)obj;
                //    ContinuousXYPoint xyPoint = observation.ToContinuousXyPoint();
                //    double x = xyPoint.X;
                //    double y = fitline.ModelPredictX2Y(x);
                //    DataPoint sp = new DataPoint(x, y);
                //    return sp;
                //};

                //model.Series.Add(new LineSeries()
                //{
                //    Mapping = lineMap,
                //    ItemsSource = track.ObservedPeaks,
                //    Color = OxyColors.Purple
                //});
            }

            return model;
        }
        private PlotModel AnnotateRemovedPeaks(PlotModel associationHypothsisPlot, IDictionary<string, IList<ObservedPeak>> preFilteredPeaks)
        {
            Func<ObservedPeak, ScatterPoint> fitPointMap = obj =>
            {
                ObservedPeak observation = obj;
                ContinuousXYPoint xyPoint = observation.ToContinuousXyPoint(false, 0);
                double size = MapToPointSize(observation);
                ScatterPoint sp = new ScatterPoint(xyPoint.X, xyPoint.Y, size);
                return sp;
            };

            foreach (KeyValuePair<string, IList<ObservedPeak>> pair in preFilteredPeaks)
            {
                string rejectionReason = pair.Key;
                IEnumerable<ObservedPeak> peaks = pair.Value;

                ScatterSeries series = new ScatterSeries
                {
                    Title = rejectionReason,
                    MarkerType = MarkerType.Circle
                };

                associationHypothsisPlot.Series.Add(series);
                series.Points.AddRange(peaks.Select(x => fitPointMap(x)));
            }

            return associationHypothsisPlot;
        }
        private void InitializePlot()
        {
            //TODO: Plot the history data.
            Plot.Model = new PlotModel();
            Plot.Dock = DockStyle.Fill;
            PlotBox.Controls.Add(Plot);

            Plot.Model.PlotType = PlotType.XY;
            Plot.Model.Background = OxyColor.FromRgb(255, 255, 255);
            Plot.Model.TextColor = OxyColor.FromRgb(0, 0, 0);

            axis1.Position = AxisPosition.Bottom;
            axis1.Minimum = -1.0;
            axis1.Maximum = 10.0;
            axis1.Title = "运行时间";
            axis1.Unit = "秒";
            Plot.Model.Axes.Add(axis1);

            var axis2 = new LinearAxis();
            axis2.Position = AxisPosition.Left;
            axis2.Minimum = -15.0;
            axis2.Maximum = 15.0;
            axis2.Title = "转速";
            axis2.Unit = "档";
            Plot.Model.Axes.Add(axis2);

            // add Series and Axis to plot model
            ScatterSeries arcScatterSeries = new ScatterSeries { MarkerType = MarkerType.Circle, MarkerFill = OxyColor.FromRgb(0xFF, 0x66, 0x77) };
            ScatterSeries solderScatterSeries = new ScatterSeries { MarkerType = MarkerType.Circle, MarkerFill = OxyColor.FromRgb(0xBB, 0x11, 0x66) };
            ScatterSeries accScatterSeries = new ScatterSeries { MarkerType = MarkerType.Circle, MarkerFill = OxyColor.FromRgb(0x88, 0x33, 0x44) };
            ScatterSeries deaccScatterSeries = new ScatterSeries { MarkerType = MarkerType.Circle, MarkerFill = OxyColor.FromRgb(0x55, 0x88, 0xAA) };
            ScatterSeries rotateScatterSeries = new ScatterSeries { MarkerType = MarkerType.Circle, MarkerFill = OxyColor.FromRgb(0x33, 0xAA, 0xDD) };
            ScatterSeries reverseRotateScatterSeries = new ScatterSeries { MarkerType = MarkerType.Circle, MarkerFill = OxyColor.FromRgb(0x55, 0x99, 0x11) };

            Plot.Model.Series.Add(arcScatterSeries);
            Plot.Model.Series.Add(solderScatterSeries);
            Plot.Model.Series.Add(accScatterSeries);
            Plot.Model.Series.Add(deaccScatterSeries);
            Plot.Model.Series.Add(rotateScatterSeries);
            Plot.Model.Series.Add(reverseRotateScatterSeries);

            var signals = History.Signals;
            var signalCount = signals.Count;

            Plot.Model.InvalidatePlot(true); // Invalidate it.

            var totalTime = (int)((signals.Last().Timestamp - signals.First().Timestamp).TotalMilliseconds); // Ignore time less tham 1ms.
            axis1.Maximum = Math.Floor(totalTime / 1000.0 + 5);

            for (int i = 0; i < signalCount; i++)
            {
                var signal = signals[i];
                var currentSpeed = 0;

                var delta = (int)((signals[i].Timestamp - signals.First().Timestamp).TotalMilliseconds);

                ScatterSeries currentSerials = null;
                switch (signal.Type)
                {
                    case SignalType.ArcStart:
                        currentSerials = arcScatterSeries;
                        break;
                    case SignalType.ArcEnd:
                        currentSerials = arcScatterSeries;
                        break;
                    case SignalType.SolderStart:
                        currentSerials = solderScatterSeries;
                        break;
                    case SignalType.SolderEnd:
                        currentSerials = solderScatterSeries;
                        break;
                    case SignalType.Acceleration:
                        currentSerials = accScatterSeries;
                        currentSpeed = signal.Step;
                        break;
                    case SignalType.Deceleration:
                        currentSerials = deaccScatterSeries;
                        currentSpeed = signal.Step; // TODO: Fixme, should be minus while reverse rotate.
                        break;
                    case SignalType.RevolveStart:
                        currentSerials = reverseRotateScatterSeries;
                        break;
                    case SignalType.RevolveEnd:
                        currentSerials = reverseRotateScatterSeries;
                        break;
                    case SignalType.Unknown:
                        currentSerials = rotateScatterSeries; // TODO: Fix it.
                        break;
                    default:
                        currentSerials = rotateScatterSeries; // TODO: Fix it.
                        break;
                }
                var point = new ScatterPoint(delta / 1000.0, currentSpeed, 3);
                currentSerials.Points.Add(point);
            }
        }
 private bool IsSamePt(ScatterPoint pt, ScatterPoint currentPt, double xOffSet, double yOffSet)
 {
     return pt.X == currentPt.X + xOffSet && pt.Y == currentPt.Y + yOffSet;
 }
        public void UpdateCurrent(Point2D currentPt, List<Point2D> reachablePts, bool fromKeyboard = false)
        {
            Current.Points.Clear();
            if(current.Points.Count > 0)
            {
                var firstPt = current.Points.First();
                reachablePts.RemoveAll(pt => pt.X == firstPt.X && pt.Y == firstPt.Y);
            }
            
            Thickness = FishingNet.Instance.Thickness * 2;
            var scatterPt = new ScatterPoint(currentPt.X, currentPt.Y, Thickness);
            Current.Points.Add(scatterPt);
            Reachable.Points.Clear();

            foreach(var pt in reachablePts)
            {
                Reachable.Points.Add(new ScatterPoint(pt.X, pt.Y, Thickness));
            }
            if (!fromKeyboard) //user create a new cutting line
                Whole.Points.Clear();

            Whole.Points.Add(new DataPoint(currentPt.X,currentPt.Y));
        }
        private static List<ScatterPoint> CreateRandomScatterPoints(int n)
        {
            var r = new Random(12345);

            var points = new List<ScatterPoint>();
            for (int i = 0; i < n; i++)
            {
                double x = r.NextDouble() * 10;
                double y = r.NextDouble() * 10;
                var p = new ScatterPoint(x, y);
                points.Add(p);
            }

            return points;
        }
        private static ScatterSeries CreateRandomScatterSeries(int n, MarkerType markerType, bool setSize, bool setValue, LinearColorAxis colorAxis)
        {
            var s1 = new ScatterSeries
            {
                MarkerType = markerType,
                MarkerSize = 6,
                ColorAxisKey = colorAxis != null ? colorAxis.Key : null
            };
            var random = new Random(13);
            for (int i = 0; i < n; i++)
            {
                var p = new ScatterPoint((random.NextDouble() * 2.2) - 1.1, random.NextDouble());
                if (setSize)
                {
                    p.Size = (random.NextDouble() * 5) + 5;
                }

                if (setValue)
                {
                    p.Value = (random.NextDouble() * 2.2) - 1.1;
                }

                s1.Points.Add(p);
            }

            return s1;
        }
        /// <summary>
        /// The mobility fit FitLine plot.
        /// </summary>
        /// <param name="fitline">
        /// The fitline.
        /// </param>
        /// <returns>
        /// The <see cref="PlotModel"/>.
        /// </returns>
        private PlotModel MobilityFitLinePlot(FitLine fitline)
        {
            IEnumerable<ContinuousXYPoint> fitPointList = fitline.FitPointCollection.Select(x => x.Point);
            IEnumerable<ContinuousXYPoint> outlierList = fitline.OutlierCollection.Select(x => x.Point);
            Func<object, ScatterPoint> fitPointMap = obj =>
            {
                ContinuousXYPoint point = (ContinuousXYPoint)obj;
                double size = 5;
                double color = 0;
                ScatterPoint sp = new ScatterPoint(point.X, point.Y, size, color);
                return sp;
            };

            Func<object, ScatterPoint> OutlierPointMap = obj =>
            {
                ContinuousXYPoint point = (ContinuousXYPoint)obj;
                double size = 5;
                double color = 1;
                ScatterPoint sp = new ScatterPoint(point.X, point.Y, size, color);
                return sp;
            };

            PlotModel model = new PlotModel();
            model.TitlePadding = 0;
            model.Title = "Mobility Fit FitLine";

            ScatterSeries fitPointSeries = new ScatterSeries
            {
                Mapping = fitPointMap,
                ItemsSource = fitPointList,
            };

            ScatterSeries outlierSeries = new ScatterSeries
            {
                Mapping = OutlierPointMap,
                ItemsSource = outlierList,
            };

            Func<object, DataPoint> lineMap = obj =>
            {
                ContinuousXYPoint point = (ContinuousXYPoint)obj;
                double x = point.X;
                double y = fitline.ModelPredictX2Y(x);
                DataPoint sp = new DataPoint(x, y);
                return sp;
            };

            LineSeries fitlineSeries = new LineSeries()
            {
                Mapping = lineMap,
                ItemsSource = fitPointList,
                Color = OxyColors.Purple
            };

            var yAxis = new LinearAxis()
            {
                Title = "IMS scan time (milliseconds)",
                MajorGridlineStyle = LineStyle.Solid,
                Position = AxisPosition.Left,

                //MajorStep = 100.0,
                //MinorStep = 50.0,
                //Minimum = 0,
                //Maximum = 360,
                //FilterMinValue = 0,
                //FilterMaxValue = 360,
            };

            var xAxis = new LinearAxis()
            {
                Title = "Pressure / (Temperature * Voltage) (1 / V))",
                Position = AxisPosition.Bottom,
                MajorGridlineStyle = LineStyle.Solid,
                //MajorStep = 100.0,
                //MinorStep = 50.0,
                //Minimum = 1000,
                //Maximum = 2000,
                //MinimumRange = 100.0,
                //FilterMinValue = 1000,
                //FilterMaxValue = 2000,
            };

            model.Axes.Add(yAxis);
            model.Axes.Add(xAxis);
            model.Series.Add(fitPointSeries);
            model.Series.Add(outlierSeries);
            model.Series.Add(fitlineSeries);
            return model;
        }