Răsfoiți Sursa

性能验证模块 开发 (二期) / 添加线性验证 - ADLPCTBND

liyuan 1 an în urmă
părinte
comite
004dc901dc

+ 2 - 2
ibps-provider-root/modules/provider-business/src/main/java/com/lc/ibps/components/verification/funcs/TestFuncs.java

@@ -33,8 +33,8 @@ public class TestFuncs {
 
         xValue r = xFuncArray2Args.evalArgs(cNode2, cNode1, xFuncArray2Args.iCORREL);
         System.out.println(r.getDoub() * r.getDoub());
-        PolynomialRegression po = new PolynomialRegression();
-        po.addData(cNode11, cNode21, 1, 1);
+        PolynomialRegression po = new PolynomialRegression(1);
+        po.addData(cNode11, cNode21, 1);
 
         System.out.println("R方为" + po.getRSquared());
         System.out.println("调整R方为" + po.getAdjRSquared());

+ 283 - 0
ibps-provider-root/modules/provider-business/src/main/java/com/lc/ibps/components/verification/model2/LinearRangeADLPctBnd.java

@@ -0,0 +1,283 @@
+package com.lc.ibps.components.verification.model2;
+
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.serializer.SerializerFeature;
+import com.baomidou.mybatisplus.extension.api.R;
+import com.lc.ibps.components.verification.model.InspectionConfigVO;
+import com.lc.ibps.components.verification.regression.PolynomialRegression;
+import com.lc.ibps.components.verification.report.ChartDTO;
+import com.lc.ibps.components.verification.report.TableDTO;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.math3.stat.StatUtils;
+import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics;
+
+import java.util.*;
+
+public class LinearRangeADLPctBnd extends PVModel {
+
+    private final double[] means;
+    private double mean;
+    private final double[] standardDeviations;
+
+    private double[] targetValues;
+    private boolean isTarget = true;
+
+    private double adl;
+    private double cv;
+    private double pctBnd;
+
+    private final PolynomialRegression pr1 = new PolynomialRegression(1);
+    private final PolynomialRegression pr2 = new PolynomialRegression(2);
+    private final PolynomialRegression pr3 = new PolynomialRegression(3);
+    private PolynomialRegression prBest;
+
+    public LinearRangeADLPctBnd(double[][] data, InspectionConfigVO configVO) {
+        super(data, configVO);
+
+        this.means = new double[this.specimensNum];
+        this.standardDeviations = new double[this.specimensNum];
+        this.targetValues = new double[this.specimensNum];
+        calcTarget(configVO.getTargetValue());
+    }
+
+    @Override
+    public void calculate() {
+        final int n = specimensNum * repeatNum;
+        for (int i = 0; i < specimensNum; i++) {
+            DescriptiveStatistics stat = new DescriptiveStatistics(data[i]);
+            means[i] = stat.getMean();
+            standardDeviations[i] = stat.getStandardDeviation();
+
+        }
+        mean = StatUtils.mean(means);
+
+        pr1.addData(targetValues, means, repeatNum);
+        pr2.addData(targetValues, means, repeatNum);
+        pr3.addData(targetValues, means, repeatNum);
+
+        if (pr2.isNonlinear() && pr3.isNonlinear()) {
+            if (pr2.getStdError() > pr3.getStdError()) prBest = pr3;
+            else prBest = pr2;
+        } else if (pr2.isNonlinear()) {
+            prBest = pr2;
+        } else if (pr3.isNonlinear()) {
+            prBest = pr3;
+        } else{
+            prBest = pr1;
+        }
+        //calc sdl
+        if (prBest.getPower()>1) {
+            double valSum = 0.0;
+            for (int i = 0; i < specimensNum; i++) {
+                valSum += Math.pow(prBest.calcFunc(targetValues[i])-pr1.calcFunc(targetValues[i]),2);
+            }
+            adl = 100* Math.sqrt(valSum/n)/mean;
+        }
+        cv = 100d*prBest.getStdError()/mean;
+        pctBnd = 0.05 * Math.sqrt(n/ prBest.getPower() ==3?6.5:6.3);
+    }
+
+    private void calcTarget(double[] targets) {
+        if (ArrayUtils.isEmpty(targets)) {
+            for (int i = 0; i < specimensNum; i++) {
+                targetValues[i] = i + 1;
+            }
+            isTarget = false;
+        } else if (targets.length == 2) {
+            targetValues[0] = targets[0];
+            targetValues[specimensNum - 1] = targets[1];
+            int range = specimensNum - 1;
+            for (int i = 1; i < range; i++) {
+                targetValues[i] = format(targets[0] * (range - i) / range + targets[1] * i / range, 2);
+            }
+        } else if (targets.length == specimensNum) {
+            targetValues = targets;
+        }
+    }
+
+    public TableDTO buildDataTableDTO() {
+        List<String> header = new ArrayList<String>();
+
+        header.add("标本号");
+        if (isTarget) header.add("目标值");
+        for (int i = 1; i <= repeatNum; i++) {
+            header.add(String.format("重复#%d", i));
+        }
+        TableDTO table = new TableDTO();
+        table.buildHeader(header.toArray(new String[header.size()]));
+
+        String[][] r = new String[specimensNum][];
+        for (int i = 0; i < data.length; i++) {
+            List<String> rl = new ArrayList();
+            rl.add(String.valueOf(i + 1));
+            if (isTarget) rl.add(String.valueOf(targetValues[i]));
+
+            for (int j = 0; j < data[i].length; j++) {
+                rl.add(format(data[i][j]));
+            }
+            r[i] = rl.toArray(new String[rl.size()]);
+        }
+        table.buildData(r);
+        return table;
+    }
+
+
+    @Override
+    public String generateResult() {
+        return renderReportTemplate(this, "/report/linearRangeEP6A.ftl");
+    }
+
+
+    @Override
+    public String[] tableNames() {
+        return new String[]{"表1: 重复性差异检测结果", "表2: 多项式回归分析结果", "表3: 线性偏离计算结果"};
+    }
+
+    @Override
+    public String[] chartNames() {
+        return new String[]{"图1: 线性实验", "图2: 线性评价差值点图"};
+    }
+
+//    @Override
+//    ChartDTO buildChart2DTO(int sheetIndex) {
+//        ChartDTO chartDTO = new ChartDTO("linesForRange");
+//        double[][] data = new double[targetValues.length][2];
+//        for (int i = 0; i < data.length; i++) {
+//            data[i] = new double[]{i + 1, diffs[1][i]};
+//        }
+////        chartDTO.setData(data);
+//        final HashMap<String, Object> config = new HashMap<>();
+//        config.put("yAxisUp", 0.1);
+//        config.put("yAxisLow", -0.1);
+//        config.put("data", JSONObject.toJSONString(data, SerializerFeature.DisableCircularReferenceDetect));
+//
+//        chartDTO.setOption(renderChartTemplate(config, 1, "/scatter/linesForRange.ftl"));
+//        return chartDTO;
+//    }
+
+    @Override
+    ChartDTO buildChart1DTO(int sheetIndex) {
+        ChartDTO chartDTO = new ChartDTO("polynomialRegression");
+        double[][] data = new double[targetValues.length][2];
+        for (int i = 0; i < data.length; i++) {
+            data[i] = new double[]{targetValues[i], means[i]};
+        }
+//        chartDTO.setData(data);
+        Map<String, Object> map = new HashMap<>();
+        map.put("data", JSONObject.toJSONString(data, SerializerFeature.DisableCircularReferenceDetect));
+
+        chartDTO.setOption(renderChartTemplate(map, 0, "/scatter/polynomialRegression.ftl"));
+        return chartDTO;
+    }
+    @Override
+    TableDTO buildTable2DTO(int sheetIndex) {
+
+        TableDTO table = new TableDTO();
+        String[] header = {"阶别", "系数", "系数值", "系数标准误", "t 检验", "自由度", "回归标准误"};
+        table.buildHeader(header);
+        table.getHeader()[0].put("merge", "true");
+        table.getHeader()[5].put("merge", "true");
+        table.getHeader()[6].put("merge", "true");
+        String[][] r = new String[9][7];
+        int i = 0;
+        for (int j = 0; j < pr1.getParameters().length; j++) {
+            r[i][0] = "一阶";
+            r[i][1] = String.format("b%d", j);
+            r[i][2] = format(pr1.getParameters()[j]);
+            r[i][3] = format(pr1.getStdErrors()[j]);
+            r[i][4] = format(pr1.gettValues()[j]);
+            r[i][5] = pr1.getDfDependent().toString();
+            r[i][6] = format((pr1.getStdError()));
+            i++;
+        }
+        for (int j = 0; j < pr2.getParameters().length; j++) {
+            r[i][0] = "二阶";
+            r[i][1] = String.format("b%d", j);
+            r[i][2] = format(pr2.getParameters()[j]);
+            r[i][3] = format(pr2.getStdErrors()[j]);
+            r[i][4] = format(pr2.gettValues()[j]);
+            r[i][5] = pr2.getDfDependent().toString();
+            r[i][6] = format((pr2.getStdError()));
+            i++;
+        }
+        for (int j = 0; j < pr3.getParameters().length; j++) {
+            r[i][0] = "三阶";
+            r[i][1] = String.format("b%d", j);
+            r[i][2] = format(pr3.getParameters()[j]);
+            r[i][3] = format(pr3.getStdErrors()[j]);
+            r[i][4] = format(pr3.gettValues()[j]);
+            r[i][5] = pr3.getDfDependent().toString();
+            r[i][6] = format((pr3.getStdError()));
+            i++;
+        }
+        table.buildData(r);
+        return table;
+    }
+    @Override
+    TableDTO buildTable3DTO(int sheetIndex) {
+
+        TableDTO table = new TableDTO();
+        String[] header = {"不精密度百分比", "L×R=10", "L×R=12", "L×R=14", "L×R=16", "L×R=18","L×R=20"};
+        table.buildHeader(header);
+
+
+        String[][] r3 = new String[][]{
+            {"1","5.5","5.5","5.4","5.4","5.4","5.4"},
+            {"2","6.1","6.0","5.9","5.9","5.8","5.8"},
+            {"3","6.7","6.5","6.4","6.3","6.2","6.2"},
+            {"4","7.2","7.0","6.9","6.8","6.7","6.6"},
+            {"5","7.8","7.6","7.4","7.2","7.1","7.0"},
+            {"6","8.4","8.1","7.9","7.7","7.5","7.4"},
+            {"7","9.0(P)","8.7(P)","8.4","8.2","8.0","7.8"},
+            {"8","P","P","8.9(P)","8.6(P)","8.4","8.2"},
+            {"9","P","P","P","P","8.9(P)","8.7(P)"},
+            {">9","P","P","P","P","P","P"}
+        };
+
+        String[][] r1 = new String[][]{
+                {"1","5.5","5.5","5.4","5.4","5.4","5.4"},
+                {"2","6.1","6.0","5.9","5.8","5.8","5.7"},
+                {"3","6.6","6.4","6.3","6.3","6.2","6.1"},
+                {"4","7.1","6.9","6.8","6.7","6.6","6.5"},
+                {"5","6.6","7.4","7.2","7.1","7.0","6.9"},
+                {"6","8.2","7.9","7.7","7.5","7.4","7.2"},
+                {"7","8.7(P)","8.4(P)","8.1","7.9","7.8","7.6"},
+                {"8","P","P","8.6(P)","8.3(P)","8.1","8.0"},
+                {"9","P","P","P","P","8.5(P)","8.3(P)"},
+                {">9","P","P","P","P","P","P"}
+        };
+
+
+        table.buildData(prBest == pr3?r3:r1);
+        final String note = new StringJoiner("<br />")
+                .add("L: 样本数")
+                .add("R: 重复测量的次数")
+                .add("P: 标注P的表格表示最优拟合方程的精密度太差,无法进行线性判断").toString();
+        table.setNote(note);
+        return table;
+    }
+
+    public double getMean() {
+        return mean;
+    }
+
+    public void setMean(double mean) {
+        this.mean = mean;
+    }
+
+    public double getAdl() {
+        return adl;
+    }
+
+    public void setAdl(double adl) {
+        this.adl = adl;
+    }
+
+    public double getCv() {
+        return cv;
+    }
+
+    public void setCv(double cv) {
+        this.cv = cv;
+    }
+}

+ 7 - 7
ibps-provider-root/modules/provider-business/src/main/java/com/lc/ibps/components/verification/model2/LinearRangeEP6A.java

@@ -25,9 +25,9 @@ public class LinearRangeEP6A extends PVModel {
     private boolean isTarget = true;
 
 
-    private final PolynomialRegression pr1 = new PolynomialRegression();
-    private final PolynomialRegression pr2 = new PolynomialRegression();
-    private final PolynomialRegression pr3 = new PolynomialRegression();
+    private final PolynomialRegression pr1 = new PolynomialRegression(1);
+    private final PolynomialRegression pr2 = new PolynomialRegression(2);
+    private final PolynomialRegression pr3 = new PolynomialRegression(3);
     private PolynomialRegression prBest;
 
 
@@ -66,9 +66,9 @@ public class LinearRangeEP6A extends PVModel {
         cvr = Math.sqrt(StatUtils.mean(diffs[4])) * 100;
         //TODO: check cvr
 
-        pr1.addData(targetValues, means, repeatNum, 1);
-        pr2.addData(targetValues, means, repeatNum, 2);
-        pr3.addData(targetValues, means, repeatNum, 3);
+        pr1.addData(targetValues, means, repeatNum);
+        pr2.addData(targetValues, means, repeatNum);
+        pr3.addData(targetValues, means, repeatNum);
 
         if (pr2.isNonlinear() && pr3.isNonlinear()) {
             if (pr2.getStdError() > pr3.getStdError()) prBest = pr3;
@@ -146,7 +146,7 @@ public class LinearRangeEP6A extends PVModel {
 
     @Override
     public String generateResult() {
-        return renderReportTemplate(this, null);
+        return renderReportTemplate(this, "/report/linearRangeEP6A.ftl");
     }
 
 

+ 20 - 3
ibps-provider-root/modules/provider-business/src/main/java/com/lc/ibps/components/verification/regression/PolynomialRegression.java

@@ -15,14 +15,15 @@ public class PolynomialRegression extends Regression {
 
     private boolean isNonlinear = false;
     private double t;
+    private int power;
 
-
-    public PolynomialRegression() {
+    public PolynomialRegression(int power) {
         ols = new OLSMultipleLinearRegression();
+        this.power = power;
     }
 
 
-    public void addData(double[] xArray, double[] yArray, int repeatNum, int power) {
+    public void addData(double[] xArray, double[] yArray, int repeatNum) {
 
         double[][] independentVariable = generateVariable(xArray, power);
         int dfDependent = yArray.length * repeatNum - power - 1;
@@ -131,4 +132,20 @@ public class PolynomialRegression extends Regression {
     public void settValues(double[] tValues) {
         this.tValues = tValues;
     }
+
+    public double getT() {
+        return t;
+    }
+
+    public void setT(double t) {
+        this.t = t;
+    }
+
+    public int getPower() {
+        return power;
+    }
+
+    public void setPower(int power) {
+        this.power = power;
+    }
 }

+ 2 - 2
ibps-provider-root/modules/provider-business/src/main/java/com/lc/ibps/components/verification/regression/StatisticsTest.java

@@ -69,8 +69,8 @@ public class StatisticsTest {
 //        w.add(24.56,24.06);
         double[] xArray = {0, 4.91, 9.82, 14.74, 19.65, 24.56};
         double[] yArray = {-0.01, 5, 10.12, 14.65, 19.61, 24.06};
-        final PolynomialRegression po = new PolynomialRegression();
-        po.addData(xArray, yArray, 1, 3);
+        final PolynomialRegression po = new PolynomialRegression(3);
+        po.addData(xArray, yArray, 1);
 
         System.out.println("R方为" + po.getRSquared());
         System.out.println("调整R方为" + po.getAdjRSquared());

+ 11 - 3
ibps-provider-root/modules/provider-business/src/test/java/com/lc/ibps/components/verification/model2/LinearRangeEP6ATest.java

@@ -5,6 +5,7 @@ import com.alibaba.fastjson.serializer.SerializerFeature;
 import com.lc.ibps.components.verification.model.InspectionConfigVO;
 import com.lc.ibps.components.verification.report.ReportDataDTO;
 import com.lc.ibps.components.verification.report.ReportFactory;
+import org.apache.commons.lang3.RandomUtils;
 import org.apache.commons.math3.linear.MatrixUtils;
 import org.apache.commons.math3.linear.RealMatrix;
 import org.apache.commons.math3.linear.RealMatrixFormat;
@@ -26,10 +27,17 @@ public class LinearRangeEP6ATest {
     public void calculate() {
         InspectionConfigVO config = new InspectionConfigVO("EP6-A线性评价", 1, 6,
                 null, 2, LocalDate.now(), true);
-        config.setTargetValue(new double[]{0, 24.56});
+        config.setTargetValue(new double[]{0, 10});
+        config.setDecimal(3);
+        config.setUnits("mmg/L");
         config.setKey(ModelEnum.LinearRangeEP6A.getKey());
-        double[][] data = {{-0.01, -0.01}, {5.00, 4.99}, {10.18, 10.05}, {14.65, 14.65}, {19.57, 19.65}, {24.02, 24.09}};
-
+        RandomUtils.nextDouble();
+        double[][] data = new double[config.getSpecimensNum()][config.getRepeatNum()];
+        for (int i = 0; i < config.getSpecimensNum(); i++) {
+            for (int j = 0; j < config.getRepeatNum(); j++) {
+                data[i][j] = RandomUtils.nextDouble(0+i*2, 1+i*2);
+            }
+        }
         RealMatrix matrix = MatrixUtils.createRealMatrix(data);
         RealMatrixFormat matrixFormat = new RealMatrixFormat("", "", "", "\n",
                 "", ",", new DecimalFormat("0.00"));