29 changed files with 634 additions and 200 deletions
-
6src/main/java/a8k/app/constant/OptConstant.java
-
29src/main/java/a8k/app/dao/AppStatePersistenceDao.java
-
3src/main/java/a8k/app/dao/type/db/OptCfg.java
-
1src/main/java/a8k/app/dao/type/db/OptRawScanData.java
-
17src/main/java/a8k/app/dao/type/db/ReactionReport.java
-
11src/main/java/a8k/app/factory/A8kOptProcessExceptionFactory.java
-
30src/main/java/a8k/app/i18n/Internationalization.java
-
265src/main/java/a8k/app/optalgo/A8kOptCurveAnalyzer.java
-
49src/main/java/a8k/app/optalgo/A8kPeakAnalyzer.java
-
106src/main/java/a8k/app/optalgo/algo/LinearRegressionCalculator.java
-
1src/main/java/a8k/app/optalgo/type/A8kOptProcessException.java
-
12src/main/java/a8k/app/optalgo/type/PeakPresetPosConfig.java
-
2src/main/java/a8k/app/optalgo/type/ReactionResultStatus.java
-
8src/main/java/a8k/app/service/data/ProjIdCardInfoMgrService.java
-
3src/main/java/a8k/app/service/data/ReactionRecordMgrService.java
-
47src/main/java/a8k/app/service/lowerctrl/OptScanModuleLowerCtrlService.java
-
2src/main/java/a8k/app/service/module/OptScanCtrlModule.java
-
8src/main/java/a8k/app/service/module/SamplePreProcessModule.java
-
11src/main/java/a8k/app/type/a8k/container/A8kOptPeakContainer.java
-
4src/main/java/a8k/app/type/a8k/opt/A8kOptPeak.java
-
1src/main/java/a8k/app/type/a8k/opt/PeakName.java
-
4src/main/java/a8k/app/type/a8k/optfn/A8kOptX.java
-
13src/main/java/a8k/app/type/a8k/state/SampleInfo.java
-
4src/main/java/a8k/extui/mgr/ExtApiPageGroupCfgMgr.java
-
70src/main/java/a8k/extui/page/optalgotest/OptAlgoTestPage.java
-
3src/main/java/a8k/extui/page/test/codetest/OptFormulaTestPageV2.java
-
76src/main/resources/db/zapp_a8k_project_opt_config.csv
-
BINtools/20250427-F-光学光学报告.xlsx
-
BINtools/20250427-T-光学光学报告-2.xlsx
@ -1,8 +1,12 @@ |
|||||
package a8k.app.constant; |
package a8k.app.constant; |
||||
|
|
||||
public class OptConstant { |
public class OptConstant { |
||||
static public final Integer OPT_F_RESULT_TOLERATE = 300; |
|
||||
static public final Integer OPT_T_RESULT_TOLERATE = 700; |
static public final Integer OPT_T_RESULT_TOLERATE = 700; |
||||
static public final Integer OPT_T_TARGET_VAL = 2300; |
static public final Integer OPT_T_TARGET_VAL = 2300; |
||||
|
static public final Integer OPT_T_FINAL_TARGET_VAL = 3600; |
||||
|
|
||||
static public final Integer OPT_F_TARGET_VAL = 3600; |
static public final Integer OPT_F_TARGET_VAL = 3600; |
||||
|
static public final Integer OPT_F_RESULT_TOLERATE = 300; |
||||
|
static public final Integer OPT_F_FINAL_TARGET_VAL = 3600; |
||||
|
static public final Integer OPT_F_OVERFLOW_VAL = 3900; |
||||
} |
} |
@ -0,0 +1,29 @@ |
|||||
|
package a8k.app.dao; |
||||
|
|
||||
|
import a8k.app.dao.type.db.KeyVal; |
||||
|
import a8k.app.utils.ZSqlite; |
||||
|
import jakarta.annotation.PostConstruct; |
||||
|
import jakarta.annotation.Resource; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.springframework.jdbc.core.JdbcTemplate; |
||||
|
import org.springframework.stereotype.Component; |
||||
|
|
||||
|
@Component |
||||
|
@Slf4j |
||||
|
public class AppStatePersistenceDao extends ZSqlite<KeyVal> { |
||||
|
@Resource |
||||
|
JdbcTemplate jdbcTemplate; |
||||
|
|
||||
|
@PostConstruct |
||||
|
void init() { |
||||
|
init(jdbcTemplate, "zapp_state_persistence_dao", KeyVal.class, false); |
||||
|
} |
||||
|
|
||||
|
void storage(String key, String val) { |
||||
|
if (key == null || val == null) { |
||||
|
log.error("key or val is null, key: {}, val: {}", key, val); |
||||
|
return; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,11 @@ |
|||||
|
package a8k.app.factory; |
||||
|
|
||||
|
import a8k.app.i18n.Internationalization; |
||||
|
import a8k.app.optalgo.type.A8kOptProcessException; |
||||
|
import a8k.app.optalgo.type.ReactionResultStatus; |
||||
|
|
||||
|
public class A8kOptProcessExceptionFactory { |
||||
|
static public A8kOptProcessException create(ReactionResultStatus status) { |
||||
|
return new A8kOptProcessException(status, Internationalization.reactionResultStatus2String(status)); |
||||
|
} |
||||
|
} |
@ -0,0 +1,106 @@ |
|||||
|
package a8k.app.optalgo.algo; |
||||
|
|
||||
|
import lombok.Data; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
public class LinearRegressionCalculator { |
||||
|
|
||||
|
|
||||
|
@Data |
||||
|
public static class Point2D { |
||||
|
public double x; |
||||
|
public double y; |
||||
|
|
||||
|
public Point2D(double x, double y) { |
||||
|
this.x = x; |
||||
|
this.y = y; |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
public static double[] calculateRegression(double[] points) { |
||||
|
List<Point2D> pointList = new java.util.ArrayList<>(); |
||||
|
for (int i = 0; i < points.length; i += 1) { |
||||
|
pointList.add(new Point2D(i, points[i])); |
||||
|
} |
||||
|
return calculateRegression(pointList); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* 计算线性回归和相关系数 |
||||
|
* @param points 数据点集合 |
||||
|
* @return 包含斜率、截距和相关系数的数组 [slope, intercept, r] |
||||
|
*/ |
||||
|
public static double[] calculateRegression(List<Point2D> points) { |
||||
|
int n = points.size(); |
||||
|
if (n < 2) { |
||||
|
throw new IllegalArgumentException("至少需要两个点进行计算"); |
||||
|
} |
||||
|
|
||||
|
// 计算x和y的总和 |
||||
|
double sumX = 0, sumY = 0; |
||||
|
for (Point2D p : points) { |
||||
|
sumX += p.getX(); |
||||
|
sumY += p.getY(); |
||||
|
} |
||||
|
|
||||
|
// 计算x和y的平均值 |
||||
|
double meanX = sumX / n; |
||||
|
double meanY = sumY / n; |
||||
|
|
||||
|
// 计算所需的和 |
||||
|
double sumXY = 0, sumXSq = 0, sumYSq = 0; |
||||
|
for (Point2D p : points) { |
||||
|
double xDev = p.getX() - meanX; |
||||
|
double yDev = p.getY() - meanY; |
||||
|
sumXY += xDev * yDev; |
||||
|
sumXSq += xDev * xDev; |
||||
|
sumYSq += yDev * yDev; |
||||
|
} |
||||
|
|
||||
|
// 计算斜率 (m) 和截距 (b) |
||||
|
double slope = sumXY / sumXSq; |
||||
|
double intercept = meanY - slope * meanX; |
||||
|
|
||||
|
// 计算相关系数 r |
||||
|
double r = sumXY / Math.sqrt(sumXSq * sumYSq); |
||||
|
|
||||
|
return new double[]{slope, intercept, r}; |
||||
|
} |
||||
|
|
||||
|
public static void main(String[] args) { |
||||
|
// 示例数据点 |
||||
|
List<Point2D> points = List.of( |
||||
|
new Point2D(1, 2), |
||||
|
new Point2D(2, 3), |
||||
|
new Point2D(3, 5), |
||||
|
new Point2D(4, 4), |
||||
|
new Point2D(5, 6) |
||||
|
); |
||||
|
|
||||
|
// 计算线性回归和相关系数 |
||||
|
double[] result = calculateRegression(points); |
||||
|
double slope = result[0]; |
||||
|
double intercept = result[1]; |
||||
|
double r = result[2]; |
||||
|
|
||||
|
// 输出结果 |
||||
|
System.out.println("回归方程: y = " + String.format("%.4f", slope) + "x + " + String.format("%.4f", intercept)); |
||||
|
System.out.println("相关系数 r = " + String.format("%.4f", r)); |
||||
|
System.out.println("决定系数 R² = " + String.format("%.4f", r * r)); |
||||
|
|
||||
|
// 解释相关系数 |
||||
|
String interpretation; |
||||
|
if (Math.abs(r) >= 0.8) { |
||||
|
interpretation = "强相关"; |
||||
|
} else if (Math.abs(r) >= 0.5) { |
||||
|
interpretation = "中度相关"; |
||||
|
} else { |
||||
|
interpretation = "弱相关"; |
||||
|
} |
||||
|
System.out.println("相关性: " + interpretation); |
||||
|
} |
||||
|
} |
@ -0,0 +1,12 @@ |
|||||
|
package a8k.app.optalgo.type; |
||||
|
|
||||
|
import a8k.app.type.a8k.opt.PeakName; |
||||
|
|
||||
|
import java.util.List; |
||||
|
public class PeakPresetPosConfig { |
||||
|
public PeakName P040 = null; |
||||
|
public PeakName P080 = null; |
||||
|
public PeakName P120 = null; |
||||
|
public PeakName P160 = null; |
||||
|
public PeakName P200 = null; |
||||
|
} |
@ -0,0 +1,70 @@ |
|||||
|
package a8k.extui.page.optalgotest; |
||||
|
|
||||
|
import a8k.app.dao.type.db.ProjExtInfoCard; |
||||
|
import a8k.app.dao.type.db.ReactionReport; |
||||
|
import a8k.app.hardware.type.A8kEcode; |
||||
|
import a8k.app.optalgo.A8kOptCurveAnalyzer; |
||||
|
|
||||
|
import a8k.app.optalgo.A8kPeakAnalyzer; |
||||
|
import a8k.app.optalgo.type.A8kOptPeakInfo; |
||||
|
import a8k.app.service.data.ProjInfoMgrService; |
||||
|
import a8k.app.service.data.ReactionRecordMgrService; |
||||
|
import a8k.app.type.a8k.proj.ProjInfo; |
||||
|
import a8k.app.type.exception.AppException; |
||||
|
import a8k.extui.mgr.ExtApiPageMgr; |
||||
|
import jakarta.annotation.PostConstruct; |
||||
|
import lombok.RequiredArgsConstructor; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.springframework.stereotype.Component; |
||||
|
|
||||
|
@Component |
||||
|
@RequiredArgsConstructor |
||||
|
@Slf4j |
||||
|
public class OptAlgoTestPage { |
||||
|
|
||||
|
private final ExtApiPageMgr extApiPageMgr; |
||||
|
private final ReactionRecordMgrService reactionRecordMgrService; |
||||
|
private final ProjInfoMgrService projInfoMgrService; |
||||
|
|
||||
|
public ReactionReport.ReactionResult testAlgo(Integer recordId, Integer subProjIndex) throws AppException { |
||||
|
ReactionReport record = reactionRecordMgrService.getRecordById(recordId); |
||||
|
if (record == null) { |
||||
|
log.error("Record with ID {} not found", recordId); |
||||
|
throw AppException.of(A8kEcode.CODEERROR, "RECORD NOT FOUND"); |
||||
|
} |
||||
|
|
||||
|
var buildInRecordInfo = projInfoMgrService.getProjBuildInInfo(record.projId); |
||||
|
|
||||
|
|
||||
|
A8kOptCurveAnalyzer a8KOptCurveAnalyzer = new A8kOptCurveAnalyzer(); |
||||
|
A8kOptPeakInfo analysResult = a8KOptCurveAnalyzer.analysisCurve( |
||||
|
record.projId, |
||||
|
buildInRecordInfo.optcfg.get(subProjIndex), |
||||
|
record.detailOptData.get(subProjIndex).rawData.rawData |
||||
|
); |
||||
|
|
||||
|
// ProjExtInfoCard projExtInfoCard = record.projExtInfoCard; |
||||
|
ProjExtInfoCard projExtInfoCard = null; |
||||
|
if (projExtInfoCard == null) { |
||||
|
projExtInfoCard = projInfoMgrService.getProjExtInfoCard(record.lotId); |
||||
|
} |
||||
|
if (projExtInfoCard.lotId == null || projExtInfoCard.lotId.isEmpty()) { |
||||
|
log.error("Project Ext Info Card lotId is empty for record ID {}", recordId); |
||||
|
throw AppException.of(A8kEcode.CODEERROR, "PROJECT EXT INFO CARD LOT ID IS EMPTY"); |
||||
|
} |
||||
|
|
||||
|
ProjInfo projInfo = new ProjInfo(projInfoMgrService.getProjBuildInInfo(record.projId), projExtInfoCard); |
||||
|
|
||||
|
|
||||
|
return A8kPeakAnalyzer.analysisPeakInfo(record.getSampleInfo(), projInfo, subProjIndex, analysResult); |
||||
|
} |
||||
|
|
||||
|
@PostConstruct |
||||
|
public void init() { |
||||
|
var page = extApiPageMgr.newPage(this); |
||||
|
page.addFunction("testAlgo", this::testAlgo) |
||||
|
.setParamVal("recordId", () -> 0) |
||||
|
.setParamVal("subProjIndex", () -> 0); |
||||
|
extApiPageMgr.addPage(page); |
||||
|
} |
||||
|
} |
@ -1,38 +1,38 @@ |
|||||
id,projId,projName,subProjIndex,subProjName,subProjShortName,optType,optScanRange,optScanPeakNum,peakNameRefNum |
|
||||
0,1,hsCRP,0,hsCRP,CA,FOPT,150,3,3 |
|
||||
0,2,PCT,0,PCT,PC,TOPT,150,2,2 |
|
||||
0,3,TSH,0,TSH,TS,FOPT,150,2,2 |
|
||||
0,4,PRL,0,PRL,PL,FOPT,150,2,2 |
|
||||
0,5,T3,0,T3,T3,FOPT,150,2,2 |
|
||||
0,6,T4,0,T4,T4,FOPT,150,2,2 |
|
||||
0,7,Total β hCG,0,Total β hCG,HC,FOPT,150,3,3 |
|
||||
0,8,LH,0,LH,LH,FOPT,150,2,2 |
|
||||
0,9,FSH,0,FSH,FS,FOPT,150,2,2 |
|
||||
0,10,Progesterone,0,Progesterone,PG,FOPT,150,2,2 |
|
||||
0,12,Tn-I plus,0,Tn-I plus,TG,TOPT,150,3,3 |
|
||||
0,13,NT-proBNP,0,NT-proBNP,NB,TOPT,150,3,3 |
|
||||
0,14,CK-MB,0,CK-MB ,CK,FOPT,150,2,2 |
|
||||
0,15,Myoglobin,0,Myoglobin,MY,FOPT,150,2,2 |
|
||||
0,16,D-Dimer,0,D-Dimer,DD,FOPT,150,2,2 |
|
||||
0,17,HbAlC,0,HbAlC,HB,FOPT,150,2,2 |
|
||||
0,18,PCT plus,0,PCT plus,PP,FOPT,150,3,3 |
|
||||
0,20,Tn-I/CK-MB/Myoglobin,0,CK-MB,CK-MB,FOPT,200,3,4 |
|
||||
0,20,Tn-I/CK-MB/Myoglobin,1,Myoglobin,Myoglobin,FOPT,200,3,4 |
|
||||
0,20,Tn-I/CK-MB/Myoglobin,2,Tn-I,Tn-I,TOPT,200,4,4 |
|
||||
0,22,PCT/hsCRP,0,PCT,PCT,TOPT,200,3,4 |
|
||||
0,22,PCT/hsCRP,1,hsCRP,hsCRP,FOPT,200,3,4 |
|
||||
0,24,SAA,0,SAA,SA,FOPT,150,3,3 |
|
||||
0,25,AMH,0,AMH,AM,TOPT,150,3,3 |
|
||||
0,26,SAA/CRP,0,SAA,SAA,FOPT,250,5,5 |
|
||||
0,26,SAA/CRP,1,CRP,CRP,FOPT,250,5,5 |
|
||||
0,27,Vitamin D,0,Vitamin D,VD,FOPT,150,2,2 |
|
||||
0,33,ST2,0,ST2,ST,FOPT,150,2,2 |
|
||||
0,36,MxA,0,MxA,MX,TOPT,150,2,2 |
|
||||
0,48,IL-6,0,IL-6,IL,TOPT,150,3,3 |
|
||||
0,49,Gastrin 17,0,Gastrin 17,GA,TOPT,150,2,2 |
|
||||
0,50,Pepsinogen I/II,0,Pepsinogen I,PG-I,TOPT,150,3,3 |
|
||||
0,50,Pepsinogen I/II,1,Pepsinogen II,PG-II,TOPT,150,3,3 |
|
||||
0,52,NT-proBNP/ST2,0,ST2,ST2,FOPT,200,2,4 |
|
||||
0,52,NT-proBNP/ST2,1,NT-proBNP,NT-proBNP,TOPT,200,3,4 |
|
||||
0,54,Troponin T,0,Troponin T,TT,TOPT,150,3,3 |
|
||||
0,55,BNP,0,BNP,BP,TOPT,150,3,3 |
|
||||
|
id,projId,projName,subProjIndex,subProjName,subProjShortName,optType,optScanRange,optScanPeakNum,peakNameRefNum,peakConfig |
||||
|
0,1,hsCRP,0,hsCRP,CA,FOPT,150,3,3,"[H,T,C,N,N]" |
||||
|
0,2,PCT,0,PCT,PC,TOPT,150,2,2,"[N,C,T,N,N]" |
||||
|
0,3,TSH,0,TSH,TS,FOPT,150,2,2,"[N,T,C,N,N]" |
||||
|
0,4,PRL,0,PRL,PL,FOPT,150,2,2,"[N,T,C,N,N]" |
||||
|
0,5,T3,0,T3,T3,FOPT,150,2,2,"[N,T,C,N,N]" |
||||
|
0,6,T4,0,T4,T4,FOPT,150,2,2,"[N,T,C,N,N]" |
||||
|
0,7,Total β hCG,0,Total β hCG,HC,FOPT,150,3,3,"[H,T,C,N,N]" |
||||
|
0,8,LH,0,LH,LH,FOPT,150,2,2,"[N,T,C,N,N]" |
||||
|
0,9,FSH,0,FSH,FS,FOPT,150,2,2,"[N,T,C,N,N]" |
||||
|
0,10,Progesterone,0,Progesterone,PG,FOPT,150,2,2,"[N,T,C,N,N]" |
||||
|
0,12,Tn-I plus,0,Tn-I plus,TG,TOPT,150,3,3,"[H,T,C,N,N]" |
||||
|
0,13,NT-proBNP,0,NT-proBNP,NB,TOPT,150,3,3,"[H,T,C,N,N]" |
||||
|
0,14,CK-MB,0,CK-MB ,CK,FOPT,150,2,2,"[N,T,C,N,N]" |
||||
|
0,15,Myoglobin,0,Myoglobin,MY,FOPT,150,2,2,"[N,T,C,N,N]" |
||||
|
0,16,D-Dimer,0,D-Dimer,DD,FOPT,150,2,2,"[N,T,C,N,N]" |
||||
|
0,17,HbAlC,0,HbAlC,HB,FOPT,150,2,2,"[N,T,C,N,N]" |
||||
|
0,18,PCT plus,0,PCT plus,PP,FOPT,150,3,3,"[H,T,C,N,N]" |
||||
|
0,20,Tn-I/CK-MB/Myoglobin,0,CK-MB,CK-MB,FOPT,200,3,4,"[N,H,T,C,N]" |
||||
|
0,20,Tn-I/CK-MB/Myoglobin,1,Myoglobin,Myoglobin,FOPT,200,3,4,"[N,H,T,C,N]" |
||||
|
0,20,Tn-I/CK-MB/Myoglobin,2,Tn-I,Tn-I,TOPT,200,4,4,"[R,H,T,C,N]" |
||||
|
0,22,PCT/hsCRP,0,PCT,PCT,TOPT,200,3,4,"[N,H,T,C,N]" |
||||
|
0,22,PCT/hsCRP,1,hsCRP,hsCRP,FOPT,200,3,4,"[R,N,T,C,N]" |
||||
|
0,24,SAA,0,SAA,SA,FOPT,150,3,3,"[H,T,C,N,N]" |
||||
|
0,25,AMH,0,AMH,AM,TOPT,150,3,3,"[H,T,C,N,N]" |
||||
|
0,26,SAA/CRP,0,SAA,SAA,FOPT,250,5,5,"[T4,R,H,T,C]" |
||||
|
0,26,SAA/CRP,1,CRP,CRP,FOPT,250,5,5,"[T4,R,H,T,C]" |
||||
|
0,27,Vitamin D,0,Vitamin D,VD,FOPT,150,2,2,"[N,T,C,N,N]" |
||||
|
0,33,ST2,0,ST2,ST,FOPT,150,2,2,"[N,T,C,N,N]" |
||||
|
0,36,MxA,0,MxA,MX,TOPT,150,2,2,"[N,T,C,N,N]" |
||||
|
0,48,IL-6,0,IL-6,IL,TOPT,150,3,3,"[H,T,C,N,N]" |
||||
|
0,49,Gastrin 17,0,Gastrin 17,GA,TOPT,150,2,2,"[N,T,C,N,N]" |
||||
|
0,50,Pepsinogen I/II,0,Pepsinogen I,PG-I,TOPT,150,3,3,"[H,T,C,N,N]" |
||||
|
0,50,Pepsinogen I/II,1,Pepsinogen II,PG-II,TOPT,150,3,3,"[H,T,C,N,N]" |
||||
|
0,52,NT-proBNP/ST2,0,ST2,ST2,FOPT,200,2,4,"[N,N,T,C,N]" |
||||
|
0,52,NT-proBNP/ST2,1,NT-proBNP,NT-proBNP,TOPT,200,3,4,"[R,H,N,C,N]" |
||||
|
0,54,Troponin T,0,Troponin T,TT,TOPT,150,3,3,"[H,T,C,N,N]" |
||||
|
0,55,BNP,0,BNP,BP,TOPT,150,3,3,"[H,T,C,N,N]" |
Write
Preview
Loading…
Cancel
Save
Reference in new issue