Beispiel #1
0
        private void buttonTest_Click(object sender, EventArgs e)
        {
            Mtb.Application MtbApp       = new Mtb.Application();
            Mtb.Project     MtbProject   = MtbApp.ActiveProject;
            Mtb.Worksheet   MtbWorksheet = MtbProject.ActiveWorksheet;

            MtbApp.UserInterface.Visible       = false;
            MtbApp.UserInterface.DisplayAlerts = false;
            try
            {
                //need to exe like %'c:\...\...\xx.mac' "99000R99" "1"
                string macro     = "c:\\vm\\test.mac";
                string robotname = "24010R01";
                string appl      = "Hand";
                string subgroup  = "Clamp";

                MtbProject.ExecuteCommand("%'" + macro + "' \"" + robotname + "%\" \"" + appl + "%\" \"" + subgroup + "%\"");
                //MtbProject.ExecuteCommand("%'" + textBoxMacro.Text + "' \"" + textBoxRobot.Text + "\"");
            }
            catch (COMException ex)
            {
                MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            textBoxOutput.Text = "Commands count: " + MtbProject.Commands.Count + Environment.NewLine;
            for (int i = 1; i <= MtbProject.Commands.Count; i++)
            {
                textBoxOutput.Text += "*******************************************************************************" + Environment.NewLine;
                textBoxOutput.Text += "*******************************************************************************" + Environment.NewLine;
                textBoxOutput.Text += "Command " + i + Environment.NewLine;
                textBoxOutput.Text += "Command name: " + MtbProject.Commands.Item(i).Name + Environment.NewLine;
                textBoxOutput.Text += "Outputs count: " + MtbProject.Commands.Item(i).Outputs.Count + Environment.NewLine;
                for (int j = 1; j <= MtbProject.Commands.Item(i).Outputs.Count; j++)
                {
                    textBoxOutput.Text += "-------------------------------------------------------------------------------" + Environment.NewLine;
                    textBoxOutput.Text += "Output " + j + Environment.NewLine;
                    textBoxOutput.Text += "Output type: " + MtbProject.Commands.Item(i).Outputs.Item(j).OutputType + Environment.NewLine;
                    textBoxOutput.Text += "Output text: " + MtbProject.Commands.Item(i).Outputs.Item(j).Text + Environment.NewLine;
                    if (MtbProject.Commands.Item(i).Outputs.Item(j).OutputType == Mtb.MtbOutputTypes.OTGraph)
                    {
                        MtbProject.Commands.Item(i).Outputs.Item(j).Graph.CopyToClipboard();
                        pictureBoxChart.Image = Clipboard.GetImage();
                    }
                }
            }
            while (MtbProject.Commands.Count > 0)
            {
                MtbProject.Commands.Remove(1);
            }
        }
        static void Main(string[] args)
        {
            Mtb.Application mtbApp = new Mtb.Application();
            Mtb.Project     proj   = mtbApp.ActiveProject;
            Mtb.Worksheet   ws     = proj.ActiveWorksheet;
            mtbApp.UserInterface.Visible       = true;
            mtbApp.UserInterface.DisplayAlerts = false;

            proj.ExecuteCommand("rand 10 c1");
            for (int i = 0; i < 1100; i++)
            {
                Console.WriteLine(i + 1);
                proj.ExecuteCommand(string.Format("Note line {0}", i + 1));
                proj.Commands.Delete();
            }

            Console.WriteLine("Done");
            Console.ReadKey();
        }
Beispiel #3
0
 public BoxPlot(Mtb.Project proj, Mtb.Worksheet ws)
     : base(proj, ws)
 {
     SetDefault();
 }
        public override void Execute(Mtb.Project proj)
        {
            // 將資料匯入 Minitab
            if (RawData == null || RawData.Rows.Count == 0)
            {
                return;
            }
            _rptLst = new List <IRptOutput>(); //重新建立一個分析結果列舉
            proj.Commands.Delete();
            proj.Worksheets.Delete();
            Mtb.Worksheet ws = proj.Worksheets.Add(1);                  //新增工作表
            Mtblib.Tools.MtbTools.InsertDataTableToMtbWs(_rawdata, ws); //匯入資料至 Minitab

            Mtb.Column bkCol   = ws.Columns.Item("BK"); bkCol.Name = "斷絲率";
            Mtb.Column grouCol = ws.Columns.Item("GROUP_DESC"); grouCol.Name = "紡位群";
            grouCol.SetValueOrder(Mtb.MtbValueOrderTypes.WorksheetOrder);

            //如果沒有資料或欄位長度不一致就離開
            if ((int)bkCol.DataType == 3 || (int)grouCol.DataType == 3 ||
                (bkCol.RowCount != grouCol.RowCount))
            {
                return;
            }

            StringBuilder cmnd = new StringBuilder();

            cmnd.AppendLine("notitle");
            cmnd.AppendLine("brief 0");

            //繪製Boxplot
            cmnd.AppendFormat("boxplot ({0})*{1};\r\n", bkCol.SynthesizedName, grouCol.SynthesizedName);
            string gpath = System.IO.Path.Combine(Environment.GetEnvironmentVariable("tmp"), "Minitab", string.Format("posidiff_{0}.jpg", _rawdata.TableName));

            cmnd.AppendFormat("gsave \"{0}\";\r\n", gpath);
            cmnd.AppendLine("repl;");
            cmnd.AppendLine("jpeg;");
            cmnd.AppendLine("iqrbox;");
            cmnd.AppendLine("outl.");

            //計算統計量
            cmnd.AppendFormat("stat {0};\r\n", bkCol.SynthesizedName);
            cmnd.AppendFormat("by {0};\r\n", grouCol.SynthesizedName);
            string[] colstr = Mtblib.Tools.MtbTools.CreateVariableStrArray(ws, 5, Mtblib.Tools.MtbVarType.Column);
            Mtb.Column
                gvalCol  = ws.Columns.Item(colstr[0]),
                meanCol  = ws.Columns.Item(colstr[1]),
                stdevCol = ws.Columns.Item(colstr[2]),
                minCol   = ws.Columns.Item(colstr[3]),
                maxCol   = ws.Columns.Item(colstr[4]);
            cmnd.AppendFormat("mean {0};\r\n", meanCol.SynthesizedName);
            cmnd.AppendFormat("stdev {0};\r\n", stdevCol.SynthesizedName);
            cmnd.AppendFormat("mini {0};\r\n", minCol.SynthesizedName);
            cmnd.AppendFormat("maxi {0};\r\n", maxCol.SynthesizedName);
            cmnd.AppendFormat("gval {0}.\r\n", gvalCol.SynthesizedName);

            string mPath = Mtblib.Tools.MtbTools.BuildTemporaryMacro("mymacro.mtb", cmnd.ToString());

            proj.ExecuteCommand(string.Format("Exec \"{0}\" 1", mPath), ws);

            if (File.Exists(gpath)) //如果檔案存在就加入報表內容
            {
                _rptLst.Add(
                    new RptOutput
                {
                    OType           = MtbOType.GRAPH,
                    OutputInByteArr = File.ReadAllBytes(gpath)
                }
                    );
            }

            if (gvalCol.RowCount > 0 && (int)gvalCol.DataType != 3) // 有產出報表就加入報表
            {
                DataTable descStatTable = Mtblib.Tools.MtbTools.GetDataTableFromMtbCols(
                    new Mtb.Column[] { gvalCol, meanCol, stdevCol, minCol, maxCol });
                if (descStatTable != null)
                {
                    descStatTable.Columns[0].ColumnName = "紡位群組";
                    descStatTable.Columns[1].ColumnName = "平均";
                    descStatTable.Columns[2].ColumnName = "標準差";
                    descStatTable.Columns[3].ColumnName = "最小值";
                    descStatTable.Columns[4].ColumnName = "最大值";
                    _rptLst.Add(
                        new RptOutput
                    {
                        OType           = MtbOType.TABLE,
                        OutputInByteArr = Tool.ConvertDataSetToByteArray(descStatTable)
                    }
                        );
                }
            }
        }
        public override void Execute(Mtb.Project proj)
        {
            // 將資料匯入 Minitab
            if (_rawdata == null || _rawdata.Rows.Count == 0)
            {
                throw new ArgumentNullException("查無對應資料");
            }

            _rptLst = new List <IRptOutput>(); //重新建立一個分析結果列舉
            proj.Commands.Delete();
            proj.Worksheets.Delete();
            Mtb.Worksheet ws = proj.Worksheets.Add(1);                  //新增工作表
            Mtblib.Tools.MtbTools.InsertDataTableToMtbWs(_rawdata, ws); //匯入資料至 Minitab

            StringBuilder cmnd = new StringBuilder();

            /*
             * Create TSPlot
             * 該圖會將數據於多個平面中顯示(k*1的方式),所以要先設定 Panel 的安排方式
             *
             */

            cmnd.AppendLine("Unstack ('DateTime' 'Temperature');");
            cmnd.AppendLine("Subscripts 'Area';");
            cmnd.AppendLine("After;");
            cmnd.AppendLine("VarNames.");
            for (int i = 0; i < CountPlotArea; i++)
            {
                cmnd.AppendLine(string.Format("NAME C{0} '{1}'.", 4 + 2 * (i + 1), AreaArray[i]));
            }

            string tmpCmnd = "Tsplot ";

            for (int i = 0; i < CountPlotArea; i++)
            {
                tmpCmnd = tmpCmnd + string.Format("C{0} ", (i + 3) * 2);
            }
            tmpCmnd = tmpCmnd + ";";
            cmnd.AppendLine(tmpCmnd);
            string gpath_tsplot = System.IO.Path.Combine(Environment.GetEnvironmentVariable("tmp"), "Minitab", string.Format("trend_{0}.jpg", _rawdata.TableName));

            cmnd.AppendFormat("gsave \"{0}\";\r\n", gpath_tsplot);
            cmnd.AppendLine("repl;");
            cmnd.AppendLine("jpeg;");
            cmnd.AppendLine("Scale 2;");
            cmnd.AppendLine("Min 100;");
            cmnd.AppendLine("Max 600;");
            cmnd.AppendLine("Min 100;");
            cmnd.AppendLine("Max 600;");
            cmnd.AppendLine("Same 2;");
            cmnd.AppendLine("Panel;");
            cmnd.AppendLine("Index;");
            cmnd.AppendLine("Stamp C3;");
            cmnd.AppendLine("Connect;");
            cmnd.AppendLine("Symbol;");
            cmnd.AppendLine("Type 6;");
            cmnd.AppendLine("Color 4;");
            cmnd.AppendLine("Size 0.7;");
            cmnd.AppendLine("Title;");
            cmnd.AppendLine("Footnote;");
            cmnd.AppendLine("FPer;");
            cmnd.AppendLine("Footnote;");
            cmnd.AppendLine("FPanel;");
            cmnd.AppendLine("NoDTitle;");
            cmnd.AppendLine("NoPerFootnote.");

            //刪除所有圖形
            cmnd.AppendLine("gmana;");
            cmnd.AppendLine("all;");
            cmnd.AppendLine("close;");
            cmnd.AppendLine("nopr.");

            string fpath = Mtblib.Tools.MtbTools.BuildTemporaryMacro("mymacro.mtb", cmnd.ToString());

            proj.ExecuteCommand(string.Format("exec \"{0}\" 1", fpath), ws);


            //將檔案轉為二進位陣列
            if (File.Exists(gpath_tsplot))
            {
                this.Contents.Add(new RptOutput()
                {
                    OType           = MtbOType.GRAPH,
                    OutputInByteArr = File.ReadAllBytes(gpath_tsplot),
                    Tag             = "TSPlot"
                });
            }
            //Tsplot 'Temperature_1' 'Temperature_2';
            //Scale 2;
            //  Min 100;
            //  Max 600;
            //  Min 100;
            //  Max 600;
            //Same  2;
            //Panel;
            //Index;
            //Stamp 'Plant_2';
            //Connect;
            //Symbol;
            //Title;
            //Footnote;
            //  FPer;
            //Footnote;
            //  FPanel;
            //NoDTitle;
            //NoPerFootnote.
            this.Tag = "TSPlot";
        }
Beispiel #6
0
        public override void Execute(Mtb.Project proj)
        {
            if (_rawdata == null || _rawdata.Rows.Count == 0)
            {
                return;
            }
            _rptLst = new List <IRptOutput>();                          //重新建立一個分析結果列舉
            Mtb.Worksheet ws = proj.Worksheets.Add(1);                  //新增工作表
            Mtblib.Tools.MtbTools.InsertDataTableToMtbWs(_rawdata, ws); //匯入資料至 Minitab
            List <string>     varnames = new List <string>();
            List <Mtb.Column> varCols  = new List <Mtb.Column>();       //變數的欄位集合

            for (int i = 0; i < _rawdata.Columns.Count; i++)
            {
                DataColumn col = _rawdata.Columns[i];
                switch (col.ColumnName)
                {
                case "TIMESTAMP":
                case "CHART_PARA_INDEX":
                    break;

                default:
                    varnames.Add(col.ColumnName);
                    varCols.Add(ws.Columns.Item(col.ColumnName));
                    break;
                }
            }

            Mtb.Column timeCol = ws.Columns.Item("TIMESTAMP");

            foreach (var col in varCols)
            {
                if ((int)col.DataType == 3 || col.MissingCount == col.RowCount)
                {
                    throw new ArgumentNullException(string.Format("[{0}]查無資料-多變量管制圖", col.Name));
                }
            }

            StringBuilder cmnd = new StringBuilder();

            cmnd.AppendLine("notitle");
            cmnd.AppendLine("brief 0");

            cmnd.AppendFormat("fdate {0};\r\n", timeCol.SynthesizedName);
            cmnd.AppendLine("format(dtyyyy-MM-dd hh:mm).");

            cmnd.AppendFormat("tsplot {0};\r\n", string.Join(" ", varCols.Select(x => x.SynthesizedName)));

            double gHeight = 4;

            if (varCols.Count > 4)
            {
                gHeight = Math.Min(30, 4 + ((double)varCols.Count - 4) * 0.8);
            }

            cmnd.AppendFormat("graph 8 {0};\r\n", gHeight);
            string gpath = System.IO.Path.Combine(Environment.GetEnvironmentVariable("tmp"), "Minitab", string.Format("overlytrnd_{0}.jpg", _rawdata.TableName));

            cmnd.AppendFormat("gsave \"{0}\";\r\n", gpath);
            cmnd.AppendLine("repl;");
            cmnd.AppendLine("jpeg;");
            cmnd.AppendFormat("stamp {0};\r\n", timeCol.SynthesizedName);
            cmnd.AppendLine("axlab 1;");
            cmnd.AppendLine("adis 0;");
            cmnd.AppendLine("scale 1;");
            cmnd.AppendLine(" psize 7;");
            cmnd.AppendLine(" angle 90;");
            cmnd.AppendLine("scale 2;");
            cmnd.AppendLine(" psize 8;");
            cmnd.AppendLine("symbol;");
            cmnd.AppendLine("conn;");
            cmnd.AppendLine("pane;");
            cmnd.AppendFormat("rc {0} 1;\r\n", varCols.Count);
            cmnd.AppendLine("label;");
            cmnd.AppendLine(" psize 8;");
            cmnd.AppendLine("noal;");
            cmnd.AppendLine("nodt.");
            //刪除所有圖形
            cmnd.AppendLine("gmana;");
            cmnd.AppendLine("all;");
            cmnd.AppendLine("close;");
            cmnd.AppendLine("nopr.");

            string macroPath = Mtblib.Tools.MtbTools.BuildTemporaryMacro("mymacro.mtb", cmnd.ToString());

            proj.ExecuteCommand(string.Format("exec \"{0}\" 1", macroPath), ws);

            //將檔案轉為二進位陣列
            this.Contents.Add(new RptOutput()
            {
                OType           = MtbOType.GRAPH,
                OutputInByteArr = File.ReadAllBytes(gpath)
            });
        }
Beispiel #7
0
        /// <summary>
        /// 計算穩定狀態下的參數組(單一觀測值),使用一般的 Variance-Covariance Matrix 去計算,而非 Sullivan-Woodall
        /// </summary>
        /// <param name="data">欲使用的資料表</param>
        /// <returns></returns>
        public TsquareParameters Execute(Algebra.Matrix <double> data, Mtb.Project proj)
        {
            //確認基本資訊能否計算
            int p = data.ColumnCount;
            int m = data.RowCount;

            if (m - p <= 0)
            {
                throw new Exception(string.Format("樣本數不可低於{0},請重新確認。", p));
            }

            //組合管制界線指令並計算 Phase1 的 limit
            double        ucl;
            StringBuilder cmnd = new StringBuilder();

            cmnd.AppendLine("invCdf 0.9973 k1;");
            cmnd.AppendFormat("Beta {0} {1}.\r\n", (double)p / 2, (double)(m - p - 1) / 2);
            cmnd.AppendFormat("let k1=(({0}-1)**2)/{0}*k1\r\n", m);
            try
            {
                Mtb.Worksheet ws    = proj.Worksheets.Add(1);
                string        fpath = Mtblib.Tools.MtbTools.BuildTemporaryMacro("mymacro.mtb", cmnd.ToString());
                proj.ExecuteCommand(string.Format("Exec \"{0}\" 1", fpath), ws);
                ucl = ws.Constants.Item("k1").GetData();
                ws.Delete();
                proj.Commands.Delete();
            }
            catch (Exception e)
            {
                throw new Exception(e.Message);
            }


            double miss = Mtblib.Tools.MtbTools.MISSINGVALUE;
            var    M    = Algebra.Matrix <double> .Build;

            //計算 Mean vector & Covariance matrix
            IEnumerable <Algebra.Vector <double> > cols = data.EnumerateColumns();
            var mean    = M.DenseOfColumnMajor(1, data.ColumnCount, cols.Select(x => x.Where(o => o < miss).Average()));
            var subData = M.DenseOfRows((data.EnumerateRows().Where(x => x.All(y => y < miss)).ToArray()));
            var diff    = subData - M.Dense(subData.RowCount, 1, (i, j) => 1).Multiply(mean);
            var cov     = diff.Transpose().Multiply(diff) / (subData.RowCount - 1);
            var invS    = cov.Inverse();

            TsquareParameters tsquarePara = new TsquareParameters()
            {
                Mean         = mean,
                Covariance   = cov,
                SampleSize   = m,
                SubgroupSize = 1
            };

            //計算出資料的Tsquare value
            List <double> t2 = new List <double>();

            for (int i = 0; i < data.RowCount; i++)
            {
                if (data.Row(i).ToArray().All(x => x < miss))
                {
                    t2.Add(Tool.CalculateTSquare(data.Row(i).ToRowMatrix(), mean, invS));
                }
                else
                {
                    t2.Add(miss);
                }
            }

            if (t2.Any(x => x >= ucl && x < miss))
            {
                int[] oocRow = t2.Select((x, i) => new { Tsquare = x, Index = i }).Where(x => x.Tsquare >= ucl && x.Tsquare < miss).Select(x => x.Index).OrderByDescending(x => x).ToArray();
                subData = data.Clone();
                //逐列移除OOC的資料列
                for (int i = 0; i < oocRow.Length; i++)
                {
                    subData = subData.RemoveRow(oocRow[i]);
                }
                tsquarePara = Execute(subData, proj);
            }

            return(tsquarePara);
        }
        public override void Execute(Mtb.Project proj)
        {
            // 將資料匯入 Minitab
            if (_rawdata == null || _rawdata.Rows.Count == 0)
            {
                throw new ArgumentNullException("查無對應資料");
            }

            _rptLst = new List <IRptOutput>(); //重新建立一個分析結果列舉,因為 Cotent 唯讀
            proj.Commands.Delete();
            proj.Worksheets.Delete();
            Mtb.Worksheet ws = proj.Worksheets.Add(1);                  //新增工作表
            Mtblib.Tools.MtbTools.InsertDataTableToMtbWs(_rawdata, ws); //匯入資料至 Minitab

            List <Mtb.Column> varCols = new List <Mtb.Column>();        //變數的欄位集合

            varCols.Add(ws.Columns.Item("VALUE"));
            Mtb.Column timeCol = ws.Columns.Item("TEST_DATE");

            #region Create Minitab command
            StringBuilder cmnd = new StringBuilder();
            cmnd.AppendLine("notitle");
            cmnd.AppendLine("brief 0");
            cmnd.AppendFormat("fdate {0};\r\n", timeCol.SynthesizedName);
            cmnd.AppendLine("format(dtyyyy-MM-dd).");

            cmnd.AppendFormat("tsplot {0};\r\n", string.Join(" &\r\n", varCols.Select(x => x.SynthesizedName)));
            cmnd.AppendFormat(" stamp {0};\r\n", timeCol.SynthesizedName);

            string propName = ws.Columns.Item("PROD_NAME").GetData(1, 1);
            string compName = ws.Columns.Item("ITEM_NAME").GetData(1, 1);
            string unitName = ws.Columns.Item("ITEM_UNIT").GetData(1, 1);
            string gpath    = System.IO.Path.Combine(Environment.GetEnvironmentVariable("tmp"), "Minitab", string.Format("trend_{0}_{1}.jpg", propName, compName));

            cmnd.AppendFormat(" gsave \"{0}\";\r\n", gpath);
            cmnd.AppendLine("  repl;");
            cmnd.AppendLine("  jpeg;");
            cmnd.AppendFormat(" axlab 2 \"{0}({1})\";\r\n", compName, unitName);
            cmnd.AppendLine(" scale 1;");
            cmnd.AppendLine("  angle 90;");
            cmnd.AppendLine(" axlab 1;");
            cmnd.AppendLine("  adis 0;");
            cmnd.AppendLine(" conn;");
            cmnd.AppendLine(" symb;");
            cmnd.AppendLine("  size 2;");
            cmnd.AppendLine(" nodt.");


            cmnd.AppendLine("brief 2");
            cmnd.AppendFormat("Desc {0};\r\n", string.Join(" &\r\n", varCols.Select(x => x.SynthesizedName)));
            //cmnd.AppendFormat(" by {0};\r\n");
            cmnd.AppendLine(" n;");
            cmnd.AppendLine(" mean;");
            cmnd.AppendLine(" stdev;");
            cmnd.AppendLine(" mini;");
            cmnd.AppendLine(" maxi;");
            cmnd.AppendLine(" ztag \"DESC\".");
            cmnd.AppendLine("brief 0");
            //刪除所有圖形
            cmnd.AppendLine("gmana;");
            cmnd.AppendLine("all;");
            cmnd.AppendLine("close;");
            cmnd.AppendLine("nopr.");
            #endregion

            string fpath = Mtblib.Tools.MtbTools.BuildTemporaryMacro("mymacro.mtb", cmnd.ToString());
            proj.ExecuteCommand(string.Format("exec \"{0}\" 1", fpath), ws);

            //取得圖和敘述統計量
            try
            {
                if (File.Exists(gpath))
                {
                    this.Contents.Add(new RptOutput()
                    {
                        OType           = MtbOType.GRAPH,
                        OutputInByteArr = File.ReadAllBytes(gpath),
                        Tag             = "Trend"
                    });
                }
            }
            catch (Exception ex)
            {
                this.Contents.Add(new RptOutput()
                {
                    OType           = MtbOType.GRAPH,
                    OutputInByteArr = null,
                    Tag             = "Trend"
                });
            }

            #region 取得敘述統計量表格
            try
            {
                //將報表結果放到 DataTable
                DataTable dt = new DataTable();

                //取得結果的 html string
                string htmlCmnd = proj.Commands.Cast <Mtb.Command>().Where(x => x.Tag == "DESC").Select(x => x.Outputs).FirstOrDefault().Item(2).HTMLText;

                var htmlDoc = new HtmlDocument();
                htmlDoc.LoadHtml(htmlCmnd);

                //取得並設定表頭
                htmlDoc.LoadHtml(htmlDoc.DocumentNode.SelectSingleNode("//tr").OuterHtml);
                var htmlHeader = htmlDoc.DocumentNode.SelectSingleNode("//tr");
                foreach (var cell in htmlHeader.SelectNodes("//td"))
                {
                    if (cell.InnerText != "\n")
                    {
                        dt.Columns.Add(cell.InnerText);
                    }
                }

                //取得表格內容
                htmlDoc.LoadHtml(htmlCmnd);
                var          htmlRows = htmlDoc.DocumentNode.SelectNodes("//table/tr");
                DataRow      dr;
                HtmlDocument tmpHtmlDoc = new HtmlDocument();
                for (int i = 1; i < htmlRows.Count; i++)
                {
                    dr = dt.NewRow();
                    var row = htmlRows[i];
                    tmpHtmlDoc.LoadHtml(row.OuterHtml);
                    var xx = tmpHtmlDoc.DocumentNode.SelectNodes("//td").Select(x => x.InnerText).ToArray();
                    dr.ItemArray = xx;
                    dt.Rows.Add(dr);
                }

                //轉成 DataTable
                this.Contents.Add(new RptOutput()
                {
                    OType           = MtbOType.TABLE,
                    OutputInByteArr = Tool.ConvertDataSetToByteArray(dt),
                    Tag             = "Table"
                });
            }
            catch (Exception ex)
            {
                this.Contents.Add(new RptOutput()
                {
                    OType           = MtbOType.TABLE,
                    OutputInByteArr = null,
                    Tag             = "Table"
                });
            }
            #endregion
        }
        public Dictionary <string, object> MtbAnalysis(string chartType, Dictionary <string, string> rules)
        {
            try
            {
                foreach (Process proc in Process.GetProcessesByName("Mtb"))
                {
                    proc.Kill();
                }
            }
            catch (Exception ex)
            {}
            System.IO.FileInfo imgFile = new System.IO.FileInfo(imgDir + this.controlId + "_" + chartType + ".PNG");
            if (imgFile.Exists)
            {
                imgFile.Delete();
            }

            Mtb.Application             MtbApp       = new Mtb.Application();
            Dictionary <string, object> resultObject = new Dictionary <string, object>();

            try
            {
                MtbApp.UserInterface.Visible = false;
                Mtb.Project MtbProj = MtbApp.ActiveProject;

                Mtb.Columns MtbColumns = MtbProj.ActiveWorksheet.Columns;
                //加载dt所有数据到mtb
                for (int i = 0; i < endColumn; i++)
                {
                    Mtb.Column MtbColumn1 = MtbColumns.Add(null, null, 1);
                    ArrayList  columnData = new ArrayList();
                    for (int j = 0; j < dt.Rows.Count; j++)
                    {
                        if (dt.Rows[j][i].ToString().Length < 1)
                        {
                            columnData.Add(DBNull.Value);
                        }
                        else
                        {
                            columnData.Add(dt.Rows[j][i]);
                        }
                    }
                    MtbColumn1.SetData(columnData.ToArray());
                }

                int rawColumnCount = MtbColumns.Count;

                //Minitab 控制图 or 能力分析命令。
                //命令先生成,先调用checkRule()方法检查规则数量,以及对应生成的检验结果列数
                string execAnalysis = this.GetExcuteCommands(chartType, rules);

                //Minitab 分析结果存储列命令
                string varCommand = this.GetVarCommands(chartType);

                if (!string.IsNullOrEmpty(varCommand))
                {
                    MtbProj.ExecuteCommand(varCommand);
                }
                if (!string.IsNullOrEmpty(execAnalysis))
                {
                    MtbProj.ExecuteCommandAsync(execAnalysis);
                }

                Mtb.Output MtbOut = null;
                try {
                    MtbOut = MtbProj.Commands.Item(MtbProj.Commands.Count).Outputs.Item(1);
                    Console.WriteLine("Normal output!Normal output!Normal output!");
                }
                catch (Exception ex)
                {
                    MtbOut = MtbProj.Commands.Item(MtbProj.Commands.Count).Outputs.Item(1);
                    Console.WriteLine("Unormal output!Unormal output!Unormal output!");
                }

                //Minitab 图形保存
                Mtb.Graph MtbGraph = MtbOut.Graph;
                MtbGraph.SaveAs(imgDir + this.controlId + "_" + chartType, true, Mtb.MtbGraphFileTypes.GFPNGHighColor, 790, 500);

                //Minitab 工作区表保存
                Mtb.Worksheet MtbSheet = MtbProj.ActiveWorksheet;
                MtbSheet.SaveAs(imgDir + this.controlId + "_" + chartType, true);

                for (int i = 1; i <= MtbSheet.Columns.Count; i++)
                {
                    resultObject.Add(MtbSheet.Columns.Item(i).Name, MtbSheet.Columns.Item(i).GetData());
                }
                if (chartType.Contains("Chart"))
                {
                    resultObject.Add("RuleOut", MtbProj.Commands.OutputDocument.Text);
                }
                MtbProj.Delete();
                MtbApp.Quit();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally { MtbApp.Quit(); }
            return(resultObject);
        }
        public override void Execute(Mtb.Project proj)
        {
            // 將資料匯入 Minitab
            if (_rawdata == null || _rawdata.Rows.Count == 0)
            {
                throw new ArgumentNullException("查無對應資料");
            }

            _rptLst = new List <IRptOutput>(); //重新建立一個分析結果列舉
            proj.Commands.Delete();
            proj.Worksheets.Delete();
            Mtb.Worksheet ws = proj.Worksheets.Add(1);                  //新增工作表
            Mtblib.Tools.MtbTools.InsertDataTableToMtbWs(_rawdata, ws); //匯入資料至 Minitab

            List <Mtb.Column> varCols = new List <Mtb.Column>();        //變數的欄位集合
            List <Mtb.Column> bkCol   = new List <Mtb.Column>();        //斷絲率的集合

            Mtb.Column timeCol = null;

            for (int i = 0; i < _rawdata.Columns.Count; i++)
            {
                DataColumn col = _rawdata.Columns[i];
                switch (col.ColumnName)
                {
                case "TIMESTAMP":
                    timeCol = ws.Columns.Item(col.ColumnName);
                    break;

                case "RPT_TIMEHOUR":
                case "GROUP_ID":
                    break;

                case "BK":
                    bkCol.Add(ws.Columns.Item(col.ColumnName));
                    break;

                default:
                    varCols.Add(ws.Columns.Item(col.ColumnName));
                    break;
                }
            }

            foreach (var col in bkCol)
            {
                if ((int)col.DataType == 3 || col.MissingCount == col.RowCount)
                {
                    throw new ArgumentNullException(string.Format("[{0}]查無資料", col.Name));
                }
            }
            foreach (var col in varCols)
            {
                if ((int)col.DataType == 3 || col.MissingCount == col.RowCount)
                {
                    throw new ArgumentNullException(string.Format("[{0}]查無資料", col.Name));
                }
            }


            StringBuilder cmnd = new StringBuilder();

            /*
             * Create TSPlot
             * 該圖會將數據於多個平面中顯示(k*1的方式),所以要先設定 Panel 的安排方式
             *
             */
            cmnd.AppendLine("notitle");
            cmnd.AppendLine("brief 0");
            cmnd.AppendFormat("fdate {0};\r\n", timeCol.SynthesizedName);
            cmnd.AppendLine("format(dtyyyy-MM-dd hh:mm).");
            cmnd.AppendFormat("tsplot {0} {1};\r\n", string.Join(" &\r\n", bkCol.Select(x => x.SynthesizedName)),
                              string.Join(" &\r\n", varCols.Select(x => x.SynthesizedName)));

            double gHeight = 4;

            if (varCols.Count > 3)
            {
                gHeight = Math.Min(30, 4 + ((double)varCols.Count - 3) * 0.8);
            }
            cmnd.AppendFormat("graph 8 {0};\r\n", gHeight);
            string gpath_trend = System.IO.Path.Combine(Environment.GetEnvironmentVariable("tmp"), "Minitab", string.Format("trend_{0}.jpg", _rawdata.TableName));

            cmnd.AppendFormat("gsave \"{0}\";\r\n", gpath_trend);
            cmnd.AppendLine("repl;");
            cmnd.AppendLine("jpeg;");
            cmnd.AppendLine("panel;");
            cmnd.AppendFormat("rc {0} 1;\r\n", varCols.Count + bkCol.Count);
            cmnd.AppendLine("noal;");
            cmnd.AppendLine("label;");
            cmnd.AppendLine(" psize 8;");
            cmnd.AppendLine("scale 1;");
            cmnd.AppendLine(" psize 8;");
            cmnd.AppendLine("axlab 1;");
            cmnd.AppendLine("lshow;");
            cmnd.AppendLine(" angle 90;");
            cmnd.AppendLine("scale 2;");
            cmnd.AppendLine(" psize 8;");
            if (timeCol != null && (int)timeCol.DataType != 3)
            {
                cmnd.AppendFormat("stamp {0};\r\n", timeCol.SynthesizedName);
            }
            cmnd.AppendLine("symb;");
            cmnd.AppendLine("conn;");
            //cmnd.AppendFormat("foot \"建立時間: {0}\";\r\n", DateTime.Now);
            cmnd.AppendLine("nodt.");

            //Create Matrix Plot
            cmnd.AppendFormat("matrixplot ({0})*({1});\r\n", string.Join(" &\r\n", bkCol.Select(x => x.SynthesizedName)),
                              string.Join(" &\r\n", varCols.Select(x => x.SynthesizedName)));

            double gWidth = 8;

            if (varCols.Count > 5)
            {
                gWidth = Math.Min(30, 8 + ((double)varCols.Count - 5) * 0.8);
            }
            cmnd.AppendFormat("graph {0} 5;\r\n", gWidth);
            string gpath_corr = System.IO.Path.Combine(Environment.GetEnvironmentVariable("tmp"), "Minitab", string.Format("corr_{0}.jpg", _rawdata.TableName));

            cmnd.AppendFormat("gsave \"{0}\";\r\n", gpath_corr);
            cmnd.AppendLine("repl;");
            cmnd.AppendLine("jpeg;");
            cmnd.AppendLine("scale 1;");
            cmnd.AppendLine(" psize 8;");
            cmnd.AppendLine("nojitter;");
            cmnd.AppendLine("full;");
            cmnd.AppendLine("bound;");
            cmnd.AppendLine("noal;");
            cmnd.AppendLine("regr;");
            cmnd.AppendLine("symb;");
            cmnd.AppendLine("nodt.");

            //Calculate correlation coefficient
            string[] matIds = Mtblib.Tools.MtbTools.CreateVariableStrArray(ws, 1, Mtblib.Tools.MtbVarType.Matrix);
            cmnd.AppendFormat("corr {0} {1} {2}\r\n", string.Join(" &\r\n", bkCol.Select(x => x.SynthesizedName)),
                              string.Join(" &\r\n", varCols.Select(x => x.SynthesizedName)),
                              string.Join(" &\r\n", matIds)
                              );

            //刪除所有圖形
            cmnd.AppendLine("gmana;");
            cmnd.AppendLine("all;");
            cmnd.AppendLine("close;");
            cmnd.AppendLine("nopr.");

            string fpath = Mtblib.Tools.MtbTools.BuildTemporaryMacro("mymacro.mtb", cmnd.ToString());

            proj.ExecuteCommand(string.Format("exec \"{0}\" 1", fpath), ws);


            //將檔案轉為二進位陣列
            if (File.Exists(gpath_trend))
            {
                this.Contents.Add(new RptOutput()
                {
                    OType           = MtbOType.GRAPH,
                    OutputInByteArr = File.ReadAllBytes(gpath_trend),
                    Tag             = "Trend"
                });
            }
            if (File.Exists(gpath_corr))
            {
                this.Contents.Add(new RptOutput()
                {
                    OType           = MtbOType.GRAPH,
                    OutputInByteArr = File.ReadAllBytes(gpath_corr),
                    Tag             = "Scatter"
                });
            }

            //Create Correlation table
            DataTable corrTable = new DataTable();

            corrTable.Columns.Add("熔爐項目", typeof(string));
            corrTable.Columns.Add("與斷絲率相關係數", typeof(double));

            var corrMat = ws.Matrices.Item(matIds[0]).GetData();

            double[] subCorr = new double[varCols.Count];
            double[] corr    = corrMat as double[];
            if (corr != null)
            {
                Array.Copy(corr, 1, subCorr, 0, varCols.Count);
                string[] labNames = varCols.Select(x => x.Name).ToArray();
                DataRow  dr;
                for (int i = 0; i < subCorr.Length; i++)
                {
                    dr    = corrTable.NewRow();
                    dr[0] = labNames[i];
                    dr[1] = (object)Math.Round(subCorr[i], 3);
                    corrTable.Rows.Add(dr);
                }
            }
            this.Contents.Add(new RptOutput()
            {
                OType           = MtbOType.TABLE,
                OutputInByteArr = Tool.ConvertDataSetToByteArray(corrTable)
            });
        }
Beispiel #11
0
        private void btQuery_Click(object sender, EventArgs e)
        {
            //
            // 收集資訊
            //
            //User
            string user_id = "";

            if (!string.IsNullOrWhiteSpace(cbUser.Text))
            {
                user_id = "'" + cbUser.SelectedValue.ToString() + "'";
            }

            //Purpose
            string purpose = "";

            if (!string.IsNullOrWhiteSpace(textPurpose.Text))
            {
                purpose = "'%" + textPurpose.Text.ToUpper() + "%'";
            }

            //Prod type
            string prodType = "";

            if (oProdTypeCollection != null && oProdTypeCollection.Count > 0)
            {
                List <string> tmp = new List <string>();
                foreach (string item in oProdTypeCollection)
                {
                    tmp.Add("'" + item + "'");
                }
                prodType = string.Join(",", tmp);
            }

            //C tool
            string c_tool = "";

            if (!string.IsNullOrWhiteSpace(cbCTool.Text))
            {
                c_tool = "'" + cbCTool.SelectedValue.ToString() + "'";
            }

            //Lot
            string lot = "";

            if (oLotCollection != null && oLotCollection.Count > 0)
            {
                List <string> tmp = new List <string>();
                tmp = oLotCollection.Select(x => "'" + x + "'").ToList();
                lot = string.Join(",", tmp);
            }

            //customer
            string customer_id = "";

            if (!string.IsNullOrWhiteSpace(cbCustomer.Text))
            {
                customer_id = "'" + cbCustomer.SelectedValue.ToString() + "'";
            }

            //datetime
            string start_date_time = "'" + dtPickerExpStartDate.Value.ToString("yyyy-MM-dd") + "'";
            string end_date_time   = "'" + dtPickerExpEndDate.Value.ToString("yyyy-MM-dd") + "'";

            try
            {
                List <string> conditionList = new List <string>();
                //組出基本條件
                if (user_id != "")
                {
                    conditionList.Add(string.Format("a.emp_id={0}", user_id));
                }
                if (purpose != "")
                {
                    conditionList.Add(string.Format("upper(a.purpose) like {0}", purpose));
                }
                if (prodType != "")
                {
                    conditionList.Add(string.Format("a.type in ({0})", prodType));
                }
                if (c_tool != "")
                {
                    conditionList.Add(string.Format("a.c_tool_id={0}", c_tool));
                }
                if (lot != "")
                {
                    conditionList.Add(string.Format("a.lot_id in ({0})", lot));
                }
                conditionList.Add(string.Format("a.exp_date between {0} and {1}", start_date_time, end_date_time));
                string conditionBasic = string.Join(" and ", conditionList);


                Dictionary <string, string> pivotInfo = new Dictionary <string, string>();
                using (NpgsqlConnection conn = new NpgsqlConnection(_connString))
                {
                    conn.Open();
                    //先把大條件下的資料抓出,確認有多少 item 要 pivot
                    using (NpgsqlDataAdapter da = new NpgsqlDataAdapter("", conn))
                    {
                        string commandstring = "select distinct b.item_id, b.item_name,b.item_flag, b.unit, a.type from " +
                                               "exp_sum a, exp_detail b " +
                                               "where a.exp_sum_index = b.exp_sum_index and a.lot_id is not null and b.item_flag ~ '[PR]+' " +
                                               (string.IsNullOrEmpty(conditionBasic) ? "" : " and " + conditionBasic) +
                                               " order by b.item_flag desc";
                        da.SelectCommand.CommandText = commandstring;
                        DataTable dt = new DataTable();
                        da.Fill(dt);
                        //pivotCols = dt.Rows.Cast<DataRow>().Select(x => x["item_name"].ToString()).ToArray();
                        //pivotItemId = dt.Rows.Cast<DataRow>().Select(x => x["item_id"].ToString()).ToArray();
                        pivotInfo = dt.Rows.Cast <DataRow>().ToDictionary(x => x["item_id"].ToString(),
                                                                          x => x["item_name"].ToString() + "[" + x["unit"].ToString() + "]" +
                                                                          (x["item_flag"].ToString() == "P" ? string.Format("{{{0}}}", x["type"].ToString()) : "")
                                                                          );
                    }
                }

                //建立 pivot 後的欄位組
                if (pivotInfo == null || pivotInfo.Count == 0)
                {
                    MessageBox.Show(null, "無符合條件資料", "", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    return;
                }

                //
                // 處理子條件 (配方、物性指定項或上下限),同時過濾出主條件中無法查詢之項目,
                // 因為 pivot 後項目會變成欄位,不存在的項目會引起查詢錯誤。
                //
                Dictionary <string, string> invalidItems = new Dictionary <string, string>();
                //取出 Recipe 的條件
                conditionList.Clear();
                foreach (DataGridViewRow item in dgViewFormula.Rows)
                {
                    string id = item.Cells["colRId"].Value.ToString();
                    if (pivotInfo.ContainsKey(id))
                    {
                        if (item.Cells["colRLower"].Value != null && !string.IsNullOrWhiteSpace(item.Cells["colRLower"].Value.ToString()))
                        {
                            conditionList.Add(string.Format("\"{0}\"::numeric>={1}", id, item.Cells["colRLower"].Value.ToString()));
                        }
                        if (item.Cells["colRUpper"].Value != null && !string.IsNullOrWhiteSpace(item.Cells["colRUpper"].Value.ToString()))
                        {
                            conditionList.Add(string.Format("\"{0}\"::numeric<={1}", id, item.Cells["colRUpper"].Value.ToString()));
                        }
                        if ((item.Cells["colRLower"].Value == null || string.IsNullOrWhiteSpace(item.Cells["colRLower"].Value.ToString())) && //如果沒有填上下限,表示實驗中一定要包含此項
                            (item.Cells["colRUpper"].Value == null || string.IsNullOrWhiteSpace(item.Cells["colRUpper"].Value.ToString())))
                        {
                            conditionList.Add(string.Format("\"{0}\" is not null", id));
                        }
                    }
                    else
                    {
                        //因為 UI 不卡重複項目,所以要避免加入相同 id
                        if (!invalidItems.ContainsKey(id))
                        {
                            invalidItems.Add(id, item.Cells["colRName"].Value.ToString());
                        }
                    }
                }
                //取出 Property 的條件
                foreach (DataGridViewRow item in dgViewProperty.Rows)
                {
                    string id = item.Cells["colPId"].Value.ToString();
                    if (pivotInfo.ContainsKey(id))
                    {
                        if (item.Cells["colPLower"].Value != null && !string.IsNullOrWhiteSpace(item.Cells["colPLower"].Value.ToString()))
                        {
                            conditionList.Add(string.Format("\"{0}\"::numeric>={1}", id, item.Cells["colPLower"].Value.ToString()));
                        }
                        if (item.Cells["colPUpper"].Value != null && !string.IsNullOrWhiteSpace(item.Cells["colPUpper"].Value.ToString()))
                        {
                            conditionList.Add(string.Format("\"{0}\"::numeric<={1}", id, item.Cells["colPUpper"].Value.ToString()));
                        }
                        if ((item.Cells["colPLower"].Value == null || string.IsNullOrWhiteSpace(item.Cells["colPLower"].Value.ToString())) && //如果沒有填上下限,表示實驗中一定要包含此項
                            (item.Cells["colPUpper"].Value == null || string.IsNullOrWhiteSpace(item.Cells["colPUpper"].Value.ToString())))
                        {
                            conditionList.Add(string.Format("\"{0}\" is not null", id));
                        }
                    }
                    else
                    {
                        //因為 UI 不卡重複項目,所以要避免加入相同 id
                        if (!invalidItems.ContainsKey(id))
                        {
                            invalidItems.Add(id, item.Cells["colPName"].Value.ToString());
                        }
                    }
                }

                //若存在無效的條件,詢問是否繼續查詢?
                if (invalidItems.Count > 0)
                {
                    string msg = string.Join(", ", invalidItems.Select(x => x.Value).ToArray());
                    if (MessageBox.Show(this,
                                        string.Format("以下查詢項目:\r\n{0}\r\n未出現在實驗結果或指定的查詢範圍內。\r\n\r\n是否忽略這些條件繼續查詢?", msg), "",
                                        MessageBoxButtons.YesNo, MessageBoxIcon.Information
                                        ) == System.Windows.Forms.DialogResult.No)
                    {
                        return;
                    }
                }

                //建立最後要使用的配方、物性條件
                string conditionAddtional = string.Join(" and ", conditionList);

                using (NpgsqlConnection conn = new NpgsqlConnection(_connString))
                {
                    conn.Open();
                    using (NpgsqlDataAdapter da = new NpgsqlDataAdapter("", conn))
                    {
                        List <string> ctstring = new List <string>();
                        ctstring.Add("exp_sum_index text");
                        foreach (string itemId in pivotInfo.Keys.OrderBy(x => x))
                        {
                            ctstring.Add(@"""" + itemId + @""" text");
                        }

                        //
                        // crosstab 裡面要用單引號
                        //

                        da.SelectCommand.CommandText = "with t1 as (select * from crosstab($$select a.exp_sum_index::text, b.item_id::text, b.item_value::text from exp_sum a " +
                                                       "join exp_detail b on a.exp_sum_index = b.exp_sum_index where a.lot_id is not null " +
                                                       "and b.item_flag~'[PR]+'" +
                                                       (string.IsNullOrEmpty(conditionBasic) ? "" : " and " + conditionBasic) +
                                                       " order by 1,2 $$) AS ct(" + string.Join(",", ctstring) + ")) " +
                                                       "select a.lot_id, b.emp_ename, c.customer_ename, a.c_tool_id, a.i_tool_id, a.type, d.* , a.remark " +
                                                       "from exp_sum a, employee b, customer c, t1 d " +
                                                       "where a.exp_sum_index = d.exp_sum_index " +
                                                       "and a.customer_id = c.customer_id " +
                                                       "and a.emp_id = b.emp_id" +
                                                       //add condition for r_item and p_item conditionAddtional
                                                       (string.IsNullOrEmpty(conditionAddtional) ? "" : " and " + conditionAddtional);
                        DataTable dt = new DataTable();
                        da.Fill(dt);
                        for (int i = 6; i < dt.Columns.Count - 1; i++) // r_item and p_item start from 7th and the last two columns
                        {
                            DataColumn col = dt.Columns[i];
                            string     colName;
                            pivotInfo.TryGetValue(col.ColumnName, out colName);
                            col.ColumnName = colName ?? col.ColumnName;
                        }

                        //
                        // 把資料回填 Minitab
                        //
                        if (_proj != null)
                        {
                            //Mtb.Worksheet ws = _proj.ActiveWorksheet;
                            Mtb.Worksheet ws          = _proj.Worksheets.Add(1);
                            string[]      colIdString = Tools.MtbTools.CreateVariableStrArray(ws, dt.Columns.Count, MtbVarType.Column);

                            for (int i = 0; i < dt.Columns.Count; i++)
                            {
                                DataColumn col = dt.Columns[i];
                                ws.Columns.Item(colIdString[i]).Name = col.ColumnName;
                                var dataarray = dt.Rows.Cast <DataRow>().Select(x => x[col.ColumnName] == System.DBNull.Value ? "" : x[col.ColumnName]).ToArray();
                                ws.Columns.Item(colIdString[i]).SetData(dataarray);
                            }
                            ws.Columns.Item("exp_sum_index").Delete();
                            ws = null;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(null, "查詢時發生錯誤: " + ex.Message, "", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            finally
            {
                MessageBox.Show(null, "查詢完成 ", "", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }
        /// <summary>
        /// 判斷individaul T2管制圖的參數是否合法? 如果合法不回發生任何事,若不合法則回傳例外。
        /// </summary>
        /// <param name="paraSet"></param>
        /// <returns></returns>
        private void ParaValidation(ParaSetInfo paraSet)
        {
            DataTable mean = paraSet.Mean;
            DataTable cov  = paraSet.Cov;
            int?      ssiz = paraSet.SampleSize;

            if (mean == null || cov == null)
            {
                throw new ArgumentNullException("尚未輸入平均數向量或共變異數矩陣");
            }
            if (SampleSize == null || SampleSize <= 0)
            {
                throw new Exception("樣本數內容不正確");
            }

            //確認輸入的數據是否正確(數量、共變異矩陣對稱、對角項大於0、正定等特性)
            int    r = cov.Columns.Count;
            int    c = cov.Rows.Count;
            double result;

            if (mean.Rows.Cast <DataRow>().Any(x => x.ItemArray.Any(y => !Double.TryParse(y.ToString(), out result))))
            {
                throw new Exception("平均數欄位內容必須為數字");
            }
            if (cov.Rows.Cast <DataRow>().Any(x => x.ItemArray.Any(y => !Double.TryParse(y.ToString(), out result))))
            {
                throw new Exception("共變異數內容必須為數字");
            }

            //將共變異數矩陣轉到Minitab中判斷是否合法
            double[] covArray = new double[r * c];

            for (int cCnt = 0; cCnt < c; cCnt++)
            {
                for (int rCnt = cCnt; rCnt < r; rCnt++)
                {
                    if (rCnt == cCnt)
                    {
                        double value = double.Parse(cov.Rows[rCnt][cCnt].ToString());
                        if (value <= 0)
                        {
                            throw new Exception("共變異數矩陣對角項小於等於0");
                        }
                        covArray[cCnt * r + rCnt] = value;
                    }
                    else
                    {
                        if (cov.Rows[rCnt][cCnt].ToString() != cov.Rows[cCnt][rCnt].ToString())
                        {
                            throw new Exception("共變異數矩陣不對稱");
                        }
                        double value = double.Parse(CovarianceMatrix.Rows[rCnt][cCnt].ToString());
                        covArray[cCnt * r + rCnt] = value;
                        covArray[rCnt * r + cCnt] = value;
                    }
                }
            }
            Mtb.Worksheet ws  = Project.Worksheets.Add(1);
            Mtb.Matrix    mat = ws.Matrices.Add(Quantity: 1);
            Mtb.Column    col = ws.Columns.Add(Quantity: 1);
            mat.SetData(covArray, 1, 1);
            Project.ExecuteCommand(string.Format("Eigen {0} {1}.\r\n", mat.SynthesizedName, col.SynthesizedName), ws);
            double[] eigvalue = col.GetData();
            if (eigvalue.Any(x => x <= 0))
            {
                throw new Exception("共變異數矩陣不為正定");
            }
            ws.Delete();
            Project.Commands.Delete();
        }
Beispiel #13
0
        public static Mtb.Column[] GetMatchColumns(string colsText, Mtb.Worksheet ws)
        {
            //
            // 如果輸入的字串是 empty string, null or white space 丟出例外
            //
            if (string.IsNullOrEmpty(colsText) || string.IsNullOrWhiteSpace(colsText))
            {
                throw new ArgumentNullException("Too few items.", new Exception());
            }

            //
            // 準備 Minitab 欄位
            //
            Mtb.Column[]      cols     = ws.Columns.Cast <Mtb.Column>().ToArray();
            string[]          colLabel = cols.Select(x => x.Label).ToArray();
            string[]          colNames = cols.Select(x => x.Name).ToArray();
            string[]          colId    = cols.Select(x => x.SynthesizedName).ToArray();
            List <Mtb.Column> selCols  = new List <Mtb.Column>();


            Regex regex = new Regex(@"(?<=\s|^)(([']).*?([']))(?=\s|$)|(?<=\s|^)(.*?)(?=\s|$)");
            //
            // (?<=\s|^)(([']).*?([']))(?=\s|b): 處理用 quoted name
            // ==> 取得後判斷是否有違法的字元
            // (?<=\s|^)(.*?)(?=\s|$): 處理 non-quoted name
            // ==> 取得後判斷是否是 1)遺漏 quote 2)有違法字元
            //
            // 違法字元包含: ', # 或單獨一個*
            //
            MatchCollection matches      = regex.Matches(colsText);
            Regex           invalidRegex = new Regex(@"['#]+");

            foreach (Match match in matches)
            {
                string matchString = match.Groups[0].Value;
                string name;
                //該 pattern 也會抓到 empty string, 所以要另外處理 ==> 跳過
                if (string.IsNullOrWhiteSpace(match.Groups[0].Value) || string.IsNullOrEmpty(match.Groups[0].Value))
                {
                    continue;
                }

                if (match.Groups[1].Success == true)       // quoted name
                {
                    if (match.Groups[1].Value.Length == 2) //表示只有 ''
                    {
                        throw new FormatException("No characters in name.");
                    }
                    else if (match.Groups[1].Value.Length > 2)
                    {
                        name = match.Groups[1].Value;
                        name = name.Substring(1, name.Length - 2);                         // 取得 quote 內的文字
                        if (string.IsNullOrWhiteSpace(name.Substring(0, 1)) ||
                            string.IsNullOrWhiteSpace(name.Substring(name.Length - 1, 1))) //判斷是否有空白在頭尾
                        {
                            throw new FormatException("Leading or trailing blanks in name.");
                        }
                        else if (invalidRegex.IsMatch(name) || name.Equals("*"))
                        {
                            throw new FormatException(
                                      string.Format("There is an invalid character in this quoted name: {0}",
                                                    match.Groups[1].Value));
                        }
                        else
                        {
                            //判斷該名稱是否在現有工作表中的 label 中, 忽略 case
                            if (!colLabel.Contains(name, StringComparer.OrdinalIgnoreCase))
                            {
                                throw new ArgumentException(
                                          string.Format("There is no variable by this name: {0}",
                                                        match.Groups[1].Value));
                            }
                            else // 沒問題就加入選擇欄位清單
                            {
                                selCols.Add(ws.Columns.Item(name));
                            }
                        }
                    }
                }
                else // non-quoted name or 連續表示式
                {
                    name = match.Groups[4].Value;
                    // 先判斷連續表示式
                    // 判斷是否為連續表示式 C1-C3 or 'A'-C3
                    // ('.*?'|C[\d]+)-('.*?'|C[\d]+)
                    Regex _regex = new Regex(@"('.*?'|C[\d]+)-('.*?'|C[\d]+)", RegexOptions.IgnoreCase);
                    if (_regex.IsMatch(name))
                    {
                        MatchCollection   _mcollection = _regex.Matches(name);
                        List <Mtb.Column> _cols        = new List <Mtb.Column>();
                        foreach (Match m in _mcollection) //應該有兩個 match
                        {
                            _cols.AddRange(GetMatchColumns(m.Groups[1].Value, ws).ToList());
                            _cols.AddRange(GetMatchColumns(m.Groups[2].Value, ws).ToList());
                        }
                        int start = int.Parse(new Regex(@"C([\d]+)").Match(_cols[0].SynthesizedName).Groups[1].Value);
                        int end   = int.Parse(new Regex(@"C([\d]+)").Match(_cols[1].SynthesizedName).Groups[1].Value);
                        int step  = start < end ? 1 : -1;
                        for (int i = start; start > end ? i >= end : i <= end; i += step)
                        {
                            selCols.Add(ws.Columns.Item(i));
                        }
                    }
                    else // 非連續表示式
                    {
                        if (Regex.IsMatch(name, "^'|'$")) //邊邊有一個 quote 或是裡面有多個 quote 都會被抓進來
                        {
                            throw new FormatException(
                                      string.Format("Missing or stray quote in name: {0}", name));
                        }
                        else if (invalidRegex.IsMatch(name))
                        {
                            throw new FormatException(
                                      string.Format("This name contains invalid character(s): {0}", name));
                        }
                        else
                        {
                            if (!colNames.Contains(name, StringComparer.OrdinalIgnoreCase) &&
                                !colId.Contains(name, StringComparer.OrdinalIgnoreCase))
                            {
                                throw new ArgumentException(
                                          string.Format("There is no variable by this name: {0}", name));
                            }
                            else // 沒問題就加入選擇欄位清單
                            {
                                selCols.Add(ws.Columns.Item(name));
                            }
                        }
                    }
                }
            }
            return(selCols.ToArray());
        }
Beispiel #14
0
        public override void Execute(Mtb.Project proj)
        {
            // 將資料匯入 Minitab
            if (_rawdata == null || _rawdata.Rows.Count == 0)
            {
                return;
            }
            _rptLst = new List <IRptOutput>();                          //重新建立一個分析結果列舉
            Mtb.Worksheet ws = proj.Worksheets.Add(1);                  //新增工作表
            Mtblib.Tools.MtbTools.InsertDataTableToMtbWs(_rawdata, ws); //匯入資料至 Minitab

            List <string>     varnames = new List <string>();
            List <Mtb.Column> varCols  = new List <Mtb.Column>(); //變數的欄位集合

            for (int i = 0; i < _rawdata.Columns.Count; i++)
            {
                DataColumn col = _rawdata.Columns[i];
                switch (col.ColumnName)
                {
                case "TIMESTAMP":
                case "CHART_PARA_INDEX":
                    break;

                default:
                    varnames.Add(col.ColumnName);
                    varCols.Add(ws.Columns.Item(col.ColumnName));
                    break;
                }
            }

            foreach (var col in varCols)
            {
                if ((int)col.DataType == 3 || col.MissingCount == col.RowCount)
                {
                    throw new ArgumentNullException(string.Format("[{0}]查無資料-多變量管制圖", col.Name));
                }
            }

            StringBuilder            cmnd        = new StringBuilder();
            List <TsquareParameters> tmpParaList = new List <TsquareParameters>();                                 //用於計算 decomposition

            string[] colIds = Mtblib.Tools.MtbTools.CreateVariableStrArray(ws, 4, Mtblib.Tools.MtbVarType.Column); //Plot point, CL, UCL and Test column

            // 指定繪圖時需要的欄位變數
            Mtb.Column
                pplotCol = ws.Columns.Item(colIds[0]),
                clCol    = ws.Columns.Item(colIds[1]),
                uclCol   = ws.Columns.Item(colIds[2]),
                oocCol   = ws.Columns.Item(colIds[3]),
                timeCol  = ws.Columns.Item("TIMESTAMP");


            // 計算 T2 plot points
            if (_parameters == null || _parameters.Count == 0)
            {
                //自己算的時候需要的變數和子命令
                #region Phase I
                cmnd.AppendLine("macro");
                cmnd.AppendLine("myt2calculator x.1-x.p;");
                cmnd.AppendLine("variance cov ssiz;");
                cmnd.AppendLine("meanvect location; ");
                cmnd.AppendLine("ppoint t2;");
                cmnd.AppendLine("climit cl ucl;");
                cmnd.AppendLine("test ooc;");
                cmnd.AppendLine("siglevel alpha.");

                cmnd.AppendLine("mcolumn x.1-x.p t2");
                cmnd.AppendLine("mcolumn loc.1-loc.p xx.1-xx.p tmp.1-tmp.3 ooc ucl cl");
                cmnd.AppendLine("mconstant ssiz m alpha conf a1 a2 kk");
                cmnd.AppendLine("mmatrix location diff cov tdiff invCov");
                cmnd.AppendLine("default alpha = 0.0027");

                cmnd.AppendLine("rnmiss x.1-x.p tmp.1");
                cmnd.AppendLine("copy x.1-x.p xx.1-xx.p;");
                cmnd.AppendLine("exclude;");
                cmnd.AppendFormat("where \"tmp.1>0\".\r\n");
                cmnd.AppendLine("cova xx.1-xx.p cov"); // Get Covariance matrix
                cmnd.AppendLine("let ssiz = n(xx.1)"); // Get the sample size of covariance calculation, ALSO..THAT IS THE NUMBER OF NONMISSING OBSERVATIONS
                cmnd.AppendLine("stat x.1-x.p;");
                cmnd.AppendLine("mean loc.1-loc.p.");  //Get mean vector.

                /*
                 * Check if there is enough nonmissing observation to calculate control limit under
                 * Tsquare command (m>p+1, where m=#observation, include missing obs, p=#items)
                 * If no, you still need to draw plot points on graph..
                 * The trick is we given parameters (Mean & Covariance) and given a fake sample size, then
                 * you get t-sq value, becasue we don't need the CL & UCL from Minitab.
                 * (WE USE REGULAR COVARIANCE INSTEAD OF COVARIANCE BY Sullivan & Woodall)
                 *
                 */
                cmnd.AppendLine("if(ssiz < p+1)");
                cmnd.AppendLine("let kk = p+1");
                cmnd.AppendLine("else");
                cmnd.AppendLine("copy ssiz kk\r\n");
                cmnd.AppendLine("endif");

                cmnd.AppendLine("tsquare x.1-x.p 1;");
                cmnd.AppendLine("mu loc.1-loc.p;");
                cmnd.AppendLine("sigma cov;");
                cmnd.AppendLine("number kk;");
                cmnd.AppendLine("sampsize tmp.1;"); //Get subgroup size.
                cmnd.AppendLine("ppoint t2.");      //Get Tsquare value.



                cmnd.AppendLine("copy loc.1-loc.p location"); //Copy column to mean vector

                cmnd.AppendLine("let m = sum(tmp.1)");        //Get the actual sample size (include missing observations)

                cmnd.AppendLine("if (m <= p+1)");             // Check if there is enough obs to calc contril limit...
                cmnd.AppendLine("let cl[m]=miss()");          //no center line
                cmnd.AppendLine("let ucl[m]=miss()");         //no control limit
                cmnd.AppendLine("set ooc");                   //no ooc
                cmnd.AppendLine("(0)m");
                cmnd.AppendLine("end");

                cmnd.AppendLine("else");

                cmnd.AppendLine("let conf = 1-alpha");
                cmnd.AppendLine("let a1 = p/2");
                cmnd.AppendLine("let a2 = (m-p-1)/2");

                // Calculate UCL
                cmnd.AppendLine("set tmp.1");
                cmnd.AppendLine("(conf)m");
                cmnd.AppendLine("end");
                cmnd.AppendLine("invcdf tmp.1 ucl;");
                cmnd.AppendLine(" beta a1 a2.");
                cmnd.AppendLine("let ucl = (m-1)**2/m*ucl"); //Get upper control limit
                // Calculate CL
                cmnd.AppendLine("set tmp.1");
                cmnd.AppendLine("(0.5)m");
                cmnd.AppendLine("end");
                cmnd.AppendLine("invcdf tmp.1 cl;");
                cmnd.AppendLine(" beta a1 a2.");
                cmnd.AppendLine("let cl = (m-1)**2/m*cl");                  //Get center line
                cmnd.AppendLine("let ooc = if(t2>ucl and t2<>MISS(),1,0)"); //Get OOC info
                cmnd.AppendLine("endif");

                //刪除所有圖形
                cmnd.AppendLine("gmana;");
                cmnd.AppendLine("all;");
                cmnd.AppendLine("close;");
                cmnd.AppendLine("nopr.");


                cmnd.AppendLine("endmacro");

                string macPath = Mtblib.Tools.MtbTools.BuildTemporaryMacro("mytsquare.mac", cmnd.ToString());

                string[] matIds   = Mtblib.Tools.MtbTools.CreateVariableStrArray(ws, 2, Mtblib.Tools.MtbVarType.Matrix);   //紀錄Mean vecot & Covariance matrix
                string[] constIds = Mtblib.Tools.MtbTools.CreateVariableStrArray(ws, 1, Mtblib.Tools.MtbVarType.Constant); // Sample size of Covariance matrix

                cmnd.Clear();
                cmnd.AppendLine("notitle");
                cmnd.AppendLine("brief 0");
                cmnd.AppendFormat("%\"{0}\" {1};\r\n", macPath, string.Join(" &\r\n", varCols.Select(x => x.SynthesizedName)));
                cmnd.AppendFormat("variance {0} {1};\r\n", matIds[0], constIds[0]);
                cmnd.AppendFormat("meanvect {0};\r\n", matIds[1]);
                cmnd.AppendFormat("ppoint {0};\r\n", pplotCol.SynthesizedName);
                cmnd.AppendFormat("climit {0} {1};\r\n", clCol.SynthesizedName, uclCol.SynthesizedName);
                cmnd.AppendFormat("test {0}.\r\n", oocCol.SynthesizedName);


                string path = Mtblib.Tools.MtbTools.BuildTemporaryMacro("mymacro.mtb", cmnd.ToString());
                proj.ExecuteCommand(string.Format("exec \"{0}\" 1", path), ws);

                #endregion

                //取得參數組
                TsquareParameters tmpPara = new TsquareParameters();
                Mtb.Matrix        mat;
                mat          = ws.Matrices.Item(matIds[1]);
                tmpPara.Mean = LinearAlgebra.Matrix <double> .Build.DenseOfColumnMajor(1, mat.ColumnCount, mat.GetData());

                mat = ws.Matrices.Item(matIds[0]);
                tmpPara.Covariance = LinearAlgebra.Matrix <double> .Build.DenseOfColumnMajor(mat.RowCount, mat.ColumnCount, mat.GetData());

                tmpPara.SampleSize   = ws.Constants.Item(constIds[0]).GetData();
                tmpPara.SubgroupSize = 1;
                tmpPara.ParaID       = null;
                tmpParaList.Add(tmpPara);
            }
            else
            {
                //有指定參數的時候
                #region Phase II
                int nParas = ws.Columns.Item("CHART_PARA_INDEX").GetNumDistinctRows(); //宣告多組參數組
                cmnd.AppendLine("macro");
                cmnd.AppendLine("myt2calculator x.1-x.p;");
                cmnd.AppendFormat("variance cov.1-cov.{0} ssiz.1-ssiz.{0};\r\n", nParas);
                cmnd.AppendFormat("meanvect mvect.1-mvect.{0};\r\n", nParas);
                cmnd.AppendLine("ppoint t2;");
                cmnd.AppendLine("climit cl ucl;");
                cmnd.AppendLine("test ooc;");
                cmnd.AppendLine("siglevel alpha.");

                cmnd.AppendLine("mcolumn x.1-x.p xx.1-xx.p xxx.1-xxx.p loc.1-loc.p");
                cmnd.AppendLine("mcolumn tmp t2 ucl cl ooc tmpT2 tmpUCL tmpCL tmpOOC");
                cmnd.AppendFormat("mmatrix mvect.1-mvect.{0} cov.1-cov.{0}\r\n", nParas);
                cmnd.AppendFormat("mconstant m histm alpha conf a1 a2 ssiz.1-ssiz.{0} kk\r\n", nParas);
                cmnd.AppendLine("default alpha = 0.0027");

                var _chartparaindex = _rawdata.AsEnumerable()
                                      .Select(x => x.Field <string>("CHART_PARA_INDEX")).ToArray();
                var _distinctIds = _chartparaindex.Distinct().ToArray();

                for (int i = 0; i < _distinctIds.Length; i++) //對每個參數與對應的資料計算 Tsquare 和管制界限
                {
                    string id = _distinctIds[i];
                    cmnd.AppendLine("copy x.1-x.p xx.1-xx.p;");
                    cmnd.AppendLine("include;");
                    cmnd.AppendFormat("rows {0}.\r\n",
                                      string.Join(" &\r\n",
                                                  _chartparaindex.Select((x, rowid) => new { Value = x, RowId = rowid + 1 })
                                                  .Where(x => x.Value == id).Select(x => x.RowId).ToArray()));

                    #region Set parameter information into Minitab macro
                    TsquareParameters para = new TsquareParameters();
                    para.Mean = null; para.Covariance = null; para.SampleSize = MISSINGVALUE; para.SubgroupSize = 1;
                    if (id != null)
                    {
                        para = _parameters.Where(x => x.ParaID == id).First();
                    }

                    if (para.Mean != null) //把已知的 Mean vector 寫入 Minitab
                    {
                        cmnd.AppendLine("read loc.1-loc.p");
                        cmnd.AppendFormat("{0}\r\n", string.Join(" &\r\n", para.Mean.Enumerate()));
                        cmnd.AppendLine("end");
                    }
                    else
                    {
                        cmnd.AppendLine("stat xx.1-xx.p;");
                        cmnd.AppendLine("mean loc.1-loc.p.");
                    }


                    if (para.Covariance != null) //把已知的 Covariance 寫入 Minitab
                    {
                        cmnd.AppendFormat("read {1} {2} cov.{0} \r\n", i + 1, para.Covariance.RowCount, para.Covariance.ColumnCount);
                        List <LinearAlgebra.Vector <double> > valuesByRow = para.Covariance.EnumerateRows().ToList();
                        for (int r = 0; r < para.Covariance.RowCount; r++)
                        {
                            cmnd.AppendFormat("{0}\r\n", string.Join(" &\r\n", valuesByRow[r]));
                        }
                        cmnd.AppendLine("end");
                        cmnd.AppendFormat("let ssiz.{0}={1}\r\n", i + 1, para.SampleSize);
                    }
                    else
                    {
                        cmnd.AppendLine("rnmiss xx.1-xx.p tmp");
                        cmnd.AppendLine("copy xx.1-xx.p xxx.1-xxx.p;");
                        cmnd.AppendLine("exclud;");
                        cmnd.AppendFormat("where \"tmp>0\".\r\n");
                        cmnd.AppendFormat("cova xxx.1-xxx.p cov.{0}\r\n", i + 1);
                        cmnd.AppendFormat("let ssiz.{0} = count(xxx.1)\r\n", i + 1);
                    }
                    #endregion

                    //Tsquare command
                    cmnd.AppendFormat("if(ssiz.{0} < p+1)\r\n", i + 1);
                    cmnd.AppendLine("let kk = p+1");
                    cmnd.AppendLine("else");
                    cmnd.AppendFormat("copy ssiz.{0} kk\r\n", i + 1);
                    cmnd.AppendLine("endif");
                    if (id == null && _chartparaindex.Where(x => x == id).Count() == 1) //如果只有一個觀測值且沒有參數設定
                    {
                        cmnd.AppendLine("let tmp=1");
                        cmnd.AppendLine("let tmpT2=miss()");
                    }
                    else
                    {
                        cmnd.AppendFormat("tsquare xx.1-xx.p {0};\r\n", para.SubgroupSize);
                        cmnd.AppendLine(" mu loc.1-loc.p;");
                        cmnd.AppendFormat(" sigma cov.{0};\r\n", i + 1);
                        cmnd.AppendLine(" number kk;");
                        cmnd.AppendLine("sampsize tmp;"); //Get subgroup size.
                        cmnd.AppendLine("ppoint tmpT2."); //Get Tsquare value.
                    }


                    cmnd.AppendFormat("copy loc.1-loc.p mvect.{0}\r\n", i + 1); //Copy column to mean vector


                    /*
                     * Get the value of m which use to calculate UCL, CL.
                     * In phase II, m is the sample size of the data used to calculate historical
                     * covariance matrix.
                     * In phase I, m is the number of observations.
                     *
                     */
                    cmnd.AppendLine("let m = sum(tmp)"); //Get the actual sample size (include missing data)

                    if (para.Covariance != null)
                    {
                        cmnd.AppendFormat("let histm = ssiz.{0}\r\n", i + 1);
                    }
                    else
                    {
                        cmnd.AppendLine("copy m histm");
                    }


                    // Calculate control limits
                    if (id == null && _chartparaindex.Where(x => x == id).Count() == 1)
                    {
                        cmnd.AppendLine("let tmpUCL=miss()");
                        cmnd.AppendLine("let tmpCL=miss()");
                    }
                    else
                    {
                        cmnd.AppendLine("let conf = 1-alpha");
                        cmnd.AppendLine("let a1 = p");
                        cmnd.AppendLine("let a2 = histm");
                        #region Get UCL
                        cmnd.AppendLine("set tmp");
                        cmnd.AppendLine("(conf)m");
                        cmnd.AppendLine("end");

                        if (id == null) //phase I case
                        {
                            cmnd.AppendLine("invcdf tmp tmpUCL;");
                            cmnd.AppendLine(" beta a1 a2.");
                            cmnd.AppendLine("let tmpUCL = (m-1)**2/m*tmpUCL"); //Get upper control limit
                        }
                        else //phase II case
                        {
                            cmnd.AppendLine("invcdf tmp tmpUCL;");
                            cmnd.AppendLine(" f a1 a2.");
                            cmnd.AppendLine("let tmpUCL = p*(histm+1)*(histm-1)/histm/(histm-p)*tmpUCL"); //Get upper control limit
                        }
                        #endregion
                        #region Get CL
                        cmnd.AppendLine("set tmp");
                        cmnd.AppendLine("(0.5)m");
                        cmnd.AppendLine("end");
                        if (id == null)
                        {
                            cmnd.AppendLine("invcdf tmp tmpCL;");
                            cmnd.AppendLine(" beta a1 a2.");
                            cmnd.AppendLine("let tmpCL = (m-1)**2/m*tmpCL"); //Get upper control limit
                        }
                        else
                        {
                            cmnd.AppendLine("invcdf tmp tmpCL;");
                            cmnd.AppendLine(" f a1 a2.");
                            cmnd.AppendLine("let tmpCL =  p*(histm+1)*(histm-1)/histm/(histm-p)*tmpCL"); //Get center line
                        }
                        #endregion
                    }

                    cmnd.AppendLine("let tmpOOC = if(tmpT2>tmpUCL AND tmpT2<>MISS(),1,0)"); //Get OOC info

                    if (i == 0)
                    {
                        cmnd.AppendLine("copy tmpT2 tmpUCL tmpCL tmpOOC t2 ucl cl ooc");
                    }
                    else
                    {
                        cmnd.AppendLine("stack (t2 ucl cl ooc) (tmpT2 tmpUCL tmpCL tmpOOC) (t2 ucl cl ooc)");
                    }
                }
                //刪除所有圖形
                cmnd.AppendLine("gmana;");
                cmnd.AppendLine("all;");
                cmnd.AppendLine("close;");
                cmnd.AppendLine("nopr.");

                cmnd.AppendLine("endmacro");

                string macPath = Mtblib.Tools.MtbTools.BuildTemporaryMacro("mytsquare.mac", cmnd.ToString());

                string[] matMeanIds = Mtblib.Tools.MtbTools.CreateVariableStrArray(ws, nParas, Mtblib.Tools.MtbVarType.Matrix);
                string[] matCovIds  = Mtblib.Tools.MtbTools.CreateVariableStrArray(ws, nParas, Mtblib.Tools.MtbVarType.Matrix);
                string[] constIds   = Mtblib.Tools.MtbTools.CreateVariableStrArray(ws, 1 * nParas, Mtblib.Tools.MtbVarType.Constant);

                cmnd.Clear();
                cmnd.AppendLine("notitle");
                cmnd.AppendLine("brief 0");
                cmnd.AppendFormat("%\"{0}\" {1};\r\n", macPath, string.Join(" &\r\n", varCols.Select(x => x.SynthesizedName)));
                cmnd.AppendFormat("variance {0} {1};\r\n", string.Join(" &\r\n", matCovIds), string.Join(" &\r\n", constIds));
                cmnd.AppendFormat("meanvect {0};\r\n", string.Join(" &\r\n", matMeanIds));
                cmnd.AppendFormat("ppoint {0};\r\n", pplotCol.SynthesizedName);
                cmnd.AppendFormat("climit {0} {1};\r\n", clCol.SynthesizedName, uclCol.SynthesizedName);
                cmnd.AppendFormat("test {0}.\r\n", oocCol.SynthesizedName);

                string path = Mtblib.Tools.MtbTools.BuildTemporaryMacro("mymacro.mtb", cmnd.ToString());
                proj.ExecuteCommand(string.Format("exec \"{0}\" 1", path), ws);
                #endregion

                //取得參數組
                TsquareParameters tmpPara;
                Mtb.Matrix        mat;
                for (int i = 0; i < _distinctIds.Length; i++)
                {
                    tmpPara        = new TsquareParameters();
                    tmpPara.ParaID = _distinctIds[i];
                    mat            = ws.Matrices.Item(matMeanIds[i]);
                    tmpPara.Mean   = LinearAlgebra.Matrix <double> .Build.DenseOfColumnMajor(mat.RowCount, mat.ColumnCount, mat.GetData());

                    mat = ws.Matrices.Item(matCovIds[i]);
                    tmpPara.Covariance = LinearAlgebra.Matrix <double> .Build.DenseOfColumnMajor(mat.RowCount, mat.ColumnCount, mat.GetData());

                    tmpPara.SampleSize = ws.Constants.Item(constIds[i]).GetData();
                    tmpParaList.Add(tmpPara);
                }
            }

            //繪圖
            //會使用 TIMESTAMP, PPOINT, CL, UCL, TEST
            #region 繪製 T2 Control Chart (TSPLOT)
            string gpath = System.IO.Path.Combine(Environment.GetEnvironmentVariable("tmp"), "Minitab", string.Format("tsquare_{0}.jpg", _rawdata.TableName));
            cmnd.Clear();
            cmnd.AppendFormat("fdate {0};\r\n", timeCol.SynthesizedName);
            cmnd.AppendLine("format(dtyyyy-MM-dd hh:mm).");
            cmnd.AppendFormat("tsplot {0} {1} {2};\r\n", pplotCol.SynthesizedName, uclCol.SynthesizedName, clCol.SynthesizedName);
            cmnd.AppendFormat("gsave \"{0}\";\r\n", gpath);
            cmnd.AppendLine("repl;");
            cmnd.AppendLine("jpeg;");
            cmnd.AppendLine("over;");
            cmnd.AppendFormat("symb {0};\r\n", oocCol.SynthesizedName);
            cmnd.AppendLine("type &");
            double[] oocData = oocCol.GetData();
            if (oocData.Any(x => x == 0))
            {
                cmnd.AppendLine("6 &");
            }
            if (oocData.Any(x => x == 1))
            {
                cmnd.AppendLine("12 &");
            }
            cmnd.AppendLine("0 0 0 0;");
            cmnd.AppendLine("size 1;");
            cmnd.AppendLine("color &");
            if (oocData.Any(x => x == 0))
            {
                cmnd.AppendLine("1 &");                           //r17 color 64
            }
            if (oocData.Any(x => x == 1))
            {
                cmnd.AppendLine("2 &");
            }
            cmnd.AppendLine(";");
            cmnd.AppendLine("conn;");
            cmnd.AppendLine("type 1 1 1;");
            cmnd.AppendLine("color 1 2 120;"); //r17 conn:64 cl: 9, climit:8
            //cmnd.AppendLine("graph;");
            //cmnd.AppendLine("color 22;");
            cmnd.AppendLine("nole;");
            cmnd.AppendFormat("stamp {0};\r\n", timeCol.SynthesizedName);
            cmnd.AppendLine("scale 1;");
            cmnd.AppendFormat("tick 1:{0}/{1};\r\n", pplotCol.RowCount,
                              pplotCol.RowCount > 35 ? Math.Ceiling((double)pplotCol.RowCount / 35) : 1);
            cmnd.AppendLine("axla 1;");
            cmnd.AppendLine("adis 0;");
            cmnd.AppendLine("axla 2;");
            cmnd.AppendLine("adis 0;");
            string ttlString = string.Join(",", varnames);
            if (ttlString.Length > 23)
            {
                ttlString = ttlString.Substring(0, 20) + "...";
            }
            cmnd.AppendLine("graph 8 4;");
            cmnd.AppendFormat("title \"T2管制圖 {0}\";\r\n", ttlString);
            cmnd.AppendFormat("footn \"更新時間: {0}\";\r\n", DateTime.Now);
            cmnd.AppendFormat("ZTag \"{0}\";\r\n", "_T2CHART");
            cmnd.AppendLine(".");

            //刪除所有圖形
            cmnd.AppendLine("gmana;");
            cmnd.AppendLine("all;");
            cmnd.AppendLine("close;");
            cmnd.AppendLine("nopr.");

            string t2MacroPath = Mtblib.Tools.MtbTools.BuildTemporaryMacro("myt2macro.mtb", cmnd.ToString());
            proj.ExecuteCommand(string.Format("exec \"{0}\" 1", t2MacroPath), ws);
            #endregion

            //將檔案轉為二進位陣列
            this.Contents.Add(new RptOutput()
            {
                OType           = MtbOType.GRAPH,
                OutputInByteArr = File.ReadAllBytes(gpath)
            });


            //計算 Decomposition
            if (oocData.Any(x => x == 1))
            {
                DataTable tmpDataTable = _rawdata.Copy();
                tmpDataTable.Columns.Add("OOC", typeof(int));
                for (int r = 0; r < tmpDataTable.Rows.Count; r++)
                {
                    DataRow dr = tmpDataTable.Rows[r];
                    dr["OOC"] = oocData[r];
                }

                //建立 Decomposition 的表格
                DataTable decoTable = new DataTable();
                decoTable.Columns.Add("TIMESTAMP", typeof(DateTime));
                foreach (var item in varnames)
                {
                    decoTable.Columns.Add(item, typeof(double));
                }

                //將OOC的項目值取出
                var subData    = tmpDataTable.Select("OOC=1").CopyToDataTable();
                var oocParaSet = subData.AsEnumerable().Select(dr => dr.Field <string>("CHART_PARA_INDEX")).Distinct().ToArray(); //OOC 的參數組有哪些
                foreach (var item in tmpParaList)
                {
                    if (oocParaSet.Contains(item.ParaID)) //該參數組的觀測值是OOC
                    {
                        //把對應的觀測值轉換成 List<double[]>,其中每個 double[] 是每個 row 的數據
                        var subsubData = subData.Select(string.Format("CHART_PARA_INDEX {0}", item.ParaID == null ? "IS NULL" : "='" + item.ParaID + "'"))
                                         .CopyToDataTable();
                        var obsArray = subsubData.DefaultView.ToTable(false, varnames.ToArray())
                                       .AsEnumerable().Select(x => x.ItemArray.Select(o => Convert.ToDouble(o)).ToArray()).ToList();
                        LinearAlgebra.Matrix <double> obs = LinearAlgebra.Matrix <double> .Build.DenseOfRowArrays(obsArray);

                        LinearAlgebra.Matrix <double> t2deco = Tool.T2Decomposition(obs, item.Mean, item.Covariance);
                        var t2decoByRow = t2deco.EnumerateRows().ToArray();
                        for (int r = 0; r < t2decoByRow.Count(); r++)
                        {
                            DataRow  dr = decoTable.NewRow();
                            object[] o  = new object[1 + t2deco.ColumnCount];
                            t2decoByRow[r].ToArray().CopyTo(o, 1);
                            o[0] = subsubData.Rows[r].Field <DateTime>("TIMESTAMP");
                            decoTable.Rows.Add(o);
                        }
                    }
                }

                cmnd.Clear();
                //LinearAlgebra.Matrix<double> obs = LinearAlgebra.Matrix<double>.Build.DenseOfRowArrays(subData);
                this.Contents.Add(new RptOutput()
                {
                    OType           = MtbOType.TABLE,
                    OutputInByteArr = Tool.ConvertDataSetToByteArray(decoTable)
                });
            }
            else // 沒有 OOC 就不做
            {
                this.Contents.Add(new RptOutput()
                {
                    OType           = MtbOType.TABLE,
                    OutputInByteArr = null
                });
            }
            //Console.ReadKey();
        }