Просмотр исходного кода

[task-1853] 性能验证模块 开发 (二期) / 线性区间验证:WST 408

Li Yuan 1 год назад
Родитель
Сommit
39521e3e5e

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

@@ -30,6 +30,8 @@ public class LinearRangeADLPctBnd extends PVModel {
     private final PolynomialRegression pr2 = new PolynomialRegression(2);
     private final PolynomialRegression pr3 = new PolynomialRegression(3);
     private PolynomialRegression prBest;
+    private int n;
+    private String[][] checkTable;
 
     public LinearRangeADLPctBnd(double[][] data, InspectionConfigVO configVO) {
         super(data, configVO);
@@ -42,7 +44,7 @@ public class LinearRangeADLPctBnd extends PVModel {
 
     @Override
     public void calculate() {
-        final int n = specimensNum * repeatNum;
+        n = specimensNum * repeatNum;
         for (int i = 0; i < specimensNum; i++) {
             DescriptiveStatistics stat = new DescriptiveStatistics(data[i]);
             means[i] = stat.getMean();
@@ -124,53 +126,39 @@ public class LinearRangeADLPctBnd extends PVModel {
 
     @Override
     public String generateResult() {
-        return renderReportTemplate(this, "/report/linearRangeEP6A.ftl");
+        return renderReportTemplate(this, "/report/linearRangeADL.ftl");
     }
 
 
     @Override
     public String[] tableNames() {
-        return new String[]{"表1: 重复性差异检测结果", "表2: 多项式回归分析结果", "表3: 线性偏离计算结果"};
+        return new String[]{ "表1: 多项式回归分析结果",
+                String.format("表2: 不精密度和ADL的临界值(PcrBnd=5%%,%s方程)",prBest.getPower()>2?"3阶":"1或2阶")};
     }
 
     @Override
     public String[] chartNames() {
-        return new String[]{"图1: 线性实验", "图2: 线性评价差值点图"};
+        return new String[]{"图1: 线性范围验证实验"};
     }
 
-//    @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]};
+            data[i] = new double[]{targetValues[i], format(means[i],getScale())};
         }
 //        chartDTO.setData(data);
         Map<String, Object> map = new HashMap<>();
         map.put("data", JSONObject.toJSONString(data, SerializerFeature.DisableCircularReferenceDetect));
-
+        map.put("power",prBest.getPower());
         chartDTO.setOption(renderChartTemplate(map, 0, "/scatter/polynomialRegression.ftl"));
         return chartDTO;
     }
+
     @Override
-    TableDTO buildTable2DTO(int sheetIndex) {
+
+    TableDTO buildTable1DTO(int sheetIndex) {
 
         TableDTO table = new TableDTO();
         String[] header = {"阶别", "系数", "系数值", "系数标准误", "t 检验", "自由度", "回归标准误"};
@@ -214,7 +202,7 @@ public class LinearRangeADLPctBnd extends PVModel {
         return table;
     }
     @Override
-    TableDTO buildTable3DTO(int sheetIndex) {
+    TableDTO buildTable2DTO(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"};
@@ -247,8 +235,8 @@ public class LinearRangeADLPctBnd extends PVModel {
                 {">9","P","P","P","P","P","P"}
         };
 
-
-        table.buildData(prBest == pr3?r3:r1);
+        checkTable = prBest == pr3?r3:r1;
+        table.buildData(checkTable);
         final String note = new StringJoiner("<br />")
                 .add("L: 样本数")
                 .add("R: 重复测量的次数")
@@ -280,4 +268,76 @@ public class LinearRangeADLPctBnd extends PVModel {
     public void setCv(double cv) {
         this.cv = cv;
     }
+
+    public double getPctBnd() {
+        return pctBnd;
+    }
+
+    public void setPctBnd(double pctBnd) {
+        this.pctBnd = pctBnd;
+    }
+
+    public PolynomialRegression getPr1() {
+        return pr1;
+    }
+
+    public PolynomialRegression getPr2() {
+        return pr2;
+    }
+
+    public PolynomialRegression getPr3() {
+        return pr3;
+    }
+
+    public PolynomialRegression getPrBest() {
+        return prBest;
+    }
+
+    public void setPrBest(PolynomialRegression prBest) {
+        this.prBest = prBest;
+    }
+    public String getBestName(){
+        if(prBest.getPower() ==1){
+            return "一";
+        }else{
+            return prBest.getPower() == 2?"二":"三";
+        }
+    }
+
+    public int getN() {
+        return n;
+    }
+
+    public int getCheckTableIndex(){
+        return n/2 - 4;
+    }
+
+    public String getRangeFormat(){
+        StringBuilder sb = new StringBuilder();
+        sb.append(String.format("最优拟合方程是%s阶方程,在L×R=%s和不精密度百分比=%s%%时,",getBestName(),n,format(cv)));
+
+        int up = (int)Math.floor(cv);
+        if(up>9){
+            return sb.toString() + "查表2临界值为P,表明测量数据的精密度不符合作线性评价的要求.";
+        }
+        String s1 = checkTable[up][getCheckTableIndex()];
+        String s2 = "0";
+
+        if (up > 0) {
+            s2 = checkTable[up - 1][getCheckTableIndex()];
+        }
+        String format = String.format("查表2临界值为%s%%~%s%%,", s2, s1);
+        if (format.contains("P")){
+            return sb.toString() + format + "包含标注字母P,表明测量数据的精密度不符合作线性评价的要求.";
+        } else{
+            sb.append(format).append("没有标注字母P,表明测量数据的精密度符合作线性评价的要求。");
+            if(adl <= Double.valueOf(s1)){
+                sb.append(String.format("ADL=%s%%,小于临界值%s%%~%s%%,表明数据组具有临床可接受的非线性或%s阶线性。",format(adl,getScale()),s2,s1,getBestName()));
+            }else{
+                sb.append(String.format("ADL=%s%%,大于临界值%s%%~%s%%,表明数据组具有临床不可接受的非线性。",format(adl,getScale()),s2,s1));
+            }
+        }
+
+        return sb.toString();
+    }
 }

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

@@ -7,6 +7,7 @@ public enum ModelEnum {
     TruenessEP15Patient("正确度:使用患者样品验证"),
     TruenessRefernece("正确度:使用定值参考物质验证"),
     LinearRangeEP6A("线性区间:EP6线性评价"),
+    LinearRangeADL("线性区间:WST408线性评价"),
     LinearRangeAverageSlope("线性区间:平均斜率评价法"),
     LinearRangeRecoveryMethod("线性区间:线性稀释回收法");
     private final String key;

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

@@ -109,6 +109,8 @@ public class PVItemBuilder {
             pvModel = new LinearRangeAverageSlope(dataArrays, config);
         } else if (config.getKey().equals(ModelEnum.LinearRangeRecoveryMethod.getKey())) {
             pvModel = new LinearRangeRecoveryMethod(dataArrays, config);
+        } else if (config.getKey().equals(ModelEnum.LinearRangeADL.getKey())) {
+            pvModel = new LinearRangeADLPctBnd(dataArrays, config);
         } else {
             return null;
         }

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

@@ -60,7 +60,7 @@ public abstract class PVModel {
                     String value = (String) chart.get("value");
                     String label = (String) chart.get("label");
                     chartNames.add(label);
-                    stringLoader.putTemplate(label + "Chart", value.replaceAll("\\s*|\t|\r|\n", ""));
+                    stringLoader.putTemplate(label + "Chart", value);
                 }
             }
         }

+ 18 - 0
ibps-provider-root/modules/provider-business/src/main/resources/pv/report/linearRangeADL.ftl

@@ -0,0 +1,18 @@
+进行t检验后表明
+<#if !pr3.isNonlinear() && !pr2.isNonlinear() >
+三阶和二阶系数都无统计学意义(p>0.05),数据组符合统计学标准的线性。对数据组进行精密度检验。
+<#else>
+    <#if pr2.isNonlinear()>
+二阶系数有统计学意义(p<0.05),
+    <#else>
+二阶系数无统计学意义(p>0.05),
+    </#if>
+    <#if pr3.isNonlinear()>
+三阶系数有统计学意义(p<0.05),
+    <#else>
+三阶系数无统计学意义(p>0.05),
+    </#if>
+数据拟合结果是统计学标准的非线性。对数据组进行非线性程度判断及测定精密度检验。
+</#if>
+计算最佳拟合回归标准误σ=${prBest.stdError},总平均浓度=${mean},不精密度百分比=${cv}%。
+由ADL计算公式得ADL=${adl}%。${rangeFormat}

+ 6 - 4
ibps-provider-root/modules/provider-business/src/main/resources/pv/scatter/polynomialRegression.ftl

@@ -8,7 +8,7 @@
   },
   dataset: [
     {
-      source: ${data}
+      source: '${data}'
     },
     {
       transform: {
@@ -18,16 +18,18 @@
           order: 1
         }
       }
-    },
-    {
+    }
+<#if (power > 1) >
+    ,{
       transform: {
         type: 'ecStat:regression',
         config: {
           method: 'polynomial',
-          order: 2
+          order: ${power}
         }
       }
     }
+</#if>
   ],
   title: {
     text: '线性回归图',

+ 51 - 0
ibps-provider-root/modules/provider-business/src/test/java/com/lc/ibps/components/verification/model2/LinearRangeADLPctBndTest.java

@@ -0,0 +1,51 @@
+package com.lc.ibps.components.verification.model2;
+
+import com.alibaba.fastjson.JSONObject;
+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 junit.framework.TestCase;
+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;
+
+import java.text.DecimalFormat;
+import java.time.LocalDate;
+
+public class LinearRangeADLPctBndTest extends TestCase {
+
+    public void setUp() throws Exception {
+        super.setUp();
+    }
+
+    public void testCalculate() {
+        InspectionConfigVO config = new InspectionConfigVO("WST408线性评价", 1, 6,
+                null, 3, LocalDate.now(), true);
+        config.setTargetValue(new double[]{0, 10});
+        config.setDecimal(3);
+        config.setUnits("mmg/L");
+        config.setKey(ModelEnum.LinearRangeADL.getKey());
+        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"));
+        System.out.println(matrixFormat.format(matrix));
+
+        PVItemBuilder pvItemBuilder = PVItemBuilder.getInstance(config);
+        pvItemBuilder.buildPVModel(data);
+        ReportDataDTO dataDTO = ReportFactory.build(pvItemBuilder);
+        String s = JSONObject.toJSONString(dataDTO, SerializerFeature.DisableCircularReferenceDetect);
+        String s1 = pvItemBuilder.getPvModel().generateResult();
+        System.out.println(s);
+        System.out.println(s1);
+
+    }
+}