62 changed files with 796 additions and 803 deletions
-
8src/main/java/a8k/a8kproj/A8kIdCardDataParseService.java
-
24src/main/java/a8k/a8kproj/A8kOptScanResultAnalyzer.java
-
25src/main/java/a8k/a8kproj/fakeoptpeak/FakeOptPeakFactory.java
-
2src/main/java/a8k/a8kproj/fakeproj/FAKE_PROJ_01_FLOW1.java
-
2src/main/java/a8k/a8kproj/fakeproj/FAKE_PROJ_02_FLOW2.java
-
2src/main/java/a8k/a8kproj/fakeproj/FAKE_PROJ_03.java
-
2src/main/java/a8k/a8kproj/fakeproj/FAKE_PROJ_04.java
-
2src/main/java/a8k/a8kproj/fakeproj/FAKE_PROJ_05.java
-
2src/main/java/a8k/a8kproj/fakeproj/FAKE_PROJ_06.java
-
2src/main/java/a8k/a8kproj/fakeproj/FAKE_PROJ_07_EXPIRED.java
-
10src/main/java/a8k/a8kproj/fakeproj/FakeProjInfo.java
-
8src/main/java/a8k/a8kproj/fakeproj/FakeProjInfoFactory.java
-
216src/main/java/a8k/a8kproj/fakeprojcontext/FakeProjInfoContextFactory.java
-
241src/main/java/a8k/a8kproj/optalgo/A8kOptAlgo.java
-
18src/main/java/a8k/a8kproj/optalgo/type/A8kOptPeak.java
-
10src/main/java/a8k/a8kproj/optalgo/type/A8kOptPeakArea.java
-
14src/main/java/a8k/a8kproj/optalgo/type/A8kOptPeakAreas.java
-
19src/main/java/a8k/a8kproj/optalgo/type/A8kOptPeaks.java
-
6src/main/java/a8k/a8kproj/optanalyzer/A8kOptXGetter.java
-
3src/main/java/a8k/a8kproj/optanalyzer/OptChecker.java
-
20src/main/java/a8k/a8kproj/optanalyzer/PeakNameAssigner.java
-
2src/main/java/a8k/a8kproj/optanalyzer/context/OptAnalyzeContext.java
-
2src/main/java/a8k/a8kproj/opttype/A8kOptX.java
-
2src/main/java/a8k/a8kproj/opttype/PeakDivision.java
-
2src/main/java/a8k/a8kproj/opttype/PeakName.java
-
14src/main/java/a8k/service/app/appctrl/AppConsumablesScanService.java
-
4src/main/java/a8k/service/app/appctrl/mainflowctrl/action/PLATE_OPT_SCAN.java
-
2src/main/java/a8k/service/app/appctrl/mainflowctrl/action/SEQ5_PROCESS.java
-
6src/main/java/a8k/service/app/appdata/ProjCfgMgrService.java
-
4src/main/java/a8k/service/app/appdata/ReactionRecordMgrService.java
-
4src/main/java/a8k/service/app/appdata/UtilsProjectColorAllocer.java
-
2src/main/java/a8k/service/app/appstate/TubeStateMgrService.java
-
4src/main/java/a8k/service/app/appstate/type/SampleInfo.java
-
21src/main/java/a8k/service/app/appstate/type/TubeProcessContext.java
-
2src/main/java/a8k/service/app/devicectrl/ctrlservice/OptScanModuleCtrlService.java
-
4src/main/java/a8k/service/app/devicectrl/script/DeviceCtrlScripter.java
-
96src/main/java/a8k/service/app/devicectrl/test/OptAlgoTest.java
-
16src/main/java/a8k/service/dao/type/ProjInfoCard.java
-
4src/main/java/a8k/service/dao/type/ProjOptInfo.java
-
12src/main/java/a8k/service/dao/type/a8kidcard/A8kNormalFn.java
-
13src/main/java/a8k/service/dao/type/a8kidcard/A8kPiecewiseFn.java
-
13src/main/java/a8k/service/dao/type/a8kidcard/A8kResultBuilderFn.java
-
2src/main/java/a8k/service/test/MainflowCtrlTestService.java
-
2src/main/java/a8k/service/test/TestStateMgrService.java
-
4src/main/java/a8k/service/test/VirtualDeviceSimulationTest.java
-
53src/main/java/a8k/test/TestOptAnalyzer.java
-
5src/main/java/a8k/type/ReactionResult.java
-
14src/main/java/a8k/utils/ProjInfoContext.java
-
20src/main/java/a8k/utils/ProjProcessContextUtils.java
-
6src/main/java/a8k/utils/ZObjectUtils.java
@ -0,0 +1,25 @@ |
|||
package a8k.a8kproj.fakeoptpeak; |
|||
|
|||
import a8k.a8kproj.optalgo.type.A8kOptPeak; |
|||
import a8k.a8kproj.optalgo.type.A8kOptPeaks; |
|||
import a8k.a8kproj.optalgo.type.PeakFindState; |
|||
import a8k.a8kproj.optanalyzer.PeakNameAssigner; |
|||
|
|||
public class FakeOptPeakFactory { |
|||
|
|||
public static A8kOptPeaks build(Integer projId, Integer peakNameRefNum, Double area) { |
|||
A8kOptPeaks a8kOptPeaks = new A8kOptPeaks(); |
|||
A8kOptPeak a8kOptPeak = new A8kOptPeak(); |
|||
a8kOptPeak.area = area; |
|||
a8kOptPeak.state = PeakFindState.FIND_PEAK; |
|||
|
|||
a8kOptPeaks.P040 = a8kOptPeak.deepCopy(); |
|||
a8kOptPeaks.P080 = a8kOptPeak.deepCopy(); |
|||
a8kOptPeaks.P120 = a8kOptPeak.deepCopy(); |
|||
a8kOptPeaks.P160 = a8kOptPeak.deepCopy(); |
|||
a8kOptPeaks.P200 = a8kOptPeak.deepCopy(); |
|||
|
|||
PeakNameAssigner.assignPeakName(projId, peakNameRefNum, a8kOptPeaks); |
|||
return a8kOptPeaks; |
|||
} |
|||
} |
@ -1,4 +1,4 @@ |
|||
package a8k.service.test.fakeproj; |
|||
package a8k.a8kproj.fakeproj; |
|||
|
|||
|
|||
import a8k.service.dao.type.a8kidcard.zenum.A8kReactionFlowType; |
@ -1,4 +1,4 @@ |
|||
package a8k.service.test.fakeproj; |
|||
package a8k.a8kproj.fakeproj; |
|||
|
|||
|
|||
import a8k.service.dao.type.a8kidcard.zenum.A8kReactionFlowType; |
@ -1,4 +1,4 @@ |
|||
package a8k.service.test.fakeproj; |
|||
package a8k.a8kproj.fakeproj; |
|||
|
|||
|
|||
import a8k.service.dao.type.a8kidcard.zenum.A8kReactionFlowType; |
@ -1,4 +1,4 @@ |
|||
package a8k.service.test.fakeproj; |
|||
package a8k.a8kproj.fakeproj; |
|||
|
|||
|
|||
import a8k.service.dao.type.a8kidcard.zenum.A8kReactionFlowType; |
@ -1,4 +1,4 @@ |
|||
package a8k.service.test.fakeproj; |
|||
package a8k.a8kproj.fakeproj; |
|||
|
|||
|
|||
import a8k.service.dao.type.a8kidcard.zenum.A8kReactionFlowType; |
@ -1,4 +1,4 @@ |
|||
package a8k.service.test.fakeproj; |
|||
package a8k.a8kproj.fakeproj; |
|||
|
|||
|
|||
import a8k.service.dao.type.a8kidcard.zenum.A8kReactionFlowType; |
@ -1,4 +1,4 @@ |
|||
package a8k.service.test.fakeproj; |
|||
package a8k.a8kproj.fakeproj; |
|||
|
|||
|
|||
import a8k.service.dao.type.a8kidcard.zenum.A8kReactionFlowType; |
@ -0,0 +1,216 @@ |
|||
package a8k.a8kproj.fakeprojcontext; |
|||
|
|||
import a8k.a8kproj.opttype.A8kOptX; |
|||
import a8k.service.app.appdata.UtilsProjectColorAllocer; |
|||
import a8k.service.dao.type.ProjInfoCard; |
|||
import a8k.service.dao.type.ProjOptInfo; |
|||
import a8k.service.dao.type.ProjectInfo; |
|||
import a8k.service.dao.type.a8kidcard.A8kNormalFn; |
|||
import a8k.service.dao.type.a8kidcard.A8kOptFnFormula; |
|||
import a8k.service.dao.type.a8kidcard.A8kPiecewiseFn; |
|||
import a8k.service.dao.type.a8kidcard.A8kResultBuilderFn; |
|||
import a8k.service.dao.type.a8kidcard.zenum.A8kFnType; |
|||
import a8k.service.dao.type.a8kidcard.zenum.A8kOptType; |
|||
import a8k.service.dao.type.a8kidcard.zenum.A8kReactionFlowType; |
|||
import a8k.service.dao.type.a8kidcard.zenum.A8kResultUnit; |
|||
import a8k.utils.ProjInfoContext; |
|||
import a8k.utils.ZDateUtils; |
|||
import cn.hutool.core.util.ObjectUtil; |
|||
|
|||
import java.util.ArrayList; |
|||
import java.util.List; |
|||
|
|||
public class FakeProjInfoContextFactory { |
|||
|
|||
public static class FakeProjInfoContextCfg { |
|||
public String projName; |
|||
public String lotId; |
|||
public Integer projId; |
|||
public Integer updateChipVersion; |
|||
public Integer subProjNum; |
|||
public String projShortName; |
|||
public Integer reactionTemperature; |
|||
public String color; |
|||
public A8kReactionFlowType reactionFlowType; |
|||
public Integer wBloodSampleVolUl; |
|||
public Integer serumSampleVolUl; |
|||
public Integer shakeTimes; |
|||
public Integer bigBufferSampleUl; |
|||
public Integer mixLiquidAspirMixingCnt; |
|||
public Integer reactionPlateIncubationTimeMin; |
|||
public Integer reactionPlateDropletVolUl; |
|||
public Boolean expired; |
|||
|
|||
public A8kFnType fnType; |
|||
public A8kOptType optType; |
|||
|
|||
public Integer optScanPeakNum; |
|||
public Integer optPeakNameAssginRefPeakNum; |
|||
|
|||
} |
|||
|
|||
; |
|||
|
|||
|
|||
public static FakeProjInfoContextCfg createCfg(String projShortName, Integer projId, A8kReactionFlowType reactionType, Integer subProjNum) { |
|||
var val = new FakeProjInfoContextCfg(); |
|||
val.projName = String.format("%s%04d", projShortName, projId); |
|||
val.lotId = String.format("%s001234", projShortName, projId); |
|||
val.projId = projId; |
|||
val.updateChipVersion = 1; |
|||
val.subProjNum = subProjNum; |
|||
val.projShortName = projShortName; |
|||
val.reactionTemperature = 25; |
|||
val.color = UtilsProjectColorAllocer.getProjColor(projId); |
|||
val.reactionFlowType = reactionType; |
|||
val.wBloodSampleVolUl = 100; |
|||
val.serumSampleVolUl = 100; |
|||
val.shakeTimes = 2; |
|||
val.bigBufferSampleUl = 200; |
|||
val.mixLiquidAspirMixingCnt = 1; |
|||
val.reactionPlateIncubationTimeMin = 1; |
|||
val.reactionPlateDropletVolUl = 50; |
|||
val.expired = false; |
|||
val.fnType = A8kFnType.NormalFn; |
|||
val.optType = A8kOptType.FOPT; |
|||
if (projId == 1) { |
|||
val.optScanPeakNum = 2; |
|||
val.optPeakNameAssginRefPeakNum = 2; |
|||
} else { |
|||
val.optScanPeakNum = 5; |
|||
val.optPeakNameAssginRefPeakNum = 5; |
|||
} |
|||
|
|||
return val; |
|||
} |
|||
|
|||
|
|||
/** |
|||
* !!! WARNING 这个方法中的数值轻易不要修改,后续很多测试代码都是基于这个数值的 |
|||
*/ |
|||
private static A8kOptFnFormula buildTestFnFormula(A8kFnType fntyp) { |
|||
A8kOptFnFormula formula = new A8kOptFnFormula(); |
|||
|
|||
A8kNormalFn a8kNormalFn = new A8kNormalFn(); |
|||
a8kNormalFn.x = A8kOptX.R; |
|||
a8kNormalFn.xMin = 1.0; |
|||
a8kNormalFn.xMax = 100.0; |
|||
a8kNormalFn.A = 1.0; |
|||
a8kNormalFn.B = 1.0; |
|||
a8kNormalFn.C = 1.0; |
|||
a8kNormalFn.D = 1.0; |
|||
a8kNormalFn.lowLimit = 1.0; |
|||
a8kNormalFn.upLimit = 100.0; |
|||
|
|||
A8kPiecewiseFn a8kPiecewiseFn = new A8kPiecewiseFn(); |
|||
a8kPiecewiseFn.judeX = A8kOptX.R; |
|||
a8kPiecewiseFn.judeThres = 1.0; |
|||
a8kPiecewiseFn.lX = A8kOptX.R; |
|||
a8kPiecewiseFn.hX = A8kOptX.R; |
|||
a8kPiecewiseFn.xMin = 1.0; |
|||
a8kPiecewiseFn.xMax = 100.0; |
|||
a8kPiecewiseFn.A0 = 1.0; |
|||
a8kPiecewiseFn.B0 = 1.0; |
|||
a8kPiecewiseFn.C0 = 1.0; |
|||
a8kPiecewiseFn.D0 = 1.0; |
|||
a8kPiecewiseFn.A1 = 1.0; |
|||
a8kPiecewiseFn.B1 = 1.0; |
|||
a8kPiecewiseFn.C1 = 1.0; |
|||
a8kPiecewiseFn.D1 = 1.0; |
|||
a8kPiecewiseFn.lowLimit = 1.0; |
|||
a8kPiecewiseFn.upLimit = 100.0; |
|||
|
|||
A8kResultBuilderFn a8kResultBuilderFn = new A8kResultBuilderFn(); //结果生成函数 |
|||
|
|||
a8kResultBuilderFn.ret1Unit = A8kResultUnit.pgPml; |
|||
a8kResultBuilderFn.ret2Unit = A8kResultUnit.ngPml; |
|||
a8kResultBuilderFn.ret3Unit = A8kResultUnit.ugPml; |
|||
a8kResultBuilderFn.toUint2FnA = 2.0; |
|||
a8kResultBuilderFn.toUint2FnB = 0.1; |
|||
a8kResultBuilderFn.toUint3FnA = 3.0; |
|||
a8kResultBuilderFn.toUint3FnB = 0.1; |
|||
|
|||
|
|||
formula.fnType = fntyp; |
|||
//普通函数 |
|||
if (A8kFnType.NormalFn.equals(fntyp)) { |
|||
formula.serumNorFn = a8kNormalFn.clone(); // 血清 |
|||
formula.bloodNorFn = a8kNormalFn.clone(); // 血浆 |
|||
} |
|||
// 分段函数系数 |
|||
if (A8kFnType.PiecewiseFn.equals(fntyp)) { |
|||
formula.serumPiecewiseFn = a8kPiecewiseFn.clone(); // 血清 |
|||
formula.bloodPiecewiseFn = a8kPiecewiseFn.clone(); // 血浆 |
|||
} |
|||
//结果 |
|||
formula.resultBuilderFn = a8kResultBuilderFn.clone(); //结果生成函数 |
|||
return formula; |
|||
} |
|||
|
|||
|
|||
static public ProjInfoContext build(FakeProjInfoContextCfg cfg) { |
|||
|
|||
// |
|||
// ProjectInfo |
|||
// |
|||
ProjectInfo projInfo = new ProjectInfo(); |
|||
projInfo.projId = cfg.projId; |
|||
projInfo.projName = cfg.projName; |
|||
projInfo.projShortName = cfg.projShortName; |
|||
projInfo.subProjNum = cfg.subProjNum; |
|||
projInfo.reactionTemperature = cfg.reactionTemperature; |
|||
projInfo.color = cfg.color; |
|||
projInfo.reactionFlowType = cfg.reactionFlowType; |
|||
projInfo.wBloodSampleVolUl = cfg.wBloodSampleVolUl; |
|||
projInfo.serumSampleVolUl = cfg.serumSampleVolUl; |
|||
projInfo.shakeTimes = cfg.shakeTimes; |
|||
projInfo.bigBufferSampleUl = cfg.bigBufferSampleUl; |
|||
projInfo.reactionPlateIncubationTimeMin = cfg.reactionPlateIncubationTimeMin; |
|||
projInfo.reactionPlateDropletVolUl = cfg.reactionPlateDropletVolUl; |
|||
|
|||
// |
|||
// ProjInfoCard |
|||
// |
|||
ProjInfoCard projInfoCard = new ProjInfoCard(); |
|||
projInfoCard.projName = cfg.projName; |
|||
projInfoCard.lotId = cfg.lotId; |
|||
if (!cfg.expired) { |
|||
projInfoCard.expiryDate = ZDateUtils.nextDay(); |
|||
} else { |
|||
projInfoCard.expiryDate = ZDateUtils.theDayBeforeYesterday(); |
|||
} |
|||
projInfoCard.projId = cfg.projId; |
|||
projInfoCard.updateChipVersion = cfg.updateChipVersion; |
|||
projInfoCard.subProjNum = cfg.subProjNum; |
|||
|
|||
for (int i = 0; i < cfg.subProjNum; i++) { |
|||
var fnFormula = buildTestFnFormula(cfg.fnType); |
|||
projInfoCard.setProjFnFormual(i, fnFormula); |
|||
} |
|||
|
|||
// |
|||
// ProjOptInfo |
|||
// |
|||
List<ProjOptInfo> projOptInfoList = new ArrayList<>(); |
|||
for (int i = 0; i < cfg.subProjNum; i++) { |
|||
ProjOptInfo projOptInfo = new ProjOptInfo(); |
|||
projOptInfo.projId = cfg.projId; |
|||
projOptInfo.projName = cfg.projName; |
|||
projOptInfo.subProjIndex = i; |
|||
projOptInfo.subProjName = String.format("SUBPROJ_%d", i); |
|||
projOptInfo.subProjShortName = String.format("SP%d", i); |
|||
projOptInfo.optType = cfg.optType; |
|||
projOptInfo.optScanRange = 250; |
|||
projOptInfo.optScanPeakNum = cfg.optScanPeakNum; |
|||
projOptInfo.peakNameRefNum = cfg.optPeakNameAssginRefPeakNum; |
|||
projOptInfoList.add(projOptInfo); |
|||
} |
|||
|
|||
ProjInfoContext projInfoContext = new ProjInfoContext(); |
|||
projInfoContext.projInfo = projInfo; |
|||
projInfoContext.projInfoCard = projInfoCard; |
|||
projInfoContext.projOptInfoList = projOptInfoList; |
|||
return projInfoContext; |
|||
} |
|||
|
|||
} |
@ -1,241 +0,0 @@ |
|||
//package a8k.a8kproj.optalgo; |
|||
// |
|||
//import a8k.a8kproj.optalgo.type.LineProcessContext; |
|||
//import a8k.a8kproj.optalgo.type.OptAlgoResult; |
|||
//import a8k.a8kproj.optalgo.type.Peak; |
|||
//import a8k.a8kproj.optalgo.type.PeakFindState; |
|||
//import a8k.a8kproj.optalgo.utils.*; |
|||
//import lombok.extern.slf4j.Slf4j; |
|||
//import org.springframework.util.Assert; |
|||
// |
|||
//import java.util.ArrayList; |
|||
//import java.util.List; |
|||
// |
|||
//@Slf4j |
|||
//public class A8kOptAlgo { |
|||
// |
|||
// |
|||
// |
|||
// public static OptAlgoResult processOptData(Integer expectPeakNum, Integer searchStart, double[] data) { |
|||
// |
|||
// LineProcessContext cxt = new LineProcessContext(); |
|||
// |
|||
// //过采样 |
|||
// cxt.afSupperVal = SupperSampling.process(data, 5); |
|||
// //中值滤波 |
|||
// cxt.afSupperMedianVal = Filter.medianFiltering(cxt.afSupperVal, 25); |
|||
// |
|||
// //下采样到1000个点 |
|||
// cxt.raw1000 = SubSampling.process(cxt.afSupperMedianVal, 6); |
|||
// //生成1000个的平滑曲线 |
|||
// cxt.avg1000 = Filter.smooth(cxt.raw1000, 13); |
|||
// //生成1000个的斜率曲线 |
|||
// cxt.diff1000 = LeastSquare.calculatedSlopeCurve(cxt.avg1000, 13); |
|||
// //求数据的均值(巴迪泰A5000算法) |
|||
// cxt.avgLine = findAvgLine(cxt.raw1000); |
|||
// |
|||
// //在曲线开始的位置第10个到15点的斜率 |
|||
// cxt.baselineSlope = LeastSquare.linearLeastSquares(cxt.avg1000, 10 * 4, 5 * 4).slope; |
|||
// |
|||
// |
|||
// List<Peak> peaks = new ArrayList<>(); |
|||
// Peak peak = null; |
|||
// Peak lastPeak = null; |
|||
// for (int i = 0; i < expectPeakNum; i++) { |
|||
// if (i == 0) { |
|||
// peak = findPeak(cxt, searchStart * 4, 80 * 4); |
|||
// } else { |
|||
// peak = findPeak(cxt, lastPeak.peakEndPos, 80 * 4); |
|||
// } |
|||
// peak.off = i; |
|||
// peaks.add(peak); |
|||
// if (!peak.state.equals(PeakFindState.FIND_PEAK)) { |
|||
// break; |
|||
// } |
|||
// lastPeak = peak; |
|||
// } |
|||
// |
|||
// OptAlgoResult result = new OptAlgoResult(); |
|||
// result.resultData = SubSampling.process(cxt.avg1000, 4); |
|||
// result.ogiginData = data; |
|||
// result.peaks = peaks; |
|||
// return result; |
|||
// } |
|||
// |
|||
// /** |
|||
// * 求数据的均值(巴迪泰A5000算法) |
|||
// * @param inputRaw 输入数据 |
|||
// * @return 均值线 |
|||
// */ |
|||
// static double findAvgLine(double[] inputRaw) { |
|||
// double base_min = 500; |
|||
// double fsum = 0; |
|||
// int cnt = 0; |
|||
// |
|||
// int range = inputRaw.length; |
|||
// |
|||
// do { |
|||
// fsum = cnt = 0; |
|||
// for (int i = 1; i < range; i++) { |
|||
// if (inputRaw[i] < base_min) { |
|||
// fsum += inputRaw[i]; |
|||
// cnt++; |
|||
// } |
|||
// } |
|||
// |
|||
// base_min = base_min + 50; |
|||
// } while (cnt < range - 15 * inputRaw.length / 250); |
|||
// |
|||
// return fsum / cnt; |
|||
// } |
|||
// |
|||
// static Peak findPeak(LineProcessContext cxt, int searchStart, int peakWidth) { |
|||
// Peak peak = new Peak(); |
|||
// /* |
|||
// * @brief 查找峰的位置 |
|||
// * |
|||
// * 思路: |
|||
// * 搜索所有大于均值的点,当点满足,其数值大于附近一定数量的点时,认为是峰的位置 |
|||
// */ |
|||
// |
|||
// log.info("findpeak start:{} windth:{}", searchStart, peakWidth); |
|||
// |
|||
// // judge_win_size |
|||
// int judge_win_size = 2 * (cxt.avg1000.length / 250) + 1; |
|||
// |
|||
// int peakoff = findPeakOff(cxt, searchStart, peakWidth, judge_win_size); |
|||
// if (peakoff < 0) { |
|||
// peak.state = PeakFindState.NOT_FIND_PEAK; |
|||
// return peak; |
|||
// } |
|||
// peak.peakPos = peakoff; |
|||
// |
|||
// /* |
|||
// * @brief 查找峰的起始位置 |
|||
// * |
|||
// * 思路: |
|||
// * 从峰的位置开始,向前搜索,找到一个点,其值小于平均值。 |
|||
// * 然后继续向前搜索,找到一个点,斜率接近基线斜率。 |
|||
// * |
|||
// */ |
|||
// |
|||
// int peak_start_pos = findPeakKneePoint(cxt, peak.peakPos, -1, peakWidth / 2); |
|||
// int peak_end_pos = findPeakKneePoint(cxt, peak.peakPos, 1, peakWidth / 2); |
|||
// |
|||
// if (peak_start_pos < 0) { |
|||
// peak.state = PeakFindState.NOT_FIND_PEAK_START; |
|||
// return peak; |
|||
// } |
|||
// if (peak_end_pos < 0) { |
|||
// peak.state = PeakFindState.NOT_FIND_PEAK_END; |
|||
// return peak; |
|||
// } |
|||
// |
|||
// peak.peakStartPos = peak_start_pos; |
|||
// peak.peakEndPos = peak_end_pos; |
|||
// |
|||
// /* |
|||
// * @brief |
|||
// * 计算峰的面积 |
|||
// */ |
|||
// |
|||
// double peak_full_area = 0; |
|||
// for (int i = peak_start_pos; i <= peak_end_pos; i++) { |
|||
// peak_full_area += cxt.raw1000[i]; |
|||
// } |
|||
// |
|||
// double peak_base_line_area; |
|||
// peak_base_line_area = |
|||
// (cxt.raw1000[peak_start_pos] + cxt.raw1000[peak_end_pos]) * 0.5 * (peak_end_pos - peak_start_pos + 1); |
|||
// |
|||
// peak.peakFullArea = peak_full_area; |
|||
// peak.peakBaseLineArea = peak_base_line_area; |
|||
// peak.area = peak_full_area - peak_base_line_area; |
|||
// if (peak.area <= 0) |
|||
// peak.area = 0.0; |
|||
// peak.state = PeakFindState.FIND_PEAK; |
|||
// |
|||
// return peak; |
|||
// } |
|||
// |
|||
// static public int findPeakOff(LineProcessContext cxt, int start_off, int windos_size, int judge_win_size) { |
|||
// double maxv = 0; |
|||
// int peakoff = -1; |
|||
// boolean findmax = false; |
|||
// |
|||
// for (int index = 0; index < windos_size; index++) { |
|||
// int off = index + start_off; |
|||
// // 从窗口的一半大小开始判断 |
|||
// if (findmax && cxt.avg1000[off] <= cxt.avgLine) |
|||
// break; |
|||
// if (off < judge_win_size / 2) |
|||
// continue; |
|||
// // 查找的点要大于基线 |
|||
// if (cxt.avg1000[off] <= cxt.avgLine) |
|||
// continue; |
|||
// // 判断的 |
|||
// if ((off + judge_win_size / 2) > (cxt.avg1000.length - 1)) |
|||
// break; |
|||
// // 找到最大的峰值,这里判断用于去除一个波峰中的某个临时的小波峰 |
|||
// if (maxv > cxt.avg1000[off]) |
|||
// continue; |
|||
// |
|||
// /* |
|||
// * @brief 检查当前位置的点,是否是附近最大的点 |
|||
// */ |
|||
// if (BasicAlgo.isMaxvalInWindows(cxt.avg1000, off, judge_win_size)) { |
|||
// findmax = true; |
|||
// maxv = cxt.avg1000[off]; |
|||
// peakoff = off; |
|||
// } |
|||
// } |
|||
// return peakoff; |
|||
// } |
|||
// |
|||
// static int findPeakKneePoint(LineProcessContext cxt, |
|||
// int search_start, // |
|||
// int search_direction, // |
|||
// int search_windows) { |
|||
// /* |
|||
// * @brief |
|||
// * 通过波峰的位置查找波峰的起始位置 |
|||
// * |
|||
// * 逻辑: |
|||
// * 1. 从波峰的位置开始,向前搜索,找到一个点,其值小于平均值。 |
|||
// * 2. 然后继续向前搜索,找到一个点,斜率接近基线斜率。 |
|||
// * |
|||
// */ |
|||
// |
|||
// int off = -1; |
|||
// log.info("find peakend top_pos:{} direction:{} windows:{}", search_start, search_direction, search_windows); |
|||
// |
|||
// // |
|||
// Assert.isTrue(search_windows > 0, "search_windows <= 0"); |
|||
// Assert.isTrue(search_direction == 1 || search_direction == -1, "search_direction != 1 && search_direction != -1"); |
|||
// // |
|||
// int index_dval = search_direction >= 0 ? 1 : -1; |
|||
// int search_end = search_start + search_direction * search_windows; |
|||
// |
|||
// Assert.isTrue(search_end >= 0, "search_end < 0"); |
|||
// Assert.isTrue(cxt.avg1000.length > search_end, "cxt.avg1000.size() <= search_start"); |
|||
// |
|||
// for (int i = search_start; i != search_end; i += index_dval) { |
|||
// double now = cxt.avg1000[i]; |
|||
// if (now >= cxt.avgLine) |
|||
// continue; |
|||
// |
|||
// if (search_direction == 1) { |
|||
// if (BasicAlgo.feq(cxt.diff1000[i], cxt.baselineSlope, 0.3) || cxt.diff1000[i] >= cxt.baselineSlope) { |
|||
// off = i; |
|||
// break; |
|||
// } |
|||
// } else { |
|||
// if (BasicAlgo.feq(cxt.diff1000[i], cxt.baselineSlope, 0.3) || cxt.diff1000[i] <= cxt.baselineSlope) { |
|||
// off = i; |
|||
// break; |
|||
// } |
|||
// } |
|||
// } |
|||
// return off; |
|||
// } |
|||
//} |
@ -1,10 +0,0 @@ |
|||
package a8k.a8kproj.optalgo.type; |
|||
|
|||
import a8k.opttype.PeakName; |
|||
|
|||
import java.util.List; |
|||
|
|||
public class A8kOptPeakArea { |
|||
public PeakName peakName; |
|||
public Double area; |
|||
} |
@ -1,14 +0,0 @@ |
|||
package a8k.a8kproj.optalgo.type; |
|||
|
|||
import a8k.opttype.PeakName; |
|||
|
|||
import java.util.ArrayList; |
|||
import java.util.List; |
|||
|
|||
public class A8kOptPeakAreas { |
|||
List<A8kOptPeakArea> areas = new ArrayList<>(); |
|||
|
|||
// public Double getArea(PeakName peakName) { |
|||
// } |
|||
|
|||
} |
@ -1,4 +1,4 @@ |
|||
package a8k.opttype; |
|||
package a8k.a8kproj.opttype; |
|||
|
|||
public enum A8kOptX { |
|||
USUPPORT, |
@ -1,4 +1,4 @@ |
|||
package a8k.opttype; |
|||
package a8k.a8kproj.opttype; |
|||
|
|||
public enum PeakDivision { |
|||
R(PeakName.T, PeakName.C), //T/C |
@ -1,4 +1,4 @@ |
|||
package a8k.opttype; |
|||
package a8k.a8kproj.opttype; |
|||
|
|||
public enum PeakName { |
|||
T4, |
@ -1,2 +0,0 @@ |
|||
package a8k.service.app.appstate; |
|||
|
@ -1,21 +0,0 @@ |
|||
package a8k.service.app.appstate.type; |
|||
|
|||
import a8k.type.type.BloodType; |
|||
|
|||
import java.util.ArrayList; |
|||
import java.util.List; |
|||
|
|||
//public class TubeProcessContext { |
|||
// public String sampleid; //样本ID-系统生成-唯一标识一个样本 |
|||
// |
|||
// public Boolean isHighTube = false; |
|||
// public Boolean isEmergency = false; |
|||
// |
|||
// public BloodType bloodType = BloodType.WHOLE_BLOOD; //血液类型 |
|||
// public String sampleBarcode = ""; //用于请求用户信息的条码ID |
|||
// public String userid = ""; //用户输入的样本ID,不做逻辑,只做展示 |
|||
// public List<Integer> projId = new ArrayList<>(); //项目代码 |
|||
// |
|||
// public List<ProjProcessContext> projProcessContext; |
|||
// |
|||
//} |
@ -1,96 +0,0 @@ |
|||
package a8k.service.app.devicectrl.test; |
|||
|
|||
|
|||
import a8k.a8kproj.optalgo.type.A8kOptPeakAreas; |
|||
import a8k.a8kproj.optalgo.type.A8kOptPeaks; |
|||
import a8k.service.dao.type.a8kidcard.A8kOptFnFormula; |
|||
import a8k.type.ReactionResult; |
|||
import a8k.type.type.BloodType; |
|||
|
|||
public class OptAlgoTest { |
|||
//输入 |
|||
// 峰面积,峰面积,峰面积,峰面积,峰面积 |
|||
// ID卡 |
|||
// 虚拟ID卡 |
|||
// |
|||
|
|||
//输出 |
|||
// 峰比例数值 |
|||
// 计算结果1,单位1,2,3 |
|||
// 计算结果2,单位1,2,3 |
|||
// 计算结果3,单位1,2,3 |
|||
|
|||
|
|||
// void computeResult(){} |
|||
|
|||
// |
|||
// 方法的设备 |
|||
// 光学配置+峰集合 |
|||
|
|||
A8kOptPeaks peaks; |
|||
|
|||
// ReactionResult testComputeReactionResult() { |
|||
// } |
|||
|
|||
|
|||
// static private ReactionResult doNormalFn(A8kIdCardFn idCardFn, int subProjIndex) throws A8kOptProcessException { |
|||
// A8kFnFormula fn = switch (optcxt.bloodType) { |
|||
// case WHOLE_BLOOD -> idCardFn.norSerumFn; |
|||
// case SERUM_OR_PLASMA -> idCardFn.norBloodFn; |
|||
// }; |
|||
// OptChecker.checkNotNull(optcxt, fn, "norSerumFn == null"); |
|||
// OptChecker.checkNotNull(optcxt, idCardFn, "idCardFn == null"); |
|||
// OptChecker.checkNotNull(optcxt, optcfg, "optcfg == null"); |
|||
// |
|||
// A8kOptPeaks tpeaks = null, fpeaks = null; |
|||
// if (optcxt.foptResult != null) { |
|||
// fpeaks = optcxt.foptResult.peaks; |
|||
// } |
|||
// if (optcxt.toptResult != null) { |
|||
// tpeaks = optcxt.toptResult.peaks; |
|||
// } |
|||
// |
|||
// |
|||
// Double X = A8kOptXGetter.getX(idCardFn.norFnX, optcfg, fpeaks, tpeaks); |
|||
// OptChecker.checkX(X, idCardFn.norFnXMin, idCardFn.norFnXMax); |
|||
// |
|||
// Double result1 = fn.A * X * X + fn.B * X + fn.C; |
|||
// OptChecker.checkResult1(result1, fn.lowLimit, fn.upLimit); |
|||
// |
|||
// return buildResult(optcxt, subProjIndex, result1); |
|||
// } |
|||
// |
|||
// static private ReactionResult doPwFn(A8kIdCardFn idCardFn, int subProjIndex) throws A8kOptProcessException { |
|||
// |
|||
// A8kPiecewiseFnFormula piecfn = switch (optcxt.bloodType) { |
|||
// case WHOLE_BLOOD -> fnparam.bloodPiecewiseFn; |
|||
// case SERUM_OR_PLASMA -> fnparam.serumPiecewiseFn; |
|||
// }; |
|||
// |
|||
// Double pwFnJudeX = A8kOptXGetter.getX(fnparam.pwFnJudeX, optcfg, optcxt.foptResult.peaks, optcxt.toptResult.peaks); |
|||
// Double X = null; |
|||
// Double result1 = null; |
|||
// if (pwFnJudeX < fnparam.pwFnJudeThres) { |
|||
// X = A8kOptXGetter.getX(fnparam.pwFnLCX, optcfg, optcxt.foptResult.peaks, optcxt.toptResult.peaks); |
|||
// result1 = piecfn.A0 * X * X + piecfn.B0 * X + piecfn.C0; |
|||
// } else { |
|||
// X = A8kOptXGetter.getX(fnparam.pwFnHCX, optcfg, optcxt.foptResult.peaks, optcxt.toptResult.peaks); |
|||
// result1 = piecfn.A1 * X * X + piecfn.B1 * X + piecfn.C1; |
|||
// } |
|||
// OptChecker.checkX(X, fnparam.pwFnXMin, fnparam.pwFnXMax); |
|||
// OptChecker.checkResult1(result1, piecfn.lowLimit, piecfn.upLimit); |
|||
// |
|||
// return buildResult(optcxt, subProjIndex, result1); |
|||
// } |
|||
|
|||
|
|||
ReactionResult analyzeOptPeaks(A8kOptFnFormula projOptConfig, BloodType bloodType, A8kOptPeakAreas areas) { |
|||
|
|||
|
|||
return null; |
|||
} |
|||
// 计算结果1 |
|||
// 计算结果2 |
|||
// 计算结果3 |
|||
|
|||
} |
@ -0,0 +1,53 @@ |
|||
package a8k.test; |
|||
|
|||
import a8k.a8kproj.A8kOptScanResultAnalyzer; |
|||
import a8k.a8kproj.fakeoptpeak.FakeOptPeakFactory; |
|||
import a8k.a8kproj.fakeprojcontext.FakeProjInfoContextFactory; |
|||
import a8k.a8kproj.optalgo.type.OptScanResult; |
|||
import a8k.service.app.appstate.type.SampleInfo; |
|||
import a8k.a8kproj.fakeproj.FAKE_PROJ_01_FLOW1; |
|||
import a8k.service.dao.type.a8kidcard.zenum.A8kReactionFlowType; |
|||
import a8k.type.ReactionResult; |
|||
import a8k.utils.ProjInfoContext; |
|||
import jakarta.annotation.PostConstruct; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.stereotype.Component; |
|||
|
|||
@Component |
|||
@Slf4j |
|||
public class TestOptAnalyzer { |
|||
|
|||
@FunctionalInterface |
|||
public interface TEST { |
|||
Boolean test(); |
|||
} |
|||
|
|||
|
|||
Boolean TEST_OPT_RESULT_PARSE_01() { |
|||
var cfg = FakeProjInfoContextFactory.createCfg("TEST_PROJ", 2, A8kReactionFlowType.FlowType1, 3); |
|||
|
|||
ProjInfoContext projInfoContext = FakeProjInfoContextFactory.build(cfg); |
|||
var peaks = FakeOptPeakFactory.build(cfg.projId, 4, 100.0); |
|||
SampleInfo sampleInfo = new SampleInfo(); |
|||
sampleInfo.projId = cfg.projId; |
|||
|
|||
ReactionResult result = A8kOptScanResultAnalyzer.analyze(sampleInfo, projInfoContext, 0, peaks); |
|||
log.info("result: {}", result); |
|||
return true; |
|||
} |
|||
|
|||
void test(String mark, TEST test) { |
|||
Boolean suc = test.test(); |
|||
if (suc) { |
|||
log.info("TEST: {} -> SUCCESS", mark); |
|||
} else { |
|||
log.error("TEST: {} -> FAILED", mark); |
|||
} |
|||
|
|||
} |
|||
|
|||
@PostConstruct |
|||
void init() { |
|||
// test("TEST_OPT_RESULT_PARSE_01", this::TEST_OPT_RESULT_PARSE_01); |
|||
} |
|||
} |
@ -0,0 +1,6 @@ |
|||
package a8k.utils; |
|||
|
|||
public class ZObjectUtils { |
|||
|
|||
|
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue