lx
2025-07-22 cb764c0d0bbd76a3fd14c440e7dc0db612bb8244
version1
已修改4个文件
333 ■■■■■ 文件已修改
ErrorAnalysis.Service/COMergeCalcService.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ErrorAnalysis.Service/ErrorRatioCalc.cs 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ErrorAnalysis.UI/FrmMain.Designer.cs 34 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ErrorAnalysis.UI/FrmMain.cs 276 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ErrorAnalysis.Service/COMergeCalcService.cs
@@ -58,7 +58,7 @@
            var length = readSw == 0 ? _cWinEndIndex - _cWinStartIndex + 1 : _oWinEndIndex - _oWinStartIndex + 1;
            var originC = cArr.Skip(readSw == 0 ? _cWinStartIndex : _oWinStartIndex).Take(length).Sum();
            var coef = originC * 1e8 * 2.54 * 2.54 * 2 * 6 * 11 * 2 * 77 * 0.2 / 0.6 * speed * depth * 0.07;
            var coef = originC * 1e8 * 2.54 * 2.54 * 2 * 6 * 11 * 2 * 77 * 0.2 / 0.6 / speed * depth * 0.07;
            result = coef;
            if (sw > 0 && sw < 100)
            {
ErrorAnalysis.Service/ErrorRatioCalc.cs
@@ -10,7 +10,7 @@
{
    public class ErrorRatioCalc
    {
        public static ErrorRatioResult GetErrorRatioResult(string modelID, double porosity, double sw, double depth, bool lockSpeed, double speed, double targetErrorRatio, int pass = 0)
        public static ErrorRatioResult GetErrorRatioResult(string modelID, double porosity, double sw, double depth, bool lockSpeed, double speed, double targetErrorRatio, out double testSpeed, int pass = 0)
        {
            var result = new ErrorRatioResult
            {
@@ -24,16 +24,16 @@
            {
                List<double[]> cWOL;
                List<double[]> oWOL;
                var firsErrorPass = GetFirstErrorRatio(modelID, porosity, sw, speed, depth, out cWOL, out oWOL);
                var firstErrorPassM = GetFirstErrorRatio(modelID, porosity, sw, speed, depth, out cWOL, out oWOL);
                result.CWOL = cWOL;
                result.OWOL = oWOL;
                result.ErrorRatios.Add(firsErrorPass);
                if (firsErrorPass.ErrorRatioValue > targetErrorRatio)
                result.ErrorRatios.Add(firstErrorPassM);
                if (firstErrorPassM.ErrorRatioValue > targetErrorRatio)
                {
                    var targetPass = Convert.ToInt32(Math.Ceiling(Math.Pow(firsErrorPass.ErrorRatioValue / targetErrorRatio, 2)));
                    var targetPass = Convert.ToInt32(Math.Ceiling(Math.Pow(firstErrorPassM.ErrorRatioValue / targetErrorRatio, 2)));
                    for (int i = 2; i <= targetPass; i++)
                    {
                        result.ErrorRatios.Add(new ErrorRatio { Pass = i, ErrorRatioValue = firsErrorPass.ErrorRatioValue / Math.Sqrt(i) });
                        result.ErrorRatios.Add(new ErrorRatio { Pass = i, ErrorRatioValue = firstErrorPassM.ErrorRatioValue / Math.Sqrt(i) });
                    }
                }
            }
@@ -44,14 +44,21 @@
                List<double[]> oWOL;
                var firstErrorPass = new ErrorRatio();
                speed = 0.6;
                while (firstErrorPass.ErrorRatioValue != 0 && firstErrorPass.ErrorRatioValue > firstTargetErrorRatio)
                do
                {
                    firstErrorPass = GetFirstErrorRatio(modelID, porosity, sw, speed, depth, out cWOL, out oWOL);
                    result.CWOL = cWOL;
                    result.OWOL = oWOL;
                    speed -= 0.01;
                } while (firstErrorPass.ErrorRatioValue != 0 && firstErrorPass.ErrorRatioValue > firstTargetErrorRatio);
                result.ErrorRatios.Clear();
                result.ErrorRatios.Add(firstErrorPass);
                for (int i = 2; i <= pass; i++)
                {
                    result.ErrorRatios.Add(new ErrorRatio { Pass = i, ErrorRatioValue = firstErrorPass.ErrorRatioValue / Math.Sqrt(i) });
                }
            }
            testSpeed = speed;
            return result;
ErrorAnalysis.UI/FrmMain.Designer.cs
@@ -164,7 +164,7 @@
            // btnAnalysis
            // 
            btnAnalysis.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
            btnAnalysis.Location = new Point(616, 530);
            btnAnalysis.Location = new Point(716, 580);
            btnAnalysis.Name = "btnAnalysis";
            btnAnalysis.Size = new Size(75, 23);
            btnAnalysis.TabIndex = 0;
@@ -349,7 +349,7 @@
            gbResult.Controls.Add(txtAnalysisResult);
            gbResult.Location = new Point(17, 364);
            gbResult.Name = "gbResult";
            gbResult.Size = new Size(751, 160);
            gbResult.Size = new Size(851, 210);
            gbResult.TabIndex = 3;
            gbResult.TabStop = false;
            gbResult.Text = "Result";
@@ -366,7 +366,7 @@
            tableLayoutPanel1.Name = "tableLayoutPanel1";
            tableLayoutPanel1.RowCount = 1;
            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Percent, 50F));
            tableLayoutPanel1.Size = new Size(419, 132);
            tableLayoutPanel1.Size = new Size(519, 182);
            tableLayoutPanel1.TabIndex = 2;
            // 
            // pnlCOPic
@@ -374,32 +374,32 @@
            pnlCOPic.Dock = DockStyle.Fill;
            pnlCOPic.Location = new Point(3, 3);
            pnlCOPic.Name = "pnlCOPic";
            pnlCOPic.Size = new Size(203, 126);
            pnlCOPic.Size = new Size(253, 176);
            pnlCOPic.TabIndex = 2;
            // 
            // pnlErrorRatioPic
            // 
            pnlErrorRatioPic.Dock = DockStyle.Fill;
            pnlErrorRatioPic.Location = new Point(212, 3);
            pnlErrorRatioPic.Location = new Point(262, 3);
            pnlErrorRatioPic.Name = "pnlErrorRatioPic";
            pnlErrorRatioPic.Size = new Size(204, 126);
            pnlErrorRatioPic.Size = new Size(254, 176);
            pnlErrorRatioPic.TabIndex = 3;
            // 
            // txtAnalysisResult
            // 
            txtAnalysisResult.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Right;
            txtAnalysisResult.Location = new Point(429, 22);
            txtAnalysisResult.Location = new Point(529, 22);
            txtAnalysisResult.Multiline = true;
            txtAnalysisResult.Name = "txtAnalysisResult";
            txtAnalysisResult.ReadOnly = true;
            txtAnalysisResult.Size = new Size(317, 132);
            txtAnalysisResult.Size = new Size(317, 182);
            txtAnalysisResult.TabIndex = 1;
            txtAnalysisResult.Text = "A total of 6 passes are recommended to maintain a 15% error rate. With the tool operating at 1.5 ft/hr, the estimated total job duration is 10 hours.";
            // 
            // btnReport
            // 
            btnReport.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
            btnReport.Location = new Point(697, 530);
            btnReport.Location = new Point(797, 580);
            btnReport.Name = "btnReport";
            btnReport.Size = new Size(75, 23);
            btnReport.TabIndex = 4;
@@ -421,13 +421,13 @@
            txtDataPath.Location = new Point(98, 16);
            txtDataPath.Name = "txtDataPath";
            txtDataPath.ReadOnly = true;
            txtDataPath.Size = new Size(605, 23);
            txtDataPath.Size = new Size(705, 23);
            txtDataPath.TabIndex = 6;
            // 
            // btnSelectDataSource
            // 
            btnSelectDataSource.Anchor = AnchorStyles.Top | AnchorStyles.Right;
            btnSelectDataSource.Location = new Point(705, 16);
            btnSelectDataSource.Location = new Point(805, 16);
            btnSelectDataSource.Name = "btnSelectDataSource";
            btnSelectDataSource.Size = new Size(63, 23);
            btnSelectDataSource.TabIndex = 7;
@@ -444,7 +444,7 @@
            tabEditInfo.Location = new Point(17, 45);
            tabEditInfo.Name = "tabEditInfo";
            tabEditInfo.SelectedIndex = 0;
            tabEditInfo.Size = new Size(755, 313);
            tabEditInfo.Size = new Size(855, 313);
            tabEditInfo.TabIndex = 0;
            // 
            // tpBorehole
@@ -454,7 +454,7 @@
            tpBorehole.Location = new Point(4, 26);
            tpBorehole.Name = "tpBorehole";
            tpBorehole.Padding = new Padding(3);
            tpBorehole.Size = new Size(747, 283);
            tpBorehole.Size = new Size(847, 283);
            tpBorehole.TabIndex = 1;
            tpBorehole.Text = "Borehole";
            tpBorehole.UseVisualStyleBackColor = true;
@@ -485,7 +485,7 @@
            gpBoreholeFluid.Controls.Add(label38);
            gpBoreholeFluid.Location = new Point(6, 163);
            gpBoreholeFluid.Name = "gpBoreholeFluid";
            gpBoreholeFluid.Size = new Size(735, 119);
            gpBoreholeFluid.Size = new Size(835, 119);
            gpBoreholeFluid.TabIndex = 1;
            gpBoreholeFluid.TabStop = false;
            gpBoreholeFluid.Text = "Borehole fluid";
@@ -714,7 +714,7 @@
            gpBorehole.Controls.Add(label35);
            gpBorehole.Location = new Point(6, 6);
            gpBorehole.Name = "gpBorehole";
            gpBorehole.Size = new Size(735, 154);
            gpBorehole.Size = new Size(835, 154);
            gpBorehole.TabIndex = 0;
            gpBorehole.TabStop = false;
            gpBorehole.Text = "Borehole";
@@ -1207,7 +1207,7 @@
            // pbLoadDB
            // 
            pbLoadDB.Anchor = AnchorStyles.Top | AnchorStyles.Right;
            pbLoadDB.Location = new Point(692, 44);
            pbLoadDB.Location = new Point(792, 44);
            pbLoadDB.Name = "pbLoadDB";
            pbLoadDB.Size = new Size(75, 23);
            pbLoadDB.TabIndex = 8;
@@ -1217,7 +1217,7 @@
            // 
            AutoScaleDimensions = new SizeF(7F, 17F);
            AutoScaleMode = AutoScaleMode.Font;
            ClientSize = new Size(784, 561);
            ClientSize = new Size(884, 611);
            Controls.Add(pbLoadDB);
            Controls.Add(tabEditInfo);
            Controls.Add(btnSelectDataSource);
ErrorAnalysis.UI/FrmMain.cs
@@ -26,23 +26,24 @@
        {
            InitializeComponent();
        }
        private void rdoMode_CheckedChanged(object sender, EventArgs e)
        private void FrmMain_Load(object sender, EventArgs e)
        {
            if (rdoLockSpeed.Checked)
            cmbSpeedUnit.SelectedIndex = 0;
            cmbTargetLoggingIntervalUnit.SelectedIndex = 0;
        }
        private void InitInputControl()
        {
            foreach (var item in gpBorehole.Controls)
                if (item is ComboBox cmb)
                    cmb.Items.Clear();
            if (_models != null)
            {
                pnlLockPass.Visible = false;
                pnlLockSpeed.Visible = true;
            }
            else
            {
                pnlLockPass.Visible = true;
                pnlLockSpeed.Visible = false;
                cmbBit.Items.AddRange(_models.Select(m => m.BIT).Distinct().ToArray());
            }
        }
        #region button event
        private void btnSelectDataSource_Click(object sender, EventArgs e)
        {
            var fileDlg = new OpenFileDialog();
@@ -118,6 +119,12 @@
                return;
            }
            if (!double.TryParse(nudTargetLoggingInterval.Value.ToString(), out double targetLoggingInterval) || nudTargetLoggingInterval.Value <= 0)
            {
                MessageBox.Show("Please select a target logging interval");
                return;
            }
            if (cmbLithology.SelectedIndex == -1)
            {
                MessageBox.Show("Please select a lithology");
@@ -135,6 +142,9 @@
            if (_model == null)
                _model = curModels.First();
            if (cmbTargetLoggingIntervalUnit.Text == "ft")
                targetLoggingInterval = UnitConvert.Ft2M(targetLoggingInterval);
            if (rdoLockSpeed.Checked)
            {
                if (!double.TryParse(nudSpeed.Value.ToString(), out double speed) || nudSpeed.Value <= 0)
@@ -144,9 +154,11 @@
                }
                var calcSpeed = cmbSpeedUnit.Text == "ft/hr" ? UnitConvert.FtHr2MMin(speed) : UnitConvert.MHR2MMin(speed);
                var result = ErrorRatioCalc.GetErrorRatioResult(_model.ModelID, porosity, sw, depth, true, calcSpeed, targetErrorRatio / 100);
                var result = ErrorRatioCalc.GetErrorRatioResult(_model.ModelID, porosity, sw, depth, true, calcSpeed, targetErrorRatio / 100, out _);
                Plot(result);
                double totalTime = Math.Round((targetLoggingInterval / calcSpeed / 60), 2);
                txtAnalysisResult.Text = $"A total of {result.ErrorRatios.Count} passes are recommended to maintain a {Math.Round(result.ErrorRatios.Min(r => r.ErrorRatioValue) * 100, 2)}% error rate. With the tool operating at {speed} {cmbSpeedUnit.Text}, the estimated total job duration is {totalTime.ToString()} hours.";
            }
            else
            {
@@ -155,27 +167,18 @@
                    MessageBox.Show("Please enter a reasonable pass");
                    return;
                }
                double speed;
                var result = ErrorRatioCalc.GetErrorRatioResult(_model.ModelID, porosity, sw, depth, false, 0, targetErrorRatio / 100, out speed, pass);
                Plot(result);
                double totalTime = Math.Round((targetLoggingInterval / speed / 60), 2);
                txtAnalysisResult.Text = $"A total of {result.ErrorRatios.Count} passes are recommended to maintain a {Math.Round(result.ErrorRatios.Min(r => r.ErrorRatioValue) * 100, 2)}% error rate. With the tool operating at {Math.Round(UnitConvert.MMin2FtHr(speed), 2)} ft/hr, the estimated total job duration is {totalTime.ToString()} hours.";
            }
        }
        private void FrmMain_Load(object sender, EventArgs e)
        {
            cmbSpeedUnit.SelectedIndex = 0;
            cmbTargetLoggingIntervalUnit.SelectedIndex = 0;
        }
        private void InitInputControl()
        {
            foreach (var item in gpBorehole.Controls)
                if (item is ComboBox cmb)
                    cmb.Items.Clear();
            if (_models != null)
            {
                cmbBit.Items.AddRange(_models.Select(m => m.BIT).Distinct().ToArray());
            }
        }
        #endregion
        #region Input event
        private void borehole_cmb_SelectedIndexChanged(object sender, EventArgs e)
        {
            var control = (sender as ComboBox);
@@ -251,84 +254,6 @@
            LinkageModelProperty();
        }
        private void holdUp_cmb_SelectedIndexChanged(object sender, EventArgs e)
        {
            var control = (sender as ComboBox);
            var parentControl = control.Parent;
            var property = control.Tag.ToString();
            var filterVal = control.Text == "water" ? "0" : control.Text == "oil" ? "100" : control.Text == "gas" ? "200" : "999";
            if (_filters.ContainsKey(property))
                _filters[property] = filterVal;
            else
                _filters.Add(property, filterVal);
            var allCmb = parentControl.Controls.OfType<Control>().Where(c => c is ComboBox).Select(c => c as ComboBox).ToList();
            switch (control.Name)
            {
                case "cmbCasingHoldUp":
                    cmbScreenHoldUp.Items.Clear();
                    _filters.Remove("ScreenFluid");
                    goto case "cmbScreenHoldUp";
                case "cmbScreenHoldUp":
                    cmbTubeHoldUp.Items.Clear();
                    _filters.Remove("TubeFluid");
                    break;
                default:
                    break;
            }
            var unSelectedCmbs = allCmb.Where(c => c.SelectedIndex == -1).ToList();
            var curModels = GetFilterResult();
            var modelType = typeof(COModelTable);
            foreach (var cmb in unSelectedCmbs)
            {
                cmb.Items.Clear();
                cmb.Enabled = true;
                var cmbProperty = modelType.GetProperty(cmb.Tag.ToString());
                var currentItems = curModels.Select(c => cmbProperty.GetValue(c).ToString() == "0" ? "water" : cmbProperty.GetValue(c).ToString() == "100" ? "oil" : cmbProperty.GetValue(c).ToString() == "200" ? "gas" : "none").Distinct().ToArray();
                if (currentItems.Length == 0)
                    cmb.Enabled = false;
                cmb.Items.AddRange(currentItems);
                if (_filters.ContainsKey(cmb.Tag.ToString()) && currentItems.Contains(_filters[cmb.Tag.ToString()]))
                    cmb.Text = _filters[cmb.Tag.ToString()];
                else
                {
                    _filters.Remove(cmb.Tag.ToString());
                    if (currentItems.Length == 1)
                        cmb.SelectedIndex = 0;
                }
            }
            //foreach (var cmb in allCmb)
            //{
            //    if (cmb.Name != control.Name)
            //    {
            //        var curItems = cmb.Items.OfType<string>().ToList();
            //        var cmbProperty = modelType.GetProperty(cmb.Tag.ToString());
            //        var curFluids = curModels.Select(x => cmbProperty.GetValue(x).ToString() == "0" ? "water" : cmbProperty.GetValue(x).ToString() == "100" ? "oil" : cmbProperty.GetValue(x).ToString() == "200" ? "gas" : "none").Distinct().ToArray();
            //        var minusFluids = curItems.Where(i => !curFluids.Contains(i)).ToArray();
            //        foreach (var item in minusFluids)
            //            cmb.Items.Remove(item);
            //        var addFluids = curFluids.Where(i => !curItems.Contains(i)).ToArray();
            //        cmb.Items.AddRange(addFluids);
            //    }
            //}
            var lithology = curModels.Select(x => x.Lithology).Distinct().ToArray();
            cmbLithology.Items.Clear();
            cmbLithology.Items.AddRange(lithology);
            if (_filters.ContainsKey("Lithology") && lithology.Contains(_filters["Lithology"]))
                cmbLithology.Text = _filters["Lithology"];
            else
                _filters.Remove("Lithology");
        }
        private void LinkageModelProperty()
        {
            cmbCasingHoldUp.Items.Clear();
@@ -418,17 +343,84 @@
            if (lithology.Length == 1)
                cmbLithology.SelectedIndex = 0;
        }
        private List<COModelTable> GetFilterResult()
        private void holdUp_cmb_SelectedIndexChanged(object sender, EventArgs e)
        {
            var type = typeof(COModelTable);
            var result = _models;
            foreach (var filter in _filters)
                result = result.Where(c => type.GetProperty(filter.Key).GetValue(c).ToString() == filter.Value).ToList();
            var control = (sender as ComboBox);
            return result;
            var parentControl = control.Parent;
            var property = control.Tag.ToString();
            var filterVal = control.Text == "water" ? "0" : control.Text == "oil" ? "100" : control.Text == "gas" ? "200" : "999";
            if (_filters.ContainsKey(property))
                _filters[property] = filterVal;
            else
                _filters.Add(property, filterVal);
            var allCmb = parentControl.Controls.OfType<Control>().Where(c => c is ComboBox).Select(c => c as ComboBox).ToList();
            switch (control.Name)
            {
                case "cmbCasingHoldUp":
                    cmbScreenHoldUp.Items.Clear();
                    _filters.Remove("ScreenFluid");
                    goto case "cmbScreenHoldUp";
                case "cmbScreenHoldUp":
                    cmbTubeHoldUp.Items.Clear();
                    _filters.Remove("TubeFluid");
                    break;
                default:
                    break;
            }
            var unSelectedCmbs = allCmb.Where(c => c.SelectedIndex == -1).ToList();
            var curModels = GetFilterResult();
            var modelType = typeof(COModelTable);
            foreach (var cmb in unSelectedCmbs)
            {
                cmb.Items.Clear();
                cmb.Enabled = true;
                var cmbProperty = modelType.GetProperty(cmb.Tag.ToString());
                var currentItems = curModels.Select(c => cmbProperty.GetValue(c).ToString() == "0" ? "water" : cmbProperty.GetValue(c).ToString() == "100" ? "oil" : cmbProperty.GetValue(c).ToString() == "200" ? "gas" : "none").Distinct().ToArray();
                if (currentItems.Length == 0 || (currentItems.Length == 1 && currentItems[0] == "none"))
                {
                    cmb.Enabled = false;
                    continue;
                }
                cmb.Items.AddRange(currentItems);
                if (_filters.ContainsKey(cmb.Tag.ToString()) && currentItems.Contains(_filters[cmb.Tag.ToString()]))
                    cmb.Text = _filters[cmb.Tag.ToString()];
                else
                {
                    _filters.Remove(cmb.Tag.ToString());
                    if (currentItems.Length == 1)
                        cmb.SelectedIndex = 0;
                }
            }
            //foreach (var cmb in allCmb)
            //{
            //    if (cmb.Name != control.Name)
            //    {
            //        var curItems = cmb.Items.OfType<string>().ToList();
            //        var cmbProperty = modelType.GetProperty(cmb.Tag.ToString());
            //        var curFluids = curModels.Select(x => cmbProperty.GetValue(x).ToString() == "0" ? "water" : cmbProperty.GetValue(x).ToString() == "100" ? "oil" : cmbProperty.GetValue(x).ToString() == "200" ? "gas" : "none").Distinct().ToArray();
            //        var minusFluids = curItems.Where(i => !curFluids.Contains(i)).ToArray();
            //        foreach (var item in minusFluids)
            //            cmb.Items.Remove(item);
            //        var addFluids = curFluids.Where(i => !curItems.Contains(i)).ToArray();
            //        cmb.Items.AddRange(addFluids);
            //    }
            //}
            var lithology = curModels.Select(x => x.Lithology).Distinct().ToArray();
            cmbLithology.Items.Clear();
            cmbLithology.Items.AddRange(lithology);
            if (_filters.ContainsKey("Lithology") && lithology.Contains(_filters["Lithology"]))
                cmbLithology.Text = _filters["Lithology"];
            else
                _filters.Remove("Lithology");
        }
        private void cmbLithology_SelectedIndexChanged(object sender, EventArgs e)
        {
            var control = (sender as ComboBox);
@@ -441,6 +433,30 @@
            else
                _filters.Add(property, filterVal);
        }
        private void rdoMode_CheckedChanged(object sender, EventArgs e)
        {
            if (rdoLockSpeed.Checked)
            {
                pnlLockPass.Visible = false;
                pnlLockSpeed.Visible = true;
            }
            else
            {
                pnlLockPass.Visible = true;
                pnlLockSpeed.Visible = false;
            }
        }
        #endregion
        private List<COModelTable> GetFilterResult()
        {
            var type = typeof(COModelTable);
            var result = _models;
            foreach (var filter in _filters)
                result = result.Where(c => type.GetProperty(filter.Key).GetValue(c).ToString() == filter.Value).ToList();
            return result;
        }
        private void Plot(ErrorRatioResult errorResult)
        {
@@ -449,6 +465,8 @@
            var xAxis = new LinearAxis { Position = AxisPosition.Bottom, Title = "Porosity(%)" };
            var yAxis = new LinearAxis { Position = AxisPosition.Left, Title = "C/O" };
            xAxis.MajorGridlineStyle = LineStyle.DashDashDotDot;
            yAxis.MajorGridlineStyle = LineStyle.DashDot;
            plotModel.Axes.Add(xAxis);
            plotModel.Axes.Add(yAxis);
@@ -470,7 +488,7 @@
            // 可视化代码
            // 创建 Windows 窗体以显示图表
            var plotView = new PlotView { Model = plotModel };
            plotView.Width = 600;
            plotView.Height = 450;
            var bitmap = new Bitmap(plotView.Width, plotView.Height);
@@ -479,7 +497,31 @@
            plotView.Dock = DockStyle.Fill;
            pnlCOPic.Controls.Add(plotView);
            pnlErrorRatioPic.Controls.Clear();
            plotModel = new PlotModel();
            xAxis = new LinearAxis { Position = AxisPosition.Bottom, Title = "Pass" };
            xAxis.MajorGridlineStyle = LineStyle.Dash;
            yAxis = new LinearAxis { Position = AxisPosition.Left, Title = "Error Ratio(%)" };
            yAxis.MajorGridlineStyle = LineStyle.Dash;
            plotModel.Axes.Add(xAxis);
            plotModel.Axes.Add(yAxis);
            var series = new LineSeries { Title = "Error Ratio", Color = OxyColors.DarkRed, MarkerType = MarkerType.Diamond };
            foreach (var item in errorResult.ErrorRatios)
                series.Points.Add(new DataPoint(item.Pass, item.ErrorRatioValue * 100));
            plotModel.Series.Add(series);
            plotView = new PlotView { Model = plotModel };
            plotView.Width = 600;
            plotView.Height = 450;
            bitmap = new Bitmap(plotView.Width, plotView.Height);
            plotView.DrawToBitmap(bitmap, new Rectangle(0, 0, bitmap.Width, bitmap.Height));
            bitmap.Save(AppDomain.CurrentDomain.BaseDirectory + "er.png", System.Drawing.Imaging.ImageFormat.Png);
            plotView.Dock = DockStyle.Fill;
            pnlErrorRatioPic.Controls.Add(plotView);
        }
    }
}