- 成果展示
ecg心电图
- Java代码展示,算法比较简单暴力,有更优解可以评论,谢谢。
// package com.example.userservice80.Controller;
import com.example.userservice80.entity.heartResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.io.*;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.Map;
@CrossOrigin
@RestController
@Slf4j
public class hiddenController {
@RequestMapping("/hidden")
public heartResult ArrhythmiaHeart(@RequestParam("str")String str) throws IOException {
System.out.println(str);
FileInputStream in = null;
FileInputStream inatr = null;
BufferedReader inhea = null;
String path1 = "D:\\mitdatabase\\hidden\\"+str+".hea";
String path2 = "D:\\mitdatabase\\hidden\\"+str+".dat";
String path3 = "D:\\mitdatabase\\hidden\\"+str+".atr";
inhea = new BufferedReader (new FileReader (path1) );
in = new FileInputStream ( path2 );
inatr = new FileInputStream (path3);
heartResult heartResult = new heartResult();
//解析hea文件
String str9 = null;
int h = 0;
String[] heastr = new String[2];
while( (str9 = inhea.readLine ()) != null ){
if(h>2) break;
if(h==1){
int y = str9.lastIndexOf(' ');
heastr[h-1] = str9.substring(y)+"导联一";
System.out.println(heastr[0]);
}
if(h==2){
int y = str9.lastIndexOf(' ');
heastr[h-1] = str9.substring(y)+"导联二";
}
h++;
}
heartResult.setDaolian(heastr);
//解析dat文件
int num = 0;
//给数组赋予下标
int k = 0;
int n=0;
DecimalFormat df = new DecimalFormat ("#.0000");
//这个数组就是存储字节数据,然后统一进行转换
int[] messDate = new int[7500];
double[] arr1 = new double[2500];
double[] arr2 = new double[2500];
double[] arr3 = new double[2500];
//in = new FileInputStream ( "C:\\Users\\Yanminghui\\Desktop\\Hreat\\n40.dat" );
int data;
while ((data = in.read ()) != -1 && num<7500) {
//如果能确定数据项所占字节长度是3
messDate[k] = data;
if (k == 2 && n<7500) {
String str1 = tenTransformSixteen1 ( messDate, k );
String str2 = tenTransformSixteen2 ( messDate, k );
long num1 = Integer.valueOf ( str1 );
if(num1>=2048){
num1 -= 2048;
num1 = 2048 - num1;
}
long num2 = Integer.valueOf ( str2 );
if(num2>=2048){
num2 -= 2048;
num2 = 2048 - num2;
}
double n1 = (double) (num1-0)/800;
double n2 = (double) (num2-0)/800;
n1 = Double.valueOf ( df.format ( n1 ) );
n2 = Double.valueOf ( df.format ( n2 ) );
arr1[n]=n1;
arr2[n]=n2;
/**
* 分析时间
*/
for(int i=0;i<2500;i++){
double db = (double) i/250;
arr3[i] = Double.parseDouble(df.format(db));
}
k = -1;
n++;
}
k += 1;
num += 1;
}
heartResult.setA1(arr1);
heartResult.setA2(arr2);
heartResult.setDtime(arr3);
/**
* ATR文件解析
*/
int sum=0;
double time = 0;
double[] Atime0 = new double[2500];
int[] Asymbol0 = new int[2500];
Map<Double,Integer> map = new HashMap<>();
int data0 = 0;
int nn=0,i=0;
int p=0;
int[] messdata = new int[5000];
while ((data0 = inatr.read ()) != -1 && time<10) {
messdata[i] = data0;
if(i%2!=0){
int n1,n2;
String str2 = Integer.toBinaryString(messdata[i-1]);
String str1 = Integer.toBinaryString(messdata[i]);
int len1=str1.length();
int len2=str2.length();
if(len1<8){
for(int l=0;l<8-len1;l++){
str1 = '0' + str1;
}
}
if(len2<8){
for(int l=0;l<8-len2;l++){
str2 = '0' + str2;
}
}
// System.out.println(str1+" "+str2);
String str0 = ""+str1+str2;
// System.out.println(str);
n1 = Integer.parseInt(str0.substring(0,6));
n2 = Integer.parseInt(str0.substring(6,16));
int npre1 = Integer.parseInt(String.valueOf(n1),2);
int npre2 = Integer.parseInt(String.valueOf(n2),2);
//判断atr标记值
if (npre1==60 || npre1==61 || npre1 ==62){
} else if (npre1 == 59) {
// System.out.println(npre1);
int[] Mes = new int[6];
for(int j=0;j<6;j++){
Mes[j] = inatr.read();
}
String str3 = Integer.toBinaryString(Mes[5]);
int len3=str3.length();
if(len3<8){
for(int l=0;l<8-len3;l++){
str3 = '0' + str3;
}
}
int pre = Integer.parseInt(str3.substring(0,6),2);
// System.out.println(pre);
int p1 = Integer.parseInt(String.valueOf(Mes[0]));
int p2 = Integer.parseInt(String.valueOf(Mes[1]));
int p3 = Integer.parseInt(String.valueOf(Mes[2]));
int p4 = Integer.parseInt(String.valueOf(Mes[3]));
int o = p1+p2+p3+p4;
// System.out.println(o);
sum += o;
time = Double.parseDouble(df.format((double) sum/250));
System.out.print(" "+time);
System.out.println();
Atime0[p]=time;
Asymbol0[nn]=pre;
nn++;
p++;
i += 6;
} else if (npre1==63) {
// System.out.print(npre1+" "+npre2);
if(npre2%2!=0){
npre2++;
}
int[] Mess = new int[npre2];
for(int j=0;j<npre2;j++){
Mess[j] = inatr.read();
}
// System.out.println();
i += npre2;
} else {
sum += npre2;
time = Double.parseDouble(df.format((double) sum/250));
//System.out.println(npre1+" "+time);
map.put(time,npre1);
Atime0[p]=time;
Asymbol0[nn]=npre1;
nn++;
p++;
}
}
i++;
}
int len = 0;
for(int j=0;j<Atime0.length;j++){
System.out.println(Atime0[j]);
if(Atime0[j]<10){
len++;
}else{
break;
}
}
double[] arr4 = new double[len];
int[] arr5 = new int[len];
for(int j=0;j<len;j++){
arr4[j] = Atime0[j];
arr5[j] = Asymbol0[j];
}
int pr = 0;
int[] arr = new int[len];
for(int j=0;j<2500;j++){
if(pr >= len){
break;
}
if(arr4[pr] == arr3[j]){
arr[pr] = j;
System.out.println(pr);
pr++;
}
}
String[] s = new String[len];
s = type(s,arr5);
heartResult.setAtime(arr4);
heartResult.setType(s);
heartResult.setA(arr);
heartResult.setAsymbol(arr5);
heartResult.setStatusCode(200);
System.out.println(heartResult);
return heartResult;
}
/**
* 十进制转十六进制转十进制
* <p>
* 需要将数组中每一个十进制字节转换成十六进制,然后拼接到一起,统一转换成十进制
*/
public static String tenTransformSixteen1(int[] data, int k) {
String str = "";
for (int i = 0; i <= k; i++) {
// data为十进制,将每个十进制解析成十六进制,然后将数组中数值一起解析成十进制
String hexString = Integer.toHexString ( data[i] );
if (hexString.length () == 1) {
hexString = "0" + hexString;
}
str = str + hexString;
}
str = str.charAt ( 3 ) + str.substring ( 0, 2 );
str = String.valueOf ( Long.valueOf ( str, 16 ) );
return str;
}
public static String tenTransformSixteen2(int[] data, int k) {
String str = "";
for (int i = 0; i <= k; i++) {
// data为十进制,将每个十进制解析成十六进制,然后将数组中数值一起解析成十进制
String hexString = Integer.toHexString ( data[i] );
if (hexString.length () == 1) {
hexString = "0" + hexString;
}
str = str + hexString;
}
str = str.charAt ( 2 ) + str.substring ( 4, 6 );
str = String.valueOf ( Long.valueOf ( str, 16 ) );
return str;
}
public static String[] type(String[] s,int[] sy){
int n = sy.length;
for(int i=0;i<n;i++){
if(sy[i]==0){
}else if(sy[i]==1){
s[i]="N--正常心搏";
}else if(sy[i]==2){
s[i]="L--左束支传导阻滞";
}else if(sy[i]==3){
s[i]="R--右束支传导阻滞";
}else if(sy[i]==4){
s[i]="a--异常心房早搏";
}else if(sy[i]==5){
s[i]="V--室性早搏";
}else if(sy[i]==6){
s[i]="F--心室融和心搏";
}else if(sy[i]==7){
s[i]="J--交界性早搏";
}else if(sy[i]==8){
s[i]="A--房性早搏";
}else if(sy[i]==9){
s[i]="S--早搏或室上性一尾心搏";
}else if(sy[i]==10){
s[i]="E--室性逸搏";
}else if(sy[i]==11){
s[i]="j--交界性逸搏";
}else if(sy[i]==12){
s[i]="/--起搏心拍";
}else if(sy[i]==13){
s[i]="Q--无法分类的节拍";
}else if(sy[i]==14){
s[i]="~--信号质量变化";
}else if(sy[i]==16){
s[i]="|--像人造的异位心搏";
}else if(sy[i]==18){
s[i]="s--St改变";
}else if(sy[i]==19){
s[i]="T--T波改变";
}else if(sy[i]==20){
s[i]="*--心脏收缩";
}else if(sy[i]==21){
s[i]="D--心脏舒张";
}else if(sy[i]==22){
s[i]="\"--注释注释";
}else if(sy[i]==23){
s[i]="=--测量注释";
}else if(sy[i]==24){
s[i]="p--P波峰值";
}else if(sy[i]==25){
s[i]="B--传导阻滞心搏";
}else if(sy[i]==26){
s[i]="^--起搏器伪迹";
}else if(sy[i]==27){
s[i]= "t--T波峰值";
}else if(sy[i]==28){
s[i]="+--节律变化";
}else if(sy[i]==29){
s[i]="u--U波峰值";
}else if(sy[i]==30){
s[i]="?--无";
}else if(sy[i]==31){
s[i]="!--心室颤动";
}else if(sy[i]==32){
s[i]="[--开始心室扑动/颤动";
}else if(sy[i]==33){
s[i]="]--结束心室扑动颤动";
}else if(sy[i]==34){
s[i]="e--房性逸搏";
}else if(sy[i]==35){
s[i]="n--室上性逸搏";
}else if(sy[i]==36){
s[i]="@--无";
}else if(sy[i]==37){
s[i]="x--未下传的P波";
}else if(sy[i]==38){
s[i]="f--起搏融合心跳";
}else if(sy[i]==39){
s[i]="(--QRS波开始";
}else if(sy[i]==40){
s[i]=")--QRS波结束";
}else if(sy[i]==41){
s[i]="r--R波落在T上的室性早搏";
}else{
System.out.println("错误");
}
}
return s;
}
}
- vue前端代码展示,使用echarts,但是这个代码没有实现标准心电图的那种红格子,对前端不是很在行,但是间距依旧是0.05ms,但是由于心电数据的dat文件中的记录有几十万甚至百万条数据,因此只选取了前7500条记录。
// <template>
<div>
<div id="main" style="width: 100%; height: 600px"></div>
</div>
</template>
<script>
import * as echarts from "echarts";
import axios from "axios";
export default {
name: "echartName",
data() {
return {
list: [],
list1: [],
list2: [],
list3: [],
list4: [],
list5: [],
list6: [],
daolian: [],
s: [],
str: "",
};
},
mounted() {
this.drawLine();
},
created() {
this.str = window.localStorage.getItem("str");
const _this = this;
axios
.get("http://localhost:8082/Arrhythmia?str=" + this.str)
.then(function (response) {
if (response.data.statusCode === 200) {
for (let i = 0; i < response.data.a1.length; i++) {
_this.list1.push(response.data.a1[i]);
}
for (let i = 0; i < response.data.a2.length; i++) {
_this.list2.push(response.data.a2[i]);
}
for (let i = 0; i < response.data.daolian.length; i++) {
_this.daolian.push(response.data.daolian[i]);
}
for (let i = 0; i < response.data.dtime.length; i++) {
_this.list3.push(response.data.dtime[i]);
}
for (let i = 0; i < response.data.atime.length; i++) {
_this.list4.push(response.data.atime[i]);
}
for (let i = 0; i < response.data.asymbol.length; i++) {
_this.list5.push(response.data.asymbol[i]);
}
for (let i = 0; i < response.data.a.length; i++) {
_this.list6.push(response.data.a[i]);
}
for (let i = 0; i < response.data.type.length; i++) {
_this.s.push(response.data.type[i]);
}
}
});
},
watch: {
list2: {
handler: function () {
this.drawLine();
},
deep: true,
},
},
methods: {
drawLine() {
const _this = this;
var chartDom = document.getElementById("main");
var myChart = echarts.init(chartDom);
var option;
var xAxisData = [];
for (let i = 0; i < 3600; i++) {
// xAxisData.push(Number(i / 360).toFixed(4));
xAxisData.push(i);
}
myChart.showLoading({
text: "loading",
color: "#c23531",
textColor: "#000",
maskColor: "rgba(255, 255, 255, 0.2)",
zlevel: 0,
});
setTimeout(() => {
// setOption前隐藏loading事件
myChart.hideLoading();
myChart.setOption(option);
}, 5000);
option = {
tooltip: {
trigger: "axis",
axisPointer: {
type: "cross",
label: {
backgroundColor: "#6a7985",
},
},
},
legend: {
data: _this.daolian,
textStyle: { color: "#66b3ff" },
},
// title: {
// left: "left",
// text: "101",
// },
toolbox: {
feature: {
dataZoom: {
yAxisIndex: "none",
},
restore: {},
saveAsImage: {},
},
},
xAxis: {
data: xAxisData,
show: false,
boundaryGap: false,
smooth: true,
axisLine: { onZero: true },
},
yAxis: {
axisTick: {
show: false, // 不显示坐标轴刻度线
},
type: "value",
boundaryGap: false,
smooth: true,
},
dataZoom: [
{
type: "inside",
start: 0,
end: 20,
},
{
start: 0,
end: 20,
},
],
series: [
{
symbol: "none",
name: _this.daolian[0],
type: "line",
data: _this.list1,
smooth: true,
lineStyle: {
color: "#0770FF",
},
markPoint : {//数据全是markPoint
symbolSize: 20, // 标注大小,半宽(半径)参数,当图形为方向或菱形则总宽度为symbolSize * 2
// itemStyle: {
// normal: {
// borderColor: '#1e90ff',
// borderWidth: 1, // 标注边线线宽,单位px,默认为1
// label: {
// show: false
// }
// },
// emphasis: {
// borderColor: '#1e90ff',
// borderWidth: 5,
// label: {
// show: false
// }
// }
// },
// effect : {
// show: true,
// shadowBlur : 0
// },
label: {
show: true
},
// data:[{
// xAxis: '0.5',
// yAxis: '-0.315',
// }]
data: (function() {
const dat = [[]];
let len = _this.list4.length;
while (len--) {
dat.push({
xAxis: _this.list6[len],
yAxis: _this.list1[_this.list6[len]],
value: _this.s[len]
})
}
// dat.push({
// xAxis: [0.05, 0.2139, 1.0278, 1.8389, 2.6278, 3.4194, 4.2083, 5.025, 5.6778, 6.6722, 7.5167, 8.3278, 9.1167, 9.8889],
// yAxis: [0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,0.9,0.8,0.7,0.6,0.5],
// })
return dat
})()
},//end markPoint
},
{
symbol: "none",
name: _this.daolian[1],
type: "line",
data: _this.list2,
smooth: true,
lineStyle: {
color: "#F2597F",
},
markPoint : {
symbolSize: 20,
label: {
show: true
},
data: (function() {
const dat = [[]];
let len = _this.list4.length;
while (len--) {
dat.push({
xAxis: _this.list6[len],
yAxis: _this.list2[_this.list6[len]],
value: _this.s[len]
})
}
return dat
})()
},//end markPoint
},
],
};
option && myChart.setOption(option);
},
},
};
</script>