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; |
|||
|
|||
import a8k.optalgo.type.LinearResult; |
|||
import a8k.optalgo.type.OptAlgoResult; |
|||
|
|||
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; |
|||
|
|||
import java.util.ArrayList; |
|||
import java.util.List; |
|||
|
|||
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; |
|||
|
|||
public class PeakInfo { |
|||
public class Peak { |
|||
public Boolean findPeak; |
|||
public Float peakFullArea; |
|||
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.type.AppSetting; |
Write
Preview
Loading…
Cancel
Save
Reference in new issue