diff --git a/pom.xml b/pom.xml index 6d7a6c7..a632091 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ com.iflytop a800 - 0.0.10 + 0.0.11 boditech-a800 boditech-a800 @@ -20,7 +20,7 @@ com.iflytop uf - 0.0.43 + 0.0.57 diff --git a/src/main/java/com/iflytop/a800/utils/ScanResultAnalyseResultItem.java b/src/main/java/com/iflytop/a800/utils/ScanResultAnalyseResultItem.java new file mode 100644 index 0000000..ad0b268 --- /dev/null +++ b/src/main/java/com/iflytop/a800/utils/ScanResultAnalyseResultItem.java @@ -0,0 +1,6 @@ +package com.iflytop.a800.utils; +public class ScanResultAnalyseResultItem { + public String name; + public double value; + public String unit; +} diff --git a/src/main/java/com/iflytop/a800/utils/ScanResultAnalyser.java b/src/main/java/com/iflytop/a800/utils/ScanResultAnalyser.java new file mode 100644 index 0000000..8538d93 --- /dev/null +++ b/src/main/java/com/iflytop/a800/utils/ScanResultAnalyser.java @@ -0,0 +1,143 @@ +package com.iflytop.a800.utils; +import com.fasterxml.jackson.databind.JsonNode; +import com.iflytop.a800.model.MdbIdChip; +import com.iflytop.uf.util.UfJsonHelper; +import java.util.*; +public class ScanResultAnalyser { + // id chip + private final MdbIdChip idChip; + + // constructor + public ScanResultAnalyser( MdbIdChip idChip ) { + this.idChip = idChip; + } + + // analyse + public List analyse( String sampleType, float[] scanResult ) { + var algo = new ScanResultAnalysisAlgo(); + var algoResult = algo.calculate(scanResult, this.idChip.peakCount); + + // 处理 + List results = new ArrayList<>(); + var projects = UfJsonHelper.jsonToNode(idChip.items); + for ( var i=0; i< idChip.itemCount; i++ ) { + double valueX = 0; + JsonNode funcInfo = null; + + var project = projects.get(i); + var itemName = project.get("item").asText(); + var isPiecewiseFunction = project.get("isPiecewiseFunction").asBoolean(); + if ( !isPiecewiseFunction ) { // 非分段函数 + var func = project.get("nonPiecewiseFunction"); + var xValueSource = func.get("xValueSource").asInt(); + valueX = this.calculateRatio(algoResult, xValueSource, itemName); + funcInfo = func.get("serum"); + if ("WB".equals(sampleType)) { + funcInfo = func.get("wb"); + } + } else { // 分段函数 + var func = project.get("piecewiseFunction"); + var piecewiseValueSrc = func.get("piecewiseValueSrc").asInt(); + var piecewiseValueSrcValue = this.calculateRatio(algoResult, piecewiseValueSrc, itemName); + var piecewiseValue = func.get("piecewiseValue").asDouble(); + if ( piecewiseValueSrcValue > piecewiseValue ) { // 高浓度 + var highXValueSource = func.get("highXValueSource").asInt(); + valueX = this.calculateRatio(algoResult, highXValueSource, itemName); + funcInfo = func.get("serumHigh"); + if ("WB".equals(sampleType)) { + funcInfo = func.get("wbHigh"); + } + } else { // 低浓度 + var lowXValueSource = func.get("lowXValueSource").asInt(); + valueX = this.calculateRatio(algoResult, lowXValueSource, itemName); + funcInfo = func.get("serumLow"); + if ("WB".equals(sampleType)) { + funcInfo = func.get("wbLow"); + } + } + } + + double valueD = funcInfo.get("d").asDouble(); + double valueB = funcInfo.get("b").asDouble(); + double valueC = funcInfo.get("c").asDouble(); + double valueA = funcInfo.get("a").asDouble(); + double value = valueA * Math.pow(valueX,3) + valueB * Math.pow(valueX,2) + valueC * valueX + valueD; + + // @TODO : 单位也要从配置中读取 + var result = new ScanResultAnalyseResultItem(); + result.name = itemName; + result.value = value; + result.unit = "xx/xx"; + results.add(result); + } + + return results; + } + + /** + * @link https://iflytop1.feishu.cn/docx/UnRtdSG4qouMTaxzRb2cjiTTnZe + * @link https://iflytop1.feishu.cn/docx/A0CHdQL6OoTTCSx8MB7cQKEjnSc + * @param result - algo result + * @param xSource - x source + * @return double - value of ratio + */ + private double calculateRatio(ScanResultAnalysisAlgo.AlgoResult result, int xSource, String itenName) { + // 计算 ratio + Map ratios = new HashMap<>(); + if ( 5 == idChip.scanPeakCount ) { + var peaks = result.peakInfos; + ratios.put("ratio", peaks[3].area / peaks[4].area); // T/C + ratios.put("antiRatio", peaks[3].area / peaks[4].area); // H/C + ratios.put("antiTestRatio", peaks[3].area / peaks[2].area); // T/H + ratios.put("rfRatio", peaks[1].area / peaks[4].area); // R/C + ratios.put("rtRatio", peaks[3].area / peaks[1].area); // T/R + ratios.put("t4Ratio", peaks[0].area / peaks[4].area); // T4/C + ratios.put("t4t3Ratio", peaks[1].area / peaks[0].area); // R/T4 + } else if ( 4 == idChip.scanPeakCount && Objects.equals(idChip.scanType, 1) ) { // F 光学 + var peaks = result.peakInfos; // H T C + ratios.put("ratio", peaks[1].area / peaks[2].area); // T/C + ratios.put("antiRatio", peaks[0].area / peaks[2].area); // H/C + ratios.put("antiTestRatio", peaks[1].area / peaks[0].area); // T/H + ratios.put("rfRatio", peaks[0].area / peaks[2].area); // R/C @TODO : 待定, 三联卡F光学没有R + ratios.put("rtRatio", peaks[1].area / peaks[0].area); // T/R @TODO : 待定, 三联卡F光学没有R + } else if ( 4 == idChip.scanPeakCount && Objects.equals(idChip.scanType, 2) ) { // T 光学 + var peaks = result.peakInfos; // R H T C + ratios.put("ratio", peaks[2].area / peaks[3].area); // T/C + ratios.put("antiRatio", peaks[1].area / peaks[3].area); // H/C + ratios.put("antiTestRatio", peaks[2].area / peaks[1].area); // T/H + ratios.put("rfRatio", peaks[0].area / peaks[3].area); // R/C + ratios.put("rtRatio", peaks[2].area / peaks[0].area); // T/R + } else if ( 3 == idChip.scanPeakCount ) { + var peaks = result.peakInfos; // H T C + ratios.put("ratio", peaks[1].area / peaks[2].area); // T/C + ratios.put("antiRatio", peaks[0].area / peaks[2].area); // H/C + ratios.put("antiTestRatio", peaks[1].area / peaks[0].area); // T/H + } else if ("PCT".equals(itenName)) { + var peaks = result.peakInfos; // C T + ratios.put("ratio", peaks[1].area / peaks[0].area); // T/C + } else if ( 2 == idChip.scanPeakCount ) { + var peaks = result.peakInfos; // T C + ratios.put("ratio", peaks[0].area / peaks[1].area); // T/C + } else { + throw new RuntimeException("unknown scan peak count" + idChip.scanPeakCount); + } + + // calculate ratio by x source + if ( 1 == xSource ) { + return ratios.get("ratio"); + } else if ( 2 == xSource ) { + return ratios.get("antiTestRatio"); + } else if ( 3 == xSource ) { + return ratios.get("antiRatio"); + } else if ( 4 == xSource ) { + return ratios.get("ratio") + ratios.get("antiTestRatio"); + } else if ( 5 == xSource ) { + // @TODO : 这里 R-ratio 不知道是啥 + throw new RuntimeException("不知道 R-Ratio 是啥"); + } else if ( 6 == xSource ) { + return ratios.get("t4Ratio"); + } else { + throw new RuntimeException("unknown x source" + xSource); + } + } +}