13 changed files with 498 additions and 250 deletions
-
44README.md
-
295src/main/java/a8k/optalgo/OptAlgo.java
-
6src/main/java/a8k/optalgo/type/LinearResult.java
-
6src/main/java/a8k/optalgo/type/LinearResultSeq.java
-
14src/main/java/a8k/optalgo/type/OptAlgoResult.java
-
5src/main/java/a8k/optalgo/type/OptCfg.java
-
4src/main/java/a8k/optalgo/type/OptProcessContext.java
-
2src/main/java/a8k/optalgo/type/Peak.java
-
1src/main/java/a8k/service/appdata/AppReactionResultMgrService.java
-
105src/main/java/a8k/service/appdata/AppSampleRecordMgrService.java
-
2src/main/java/a8k/service/appsetting/AppSettingsMgr.java
@ -1,7 +1,302 @@ |
|||||
package a8k.optalgo; |
package a8k.optalgo; |
||||
|
|
||||
|
import a8k.optalgo.type.LinearResult; |
||||
|
import a8k.optalgo.type.OptAlgoResult; |
||||
|
|
||||
public class OptAlgo { |
public class OptAlgo { |
||||
|
|
||||
|
|
||||
|
OptAlgoResult processOptData(Integer expectPeakNum, Float[] data) { |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
Boolean feq(double a, double b, double epsilon) { |
||||
|
double dv = a - b; |
||||
|
if (dv < 0) |
||||
|
dv = -dv; |
||||
|
return dv <= epsilon; |
||||
|
} |
||||
|
|
||||
|
Float[] super_sampling(Float[] inputRaw, Integer nInputLength, Integer nUpSampleRate) { |
||||
|
/* |
||||
|
* @brief |
||||
|
* |
||||
|
*/ |
||||
|
int nOutputLength = nInputLength * nUpSampleRate; |
||||
|
Float[] upSamplingRaw = new Float[nOutputLength]; |
||||
|
|
||||
|
for (int si = 0, di = 0; si < nInputLength - 1; di++) { |
||||
|
float a = upSamplingRaw[di * nUpSampleRate] = (float) inputRaw[si]; |
||||
|
float b = upSamplingRaw[(di + 1) * nUpSampleRate] = (float) inputRaw[++si]; |
||||
|
|
||||
|
float nSlope = (b - a) / nUpSampleRate; |
||||
|
|
||||
|
for (int i = 0; i < nUpSampleRate - 1; i++) { |
||||
|
int baseIndex = (di * nUpSampleRate) + i; |
||||
|
upSamplingRaw[baseIndex + 1] = upSamplingRaw[baseIndex] + nSlope; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return upSamplingRaw; |
||||
|
} |
||||
|
|
||||
|
Float[] sub_sampling(Float[] inputRaw, int nSubSampleRate) { |
||||
|
int nSum = 0; |
||||
|
float fAvg = 0; |
||||
|
int subIndex = 0; |
||||
|
int nOutputLength = inputRaw.length / nSubSampleRate; |
||||
|
|
||||
|
Float[] subSampledRaw = new Float[nOutputLength]; |
||||
|
|
||||
|
for (int index = 0; index < inputRaw.length; index++) { |
||||
|
if (index % nSubSampleRate == 0 && index > 0) { |
||||
|
fAvg = nSum * 1.0f / nSubSampleRate; |
||||
|
if (subIndex < subSampledRaw.length) { |
||||
|
subSampledRaw[subIndex++] = fAvg; |
||||
|
} else { |
||||
|
int empty = 0; |
||||
|
} |
||||
|
nSum = 0; |
||||
|
} |
||||
|
nSum += inputRaw[index]; |
||||
|
} |
||||
|
subSampledRaw[subSampledRaw.length - 1] = subSampledRaw[subSampledRaw.length - 2]; |
||||
|
return subSampledRaw; |
||||
|
} |
||||
|
|
||||
|
Float[] smooth_windows(Float[] inputRaw, int windows_size) { |
||||
|
Float[] smoothRaw = new Float[inputRaw.length]; |
||||
|
int windows_size_half = (windows_size - 1) / 2; |
||||
|
|
||||
|
for (int index = windows_size_half; index < inputRaw.length - windows_size_half; index++) { |
||||
|
float sum = 0; |
||||
|
for (int i = index - windows_size_half; i <= index + windows_size_half; i++) { |
||||
|
sum += inputRaw[i]; |
||||
|
} |
||||
|
smoothRaw[index] = sum / windows_size; |
||||
|
} |
||||
|
|
||||
|
for (int i = 0; i < windows_size_half; i++) { |
||||
|
smoothRaw[i] = smoothRaw[windows_size_half]; |
||||
|
} |
||||
|
|
||||
|
for (int i = inputRaw.length - windows_size_half; i < inputRaw.length; i++) { |
||||
|
smoothRaw[i] = smoothRaw[inputRaw.length - windows_size_half - 1]; |
||||
|
} |
||||
|
|
||||
|
return smoothRaw; |
||||
|
} |
||||
|
|
||||
|
Float[] median_filtering(Float[] inputRaw, int windows_size) { |
||||
|
Float[] medianRaw = new Float[inputRaw.length]; |
||||
|
Float[] windows = new Float[windows_size]; |
||||
|
|
||||
|
int windows_size_half = (windows_size - 1) / 2; |
||||
|
|
||||
|
for (int index = windows_size_half; index < inputRaw.length - windows_size_half; index++) { |
||||
|
for (int i = 0; i < windows_size; i++) { |
||||
|
windows[i] = inputRaw[index + i - windows_size_half]; |
||||
|
} |
||||
|
sort_vector(windows); // 从小到大顺序排序 |
||||
|
medianRaw[index] = windows[windows_size_half + 1]; |
||||
|
} |
||||
|
|
||||
|
for (int i = 0; i < windows_size_half; i++) { |
||||
|
medianRaw[i] = medianRaw[windows_size_half]; |
||||
|
} |
||||
|
|
||||
|
for (int i = inputRaw.length - windows_size_half; i < inputRaw.length; i++) { |
||||
|
medianRaw[i] = medianRaw[inputRaw.length - windows_size_half - 1]; |
||||
|
} |
||||
|
|
||||
|
return medianRaw; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @brief 求数据的均值 |
||||
|
* |
||||
|
* @param inputRaw |
||||
|
* @return float |
||||
|
*/ |
||||
|
float find_avg_line(Float[] inputRaw) { |
||||
|
float base_min = 500; |
||||
|
float 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); |
||||
|
|
||||
|
float fbase = fsum / cnt; |
||||
|
return fbase; |
||||
|
} |
||||
|
|
||||
|
Float[] differentiate(Float[] inputRaw) { |
||||
|
/** |
||||
|
* @brief |
||||
|
* 巴迪泰源码,对原始数据添加了一些微小的值,原因未知 |
||||
|
*/ |
||||
|
for (int i = 0; i <= inputRaw.length - 8; i += 8) { |
||||
|
inputRaw[i + 1] = inputRaw[i + 1] + 0.001f; |
||||
|
inputRaw[i + 2] = inputRaw[i + 2] + 0.002f; |
||||
|
inputRaw[i + 3] = inputRaw[i + 3] + 0.003f; |
||||
|
inputRaw[i + 4] = inputRaw[i + 4] + 0.004f; |
||||
|
inputRaw[i + 5] = inputRaw[i + 5] + 0.005f; |
||||
|
inputRaw[i + 6] = inputRaw[i + 6] + 0.004f; |
||||
|
inputRaw[i + 7] = inputRaw[i + 7] + 0.003f; |
||||
|
inputRaw[i + 8] = inputRaw[i + 8] + 0.002f; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @brief |
||||
|
* @Warning: 此处求导和巴迪泰的存在差异, |
||||
|
* 巴迪泰的是当前数值减去下一个数值, |
||||
|
* 而此处是当前数值减去上一个数值 |
||||
|
*/ |
||||
|
|
||||
|
Float[] differentiateRaw = new Float[inputRaw.length]; |
||||
|
for (int i = 1; i < differentiateRaw.length; i++) { |
||||
|
differentiateRaw[i] = inputRaw[i] - inputRaw[i - 1]; |
||||
|
} |
||||
|
differentiateRaw[0] = differentiateRaw[1]; |
||||
|
return differentiateRaw; |
||||
|
} |
||||
|
|
||||
|
Float[] least_square_method_differentiate(Float[] inputRaw, int windows_size) { |
||||
|
assert (windows_size > 0); |
||||
|
assert (windows_size % 2 == 1); |
||||
|
|
||||
|
|
||||
|
Float[] differentiateRaw = new Float[inputRaw.length]; |
||||
|
Float[] windowsRaw = new Float[windows_size]; |
||||
|
|
||||
|
int windows_size_half = (windows_size - 1) / 2; |
||||
|
|
||||
|
for (int index = windows_size_half; index < inputRaw.length - windows_size_half; index++) { |
||||
|
windowsRaw = getwindowspoint(inputRaw, index, windows_size); |
||||
|
float intercept = 0; |
||||
|
// linear_least_squares(windowsRaw, windows_size, differentiateRaw[index], intercept); |
||||
|
} |
||||
|
|
||||
|
for (int i = 0; i < windows_size_half; i++) { |
||||
|
differentiateRaw[i] = differentiateRaw[windows_size_half]; |
||||
|
} |
||||
|
|
||||
|
for (int i = inputRaw.length - windows_size_half; i < inputRaw.length; i++) { |
||||
|
differentiateRaw[i] = differentiateRaw[inputRaw.length - windows_size_half - 1]; |
||||
|
} |
||||
|
return differentiateRaw; |
||||
|
} |
||||
|
|
||||
|
Boolean is_maxval_in_windows(Float[] data, int pos, int windows_size) { |
||||
|
assert (windows_size > 0); |
||||
|
assert (windows_size % 2 == 1); |
||||
|
|
||||
|
boolean ret = true; |
||||
|
int startPos = pos - windows_size / 2; |
||||
|
Float val = data[pos]; |
||||
|
|
||||
|
for (int i = 0; i < windows_size; i++) { |
||||
|
if (startPos + i == pos) |
||||
|
continue; |
||||
|
|
||||
|
if (data[startPos + i] > val) { |
||||
|
ret = false; |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
LinearResult linear_least_squares(double[] x, double[] y) { |
||||
|
LinearResult result = new LinearResult(); |
||||
|
int n = x.length; |
||||
|
double sumX = 0.0, sumY = 0.0, sumXY = 0.0, sumXX = 0.0; |
||||
|
for (int i = 0; i < n; ++i) { |
||||
|
sumX += x[i]; |
||||
|
sumY += y[i]; |
||||
|
sumXY += x[i] * y[i]; |
||||
|
sumXX += x[i] * x[i]; |
||||
|
} |
||||
|
double xMean = sumX / n; |
||||
|
double yMean = sumY / n; |
||||
|
|
||||
|
assert (!feq((sumXX - n * xMean * xMean), 0, 0.0001)); |
||||
|
result.slope = (sumXY - n * xMean * yMean) / (sumXX - n * xMean * xMean); |
||||
|
result.intercept = yMean - result.slope * xMean; |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
// |
||||
|
LinearResult linear_least_squares(double[] y, int size) { |
||||
|
double[] xpoint = new double[size]; |
||||
|
double[] ypoint = new double[size]; |
||||
|
|
||||
|
for (int i = 0; i < size; i++) { |
||||
|
xpoint[i] = i; |
||||
|
ypoint[i] = y[i]; |
||||
|
} |
||||
|
return linear_least_squares(xpoint, ypoint); |
||||
|
} |
||||
|
|
||||
|
LinearResult linear_least_squares_muti_windos(int[] startx, int windows, float[] y) { |
||||
|
double[] xpoint = new double[windows * startx.length]; |
||||
|
double[] ypoint = new double[windows * startx.length]; |
||||
|
|
||||
|
int j = 0; |
||||
|
for (int xstart : startx) { |
||||
|
for (int xindex = xstart; xindex < (xstart + windows); xindex++) { |
||||
|
xpoint[j] = xindex; |
||||
|
ypoint[j] = y[xindex]; |
||||
|
j++; |
||||
|
} |
||||
|
} |
||||
|
return linear_least_squares(xpoint, ypoint); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
float get_avg_in_windows(double[] src, int off, int windows) { |
||||
|
float sum = 0; |
||||
|
assert (windows % 2 == 1); |
||||
|
for (int i = off - windows / 2; i <= off + windows / 2; i++) { |
||||
|
sum += (float) src[i]; |
||||
|
} |
||||
|
return sum / windows; |
||||
|
} |
||||
|
|
||||
|
void sort_vector(Float[] src) { |
||||
|
// 实现冒泡排序 |
||||
|
for (int i = 0; i < src.length; i++) { |
||||
|
for (int j = 0; j < src.length - i - 1; j++) { |
||||
|
if (src[j] > src[j + 1]) { |
||||
|
float temp = src[j]; |
||||
|
src[j] = src[j + 1]; |
||||
|
src[j + 1] = temp; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
double[] getwindowspoint(double[] src, int off, int windows) { |
||||
|
double[] ret = new double[windows]; |
||||
|
int retindex = 0; |
||||
|
for (int i = off - windows / 2; i <= off + windows / 2; i++) { |
||||
|
ret[retindex] = src[i]; |
||||
|
retindex++; |
||||
|
} |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
|
||||
} |
} |
@ -0,0 +1,6 @@ |
|||||
|
package a8k.optalgo.type; |
||||
|
|
||||
|
public class LinearResult { |
||||
|
public double slope; |
||||
|
public double intercept; |
||||
|
} |
@ -0,0 +1,6 @@ |
|||||
|
package a8k.optalgo.type; |
||||
|
|
||||
|
public class LinearResultSeq { |
||||
|
public Float[] slope; |
||||
|
public Float intercept; |
||||
|
} |
@ -1,14 +1,12 @@ |
|||||
package a8k.optalgo.type; |
package a8k.optalgo.type; |
||||
|
|
||||
|
import java.util.ArrayList; |
||||
import java.util.List; |
import java.util.List; |
||||
|
|
||||
public class OptAlgoResult { |
public class OptAlgoResult { |
||||
// vector<float> ogigin_val; // 1200 |
|
||||
// vector<float> supper_val; // 原始数据,线性填充,1200*5=6000 |
|
||||
// vector<float> supper_median_val; // supper_val 窗口平滑滤波,6000 |
|
||||
// vector<float> supper_smooth_sub_val; // supper_smooth_val 均值压缩,6000/6=1000 |
|
||||
public Float[] ogiginVal; |
|
||||
public Float[] supperVal; |
|
||||
public Float[] supperMedianVal; |
|
||||
public Float[] supperSmoothSubVal; |
|
||||
|
|
||||
|
public Float[] ogigin_val; // 1200 POINT |
||||
|
public Float[] result_val; // 250 POINT |
||||
|
|
||||
|
public List<Peak> peaks = new ArrayList<>(); |
||||
} |
} |
@ -0,0 +1,5 @@ |
|||||
|
package a8k.optalgo.type; |
||||
|
|
||||
|
public class OptCfg { |
||||
|
public Integer peakNum; |
||||
|
} |
@ -0,0 +1,4 @@ |
|||||
|
package a8k.optalgo.type; |
||||
|
|
||||
|
public class OptProcessContext { |
||||
|
} |
@ -1,6 +1,6 @@ |
|||||
package a8k.optalgo.type; |
package a8k.optalgo.type; |
||||
|
|
||||
public class PeakInfo { |
|
||||
|
public class Peak { |
||||
public Boolean findPeak; |
public Boolean findPeak; |
||||
public Float peakFullArea; |
public Float peakFullArea; |
||||
public Float peakBaseLineArea; |
public Float peakBaseLineArea; |
@ -1,105 +0,0 @@ |
|||||
package a8k.service.appdata; |
|
||||
|
|
||||
import a8k.controler.extapi.pagecontrol.ExtApiTabConfig; |
|
||||
import a8k.controler.extapi.utils.ExtApiFn; |
|
||||
import a8k.controler.extapi.utils.ExtApiTab; |
|
||||
import a8k.dbservice.SampleRecordDBService; |
|
||||
import a8k.dbservice.type.SampleRecord; |
|
||||
import a8k.service.appstate.type.Tube; |
|
||||
import a8k.service.appstate.type.state.TubeState; |
|
||||
import a8k.type.type.BloodType; |
|
||||
import jakarta.annotation.PostConstruct; |
|
||||
import jakarta.annotation.Resource; |
|
||||
import org.springframework.stereotype.Component; |
|
||||
|
|
||||
import java.text.SimpleDateFormat; |
|
||||
import java.util.Date; |
|
||||
import java.util.List; |
|
||||
|
|
||||
@Component |
|
||||
@ExtApiTab(cfg = ExtApiTabConfig.AppSampleMgrService) |
|
||||
public class AppSampleRecordMgrService { |
|
||||
|
|
||||
@Resource |
|
||||
SampleRecordDBService sampleRecordDBService; |
|
||||
|
|
||||
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
|
||||
|
|
||||
@PostConstruct |
|
||||
public void init() { |
|
||||
} |
|
||||
|
|
||||
// String generateSampleId(Date date, Integer tubePos) { |
|
||||
// String sampleid = ""; |
|
||||
// SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd_HHmmss"); |
|
||||
// sampleid = String.format("%s_%s", sdf.format(date), tubePos + 1); |
|
||||
// if (tubePos == -1) { |
|
||||
// sampleid = String.format("%s_%s", sdf.format(date), "E"); |
|
||||
// } |
|
||||
// return sampleid; |
|
||||
// } |
|
||||
// |
|
||||
// @ExtApiFn(name = "addSampleRecordExtApi") |
|
||||
// public SampleRecord addSampleRecordExtApi(Integer tuebPos, BloodType bloodType, String sampleBarcode, String userid, String projIndex) { |
|
||||
// return addSampleRecord(new Date(), tuebPos, bloodType, sampleBarcode, userid, projIndex); |
|
||||
// } |
|
||||
// |
|
||||
// @ExtApiFn(name = "getAllSampleRecordsExtApi") |
|
||||
// public List<SampleRecord> getAllSampleRecords() { |
|
||||
// return sampleRecordDBService.getAll(); |
|
||||
// } |
|
||||
// |
|
||||
// public SampleRecord addSampleRecord(Date intertime, Integer tuebPos, BloodType bloodType, String sampleBarcode, String userid, String projIndex) { |
|
||||
// SampleRecord record = new SampleRecord(); |
|
||||
// record.bloodType = bloodType; |
|
||||
// record.sampleBarcode = sampleBarcode; |
|
||||
// record.userid = userid; |
|
||||
// record.date = intertime; |
|
||||
// record.sampleid = generateSampleId(intertime, tuebPos); |
|
||||
// for (String s : projIndex.split(",")) { |
|
||||
// record.projIndex.add(Integer.parseInt(s)); |
|
||||
// } |
|
||||
// sampleRecordDBService.add(record); |
|
||||
// return record; |
|
||||
// } |
|
||||
// |
|
||||
// public void addSampleRecord(Tube[] state) { |
|
||||
// Date intertime = new Date(); |
|
||||
// for (int i = 0; i < state.length; i++) { |
|
||||
// if (state[i] == null) { |
|
||||
// continue; |
|
||||
// } |
|
||||
// if (state[i].state.equals(TubeState.EMPTY)) { |
|
||||
// continue; |
|
||||
// } |
|
||||
// SampleRecord record = new SampleRecord(); |
|
||||
// record.bloodType = state[i].bloodType; |
|
||||
// record.sampleBarcode = state[i].sampleBarcode; |
|
||||
// record.userid = state[i].userid; |
|
||||
// record.date = intertime; |
|
||||
// record.isEmergency = state[i].isEmergency; |
|
||||
// record.sampleid = generateSampleId(intertime, i); |
|
||||
// record.projIndex = state[i].projIndex; |
|
||||
// state[i].sampleid = record.sampleid; |
|
||||
// sampleRecordDBService.add(record); |
|
||||
// } |
|
||||
// } |
|
||||
// |
|
||||
// public void addEmergencySampleRecord(Tube state) { |
|
||||
// Date intertime = new Date(); |
|
||||
// SampleRecord record = new SampleRecord(); |
|
||||
// state.isEmergency = true; |
|
||||
// |
|
||||
// record.bloodType = state.bloodType; |
|
||||
// record.sampleBarcode = state.sampleBarcode; |
|
||||
// record.userid = state.userid; |
|
||||
// record.date = intertime; |
|
||||
// record.isEmergency = true; |
|
||||
// record.sampleid = generateSampleId(intertime, -1); |
|
||||
// record.projIndex = state.projIndex; |
|
||||
// state.sampleid = record.sampleid; |
|
||||
// sampleRecordDBService.add(record); |
|
||||
// } |
|
||||
// |
|
||||
|
|
||||
} |
|
@ -1,4 +1,4 @@ |
|||||
package a8k.service.appdata; |
|
||||
|
package a8k.service.appsetting; |
||||
|
|
||||
import a8k.dbservice.AppSettingDBService; |
import a8k.dbservice.AppSettingDBService; |
||||
import a8k.dbservice.type.AppSetting; |
import a8k.dbservice.type.AppSetting; |
Write
Preview
Loading…
Cancel
Save
Reference in new issue