511 lines
20 KiB
C#
511 lines
20 KiB
C#
using HTTPServerLib;
|
|
using Newtonsoft.Json;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Configuration;
|
|
using System.Data;
|
|
using System.Drawing;
|
|
using System.Drawing.Imaging;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Net;
|
|
using System.Reflection;
|
|
using System.Runtime.InteropServices.WindowsRuntime;
|
|
using System.Text;
|
|
using System.Windows.Forms;
|
|
using 心电图绘制;
|
|
|
|
namespace _1200Gxml心电图绘制
|
|
{
|
|
public partial class Form3 : Form
|
|
{
|
|
ExampleServer server;
|
|
public Form3()
|
|
{
|
|
InitializeComponent();
|
|
}
|
|
|
|
void DataRead()
|
|
{
|
|
|
|
}
|
|
private void Form3_Load(object sender, EventArgs e)
|
|
{
|
|
|
|
string strip = ConfigurationManager.AppSettings["ip"];
|
|
string stport = ConfigurationManager.AppSettings["port"];
|
|
|
|
server = new ExampleServer(strip, int.Parse(stport), txt_msg);
|
|
|
|
EcgDataDraw_New EDDN = new EcgDataDraw_New();
|
|
var btmp = new Bitmap(pictureBox1.Width, pictureBox1.Height);
|
|
pictureBox1.Image = btmp;
|
|
Graphics Ecg_Graphics = Graphics.FromImage(pictureBox1.Image);
|
|
combo_reportModel.SelectedIndex = 0;
|
|
cBoxSpeed.SelectedIndex = 3;
|
|
cBoxAmplitude.SelectedIndex = 2;
|
|
Start();
|
|
//加载心电数据
|
|
// #region
|
|
//Dictionary<int, List<float>> EcgTable = new Dictionary<int, List<float>>();
|
|
//for (int k = 0; k < 8; k++)
|
|
// EcgTable.Add(k, new List<float>());
|
|
|
|
//string contentStr = File.ReadAllText(Application.StartupPath + @"\蓝牙holter数据\dc93ee94-c0e8-4dba-8d29-ed86b2dcb6e8.ecg");
|
|
//var contenList = JsonConvert.DeserializeObject<List<byte[]>>(contentStr);
|
|
|
|
////这里是把8个通道的数据转换出来 放到一个 字典里
|
|
|
|
//for (int i = 0; i < contenList.Count; i++)
|
|
//{
|
|
// for (int j = 0; j < contenList[i].Length; j += 16)
|
|
// {
|
|
// EcgTable[0].Add((float)((short)(byteToShort(contenList[i][j], contenList[i][j + 1]))));
|
|
// EcgTable[1].Add((float)((short)(byteToShort(contenList[i][j + 2], contenList[i][j + 3]))));
|
|
// EcgTable[2].Add((float)((short)(byteToShort(contenList[i][j + 4], contenList[i][j + 5]))));
|
|
// EcgTable[3].Add((float)((short)(byteToShort(contenList[i][j + 6], contenList[i][j + 7]))));
|
|
// EcgTable[4].Add((float)((short)(byteToShort(contenList[i][j + 8], contenList[i][j + 9]))));
|
|
// EcgTable[5].Add((float)((short)(byteToShort(contenList[i][j + 10], contenList[i][j + 11]))));
|
|
// EcgTable[6].Add((float)((short)(byteToShort(contenList[i][j + 12], contenList[i][j + 13]))));
|
|
// EcgTable[7].Add((float)((short)(byteToShort(contenList[i][j + 14], contenList[i][j + 15]))));
|
|
// }
|
|
|
|
//}
|
|
|
|
////在这里你就可以对这8个通道的数据进行滤波了 在这里写滤波代码
|
|
|
|
|
|
//Dictionary<int, List<float>> EcgTable2 = new Dictionary<int, List<float>>();
|
|
////把 I II导联加入字典中
|
|
//for (int i = 0; i < 2; i++)
|
|
// EcgTable2.Add(i, EcgTable[i]);
|
|
|
|
//List<float> list3 = new List<float>();
|
|
//List<float> list4 = new List<float>();
|
|
//List<float> list5 = new List<float>();
|
|
//List<float> list6 = new List<float>();
|
|
////把 III AVR AVL AVF 这四个导联计算出来 加入字典
|
|
//for (int A = 0; A < EcgTable[0].Count; A++)
|
|
//{
|
|
// list3.Add(EcgTable[1][A] - EcgTable[0][A]);//III
|
|
// list4.Add(-(EcgTable[1][A] + EcgTable[0][A]) / 2);//avR
|
|
// list5.Add(EcgTable[0][A] - EcgTable[1][A] / 2);//avL
|
|
// list6.Add(EcgTable[1][A] - EcgTable[0][A] / 2);//avF
|
|
//}
|
|
//EcgTable2.Add(2, list3);
|
|
//EcgTable2.Add(3, list4);
|
|
//EcgTable2.Add(4, list5);
|
|
//EcgTable2.Add(5, list6);
|
|
////把 V1-V6导联 加入字典
|
|
//for (int i = 6; i < 12; i++)
|
|
// EcgTable2.Add(i, EcgTable[i - 4]);
|
|
|
|
//Dictionary<int, List<float>> EcgTable3 = new Dictionary<int, List<float>>();
|
|
//for (int i = 0; i < EcgTable2.Count; i++)
|
|
// EcgTable3.Add(i, baseLineFilter(i, EcgTable2[i]));
|
|
|
|
//this.samplingRate = 300;
|
|
//this.windowSize = 60000;
|
|
|
|
//List<int> rPosList = DetectRWave(EcgTable3[1].ToArray());
|
|
|
|
|
|
////for (int i = 0; i < 12; i++)
|
|
//// EcgTable2[i].RemoveRange(0, 500);
|
|
|
|
|
|
////string[] ecgDataArray = dataStr.Split(' ');//把xml中每一导联的数据 变成数组 然后把数据赋值给 EcgTable 字典中的每一导联
|
|
////List<float> ecg_List = new List<float>();
|
|
////for (int i = 0; i < ecgDataArray.Length; i++)
|
|
//// ecg_List.Add(float.Parse(ecgDataArray[i]));
|
|
////for (int i = 0; i < 12; i++)
|
|
//// EcgTable.Add(i, ecg_List);
|
|
//#endregion
|
|
|
|
|
|
|
|
//List<int> leadInfo = new List<int>();
|
|
//for (int i = 0; i < 12; i++)
|
|
// leadInfo.Add(i);
|
|
//EDDN.InitEcgParameter(btmp, 12, EcgTable3, 96, leadInfo);//初始化
|
|
//EDDN.Draw_EcgBackGroundGrid();//画背景网格
|
|
//EDDN.Draw_EcgWave();//画波形
|
|
//EDDN.Draw_CalibrationVoltage_And_LeadName();//画定标电压和导联名称
|
|
|
|
// EDDN.drawRWavePos(rPosList);//绘制R波位置
|
|
|
|
}
|
|
|
|
private void groupBox2_Enter(object sender, EventArgs e)
|
|
{
|
|
|
|
}
|
|
|
|
private void pictureBox1_Click(object sender, EventArgs e)
|
|
{
|
|
|
|
}
|
|
|
|
|
|
short byteToShort(byte a, byte b)
|
|
{
|
|
short volV = (short)((a << 8) + b);//正确
|
|
return (short)(volV / 45);
|
|
}
|
|
|
|
private void pictureBox1_DoubleClick(object sender, EventArgs e)
|
|
{
|
|
|
|
}
|
|
|
|
List<float> baseLineFilter(int leadIndex, List<float> inputDatas)
|
|
{
|
|
List<float> outPutDatas = new List<float>();
|
|
float sum = 0;
|
|
for (int i = 0; i < inputDatas.Count; i++)
|
|
sum += inputDatas[i];
|
|
float avgVal = sum / inputDatas.Count;
|
|
for (int i = 0; i < inputDatas.Count; i++)
|
|
outPutDatas.Add(inputDatas[i] - avgVal);
|
|
if (leadIndex == 1)
|
|
{
|
|
float sum2 = 0;
|
|
int indexCount = 0;
|
|
for (int i = 0; i < outPutDatas.Count; i++)
|
|
{
|
|
if (outPutDatas[i] > 0)
|
|
{
|
|
sum2 += outPutDatas[i];
|
|
indexCount++;
|
|
}
|
|
}
|
|
float avgVal1 = sum2 / indexCount;
|
|
threshold = avgVal1 + 130;
|
|
|
|
}
|
|
return outPutDatas;
|
|
}
|
|
|
|
|
|
private int samplingRate;
|
|
private int windowSize;
|
|
private double threshold;
|
|
|
|
|
|
|
|
|
|
public List<int> DetectRWave(float[] ecg_data)
|
|
{
|
|
List<int> rWaveIndices = new List<int>(); int maxIndex = 0;
|
|
// R波识别
|
|
int r_wave_count = 0;
|
|
for (int i = 1; i < ecg_data.Length; i++)
|
|
{
|
|
if (ecg_data[i] > ecg_data[i - 1] && ecg_data[i] > ecg_data[i + 1] && ecg_data[i] > threshold)
|
|
{
|
|
if (!rWaveIndices.Contains(i))
|
|
rWaveIndices.Add(i);
|
|
}
|
|
}
|
|
return rWaveIndices;
|
|
}
|
|
|
|
private void 生成高精度打印报告ToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
GetEcgViewDataImage(null, "这是地址"); //普通打印
|
|
}
|
|
|
|
float[] valueConvert(float[] valueArray)
|
|
{
|
|
float[] quotients = valueArray.Select(n => n / 500).ToArray();
|
|
return quotients;
|
|
}
|
|
|
|
private string _printFilter = "0Hz";
|
|
private Bitmap _ecgBitMap;
|
|
private static int _printDpi = 300;//打印DPI
|
|
private const int Dpi = 96; //屏幕DIP
|
|
private readonly string _isQiBo;//是否是起搏信号
|
|
private int _leadindexdata;
|
|
private const string LeaderName15 = "5x3+1导报告模式";
|
|
private const string LeaderName18 = "18导报告模式";
|
|
private string _reportTitleContent = string.Empty;
|
|
private string _idStr;
|
|
private string collectTime;//心电数据采集时间
|
|
private const double Coefficient = 1.02; //放大缩小的系数
|
|
private List<int> _longLeadInfo = new List<int>(); //存储任意长两导联的导联下标
|
|
private readonly List<int> _longLeadInfo3 = new List<int>(); //存储任意长三导联的导联下标
|
|
public string LeaderType; //导联类别
|
|
private Dictionary<int, List<float>> _ecgDataDicAfterFilter = new Dictionary<int, List<float>>(); //滤波后的数据都存在这个字典中
|
|
private int _filterIndex; //滤波时 此标志 指示从数组中 哪一个位置开始滤波
|
|
/// <summary>
|
|
/// 获得心电诊断快照数据
|
|
/// </summary>
|
|
public void GetEcgViewDataImage(Image img, string addr)
|
|
{
|
|
//_ecgDataDicAfterFilter.Clear();
|
|
//string ecgDataJsonStr = File.ReadAllText(Application.StartupPath + @"\60心拍心电图数据JSON.txt");
|
|
//leadDataModel LDM = JsonConvert.DeserializeObject<leadDataModel>(ecgDataJsonStr);
|
|
//float[] LEAD_I = valueConvert(Array.ConvertAll(LDM.LEAD_I.Split(' '), float.Parse));
|
|
//_ecgDataDicAfterFilter.Add(0, LEAD_I.ToList());
|
|
//float[] LEAD_II = valueConvert(Array.ConvertAll(LDM.LEAD_II.Split(' '), float.Parse));
|
|
//_ecgDataDicAfterFilter.Add(1, LEAD_II.ToList());
|
|
//float[] LEAD_III = valueConvert(Array.ConvertAll(LDM.LEAD_III.Split(' '), float.Parse));
|
|
//_ecgDataDicAfterFilter.Add(2, LEAD_III.ToList());
|
|
//float[] LEAD_AVR = valueConvert(Array.ConvertAll(LDM.LEAD_AVR.Split(' '), float.Parse));
|
|
//_ecgDataDicAfterFilter.Add(3, LEAD_AVR.ToList());
|
|
//float[] LEAD_AVL = valueConvert(Array.ConvertAll(LDM.LEAD_AVL.Split(' '), float.Parse));
|
|
//_ecgDataDicAfterFilter.Add(4, LEAD_AVL.ToList());
|
|
//float[] LEAD_AVF = valueConvert(Array.ConvertAll(LDM.LEAD_AVF.Split(' '), float.Parse));
|
|
//_ecgDataDicAfterFilter.Add(5, LEAD_AVF.ToList());
|
|
//float[] LEAD_V1 = valueConvert(Array.ConvertAll(LDM.LEAD_V1.Split(' '), float.Parse));
|
|
//_ecgDataDicAfterFilter.Add(6, LEAD_V1.ToList());
|
|
//float[] LEAD_V2 = valueConvert(Array.ConvertAll(LDM.LEAD_V2.Split(' '), float.Parse));
|
|
//_ecgDataDicAfterFilter.Add(7, LEAD_V2.ToList());
|
|
//float[] LEAD_V3 = valueConvert(Array.ConvertAll(LDM.LEAD_V3.Split(' '), float.Parse));
|
|
//_ecgDataDicAfterFilter.Add(8, LEAD_V3.ToList());
|
|
//float[] LEAD_V4 = valueConvert(Array.ConvertAll(LDM.LEAD_V4.Split(' '), float.Parse));
|
|
//_ecgDataDicAfterFilter.Add(9, LEAD_V4.ToList());
|
|
//float[] LEAD_V5 = valueConvert(Array.ConvertAll(LDM.LEAD_V5.Split(' '), float.Parse));
|
|
//_ecgDataDicAfterFilter.Add(10, LEAD_V5.ToList());
|
|
//float[] LEAD_V6 = valueConvert(Array.ConvertAll(LDM.LEAD_V6.Split(' '), float.Parse));
|
|
//_ecgDataDicAfterFilter.Add(11, LEAD_V6.ToList());
|
|
|
|
|
|
//_reportTitleContent = "十二导联静态心电图报告";
|
|
//_idStr = "5566778899";
|
|
//collectTime = "2024-12-20 13:28:51";
|
|
////长两导的模式下 默认添加 第一导 和 第二导联 为 长显示两导联
|
|
//_longLeadInfo.Add(0);
|
|
//_longLeadInfo.Add(1);
|
|
////长三导的模式下 默认添加 第一导 和 第二导联和第三导联 为 长显示三导联
|
|
//_longLeadInfo3.Add(0);
|
|
//_longLeadInfo3.Add(1);
|
|
//_longLeadInfo3.Add(2);
|
|
//var cpew = new CommonPrintEcgWave();
|
|
//var filter = _printFilter;
|
|
//_ecgBitMap = new Bitmap(1090 * _printDpi / Dpi, 760 * _printDpi / Dpi);
|
|
//_ecgBitMap.SetResolution(_printDpi, _printDpi);
|
|
//cpew.InitEcgParameter(_ecgBitMap, _ecgDataDicAfterFilter, _isQiBo, _paperSpeed, _amplitude);
|
|
|
|
////************************************************************************
|
|
//var ecgInfoList = new string[13];
|
|
//ecgInfoList[0] = "张三";
|
|
//ecgInfoList[1] = "女";
|
|
//ecgInfoList[2] = "28";
|
|
//ecgInfoList[3] = "RV5+SV1";
|
|
//ecgInfoList[4] = "PR间期";
|
|
//ecgInfoList[5] = "QRS间期";
|
|
//ecgInfoList[6] = "QT/QTC";
|
|
//ecgInfoList[7] = "QRS电轴";
|
|
//ecgInfoList[8] = "RV5/SV1";
|
|
//ecgInfoList[9] = "心率";
|
|
//ecgInfoList[10] = "病室";
|
|
//ecgInfoList[11] = "床号";
|
|
//ecgInfoList[12] = "住院号";
|
|
//SetAandP(); //设置增益和走速
|
|
|
|
//var diagContent = "这里是心电图的诊断结论";
|
|
//var diagArray = diagContent.Split('\n');
|
|
//diagContent = string.Empty;
|
|
//for (var i = 0; i < diagArray.Length; i++) diagContent += diagArray[i].Trim();
|
|
|
|
//if (_ecgDataDicAfterFilter.Count > 0)
|
|
// _filterIndex = 0;
|
|
//else
|
|
// _filterIndex = 0;
|
|
//// _leadindexdata = hScrollBar_Lead.Value * _filterIndex;
|
|
//_leadindexdata = _filterIndex;
|
|
|
|
//if (combo_reportModel.Text == LeaderName15) filter += " 十五加一长导模式";
|
|
//if (combo_reportModel.Text == LeaderName18) filter += " 十八导模式";
|
|
//if (combo_reportModel.SelectedIndex == 2)
|
|
//{
|
|
// cpew.PrintBackGroundGrid(16, 196);
|
|
// cpew.PrintLongReportHeadInfo(_reportTitleContent);
|
|
// cpew.PrintLongEcgInfo(ecgInfoList, _idStr);
|
|
// cpew.PrintLongDiagInfo(diagContent, "医生姓名",
|
|
// "2024-12-20", filter,
|
|
// collectTime, "心电图科", _amp, _ps, img, addr);
|
|
//}
|
|
//else
|
|
//{
|
|
// cpew.PrintBackGroundGrid(40, 196); //(197-42)*12=1860像素
|
|
// cpew.PrintReportHeadInfo(_reportTitleContent, "2024-12-20");
|
|
// cpew.PrintEcgInfo(ecgInfoList, _idStr);
|
|
// cpew.PrintDiagInfo(diagContent, "医生姓名", filter,
|
|
// collectTime, "心电图科", _amp, _ps, img, addr);
|
|
//}
|
|
|
|
////6x2
|
|
//if (combo_reportModel.SelectedIndex == 0)
|
|
//{
|
|
// cpew.PrintEcgWave(8, 1, _leadindexdata);
|
|
// cpew.PrintEcgLeadName(_calibrationVoltage * Coefficient);
|
|
//}
|
|
|
|
////6x2+2
|
|
//if (combo_reportModel.SelectedIndex == 1)
|
|
//{
|
|
// cpew.PrintEcgWave(8, 1, _longLeadInfo, _leadindexdata, _leadindexdata);
|
|
// cpew.PrintEcgLeadName(_calibrationVoltage * Coefficient, _longLeadInfo);
|
|
//}
|
|
|
|
////十二长导
|
|
//if (combo_reportModel.SelectedIndex == 2)
|
|
//{
|
|
// cpew.PrintLongEcgWave(5, 1, _leadindexdata);
|
|
// //cpew.PrintLongEcgWave(8, 1, _leadindexdata);
|
|
// cpew.PrintLongEcgLeadName(_calibrationVoltage * Coefficient);
|
|
//}
|
|
|
|
////4*3 II长导模式
|
|
//if (combo_reportModel.SelectedIndex == 3)
|
|
//{
|
|
// cpew.PrintEcgWaveFourOne(8, 1, _leadindexdata, _leadindexdata);
|
|
// cpew.PrintLeadNameFourOne(_calibrationVoltage * Coefficient, _longLeadInfo);
|
|
//}
|
|
|
|
|
|
////4*3+3 长导模式
|
|
//if (combo_reportModel.SelectedIndex == 4)
|
|
//{
|
|
// cpew.PrintEcgWaveFourThree(8, 1, _longLeadInfo3, _leadindexdata, _leadindexdata);
|
|
// cpew.PrintLeadNameFourThree(_calibrationVoltage * Coefficient, _longLeadInfo3);
|
|
//}
|
|
|
|
|
|
////15x1+1导
|
|
//if (combo_reportModel.Text.Trim() == LeaderName15)
|
|
//{
|
|
// cpew.PrintEcgWaveFifteen(8, 1, _leadindexdata);
|
|
// cpew.PrintLeadNameFifteen(_calibrationVoltage * Coefficient, LeaderType);
|
|
//}
|
|
|
|
////十八导
|
|
//if (combo_reportModel.Text.Trim() == LeaderName18)
|
|
//{
|
|
// cpew.PrintEcgWaveEighteen(8, 1, _leadindexdata);
|
|
// cpew.PrintLeadNameEighteen(_calibrationVoltage * Coefficient);
|
|
//}
|
|
|
|
////_sourceCegBmp = _ecgBitMap;
|
|
//_ecgBitMap.Save("1.jpg", ImageFormat.Jpeg);
|
|
}
|
|
|
|
|
|
|
|
private double _paperSpeed = 25.0; //走速
|
|
private string _ps = "25mm/s"; //打印时的走速
|
|
private double _amplitude = 10.0; //振幅
|
|
private string _amp = "10mm/mV"; //打印时的振幅
|
|
private double _calibrationVoltage = 2.0;//定标电压
|
|
/// <summary>
|
|
/// 设置增益和走速和定标电压
|
|
/// </summary>
|
|
private void SetAandP()
|
|
{
|
|
if (cBoxSpeed.SelectedIndex == 0) //走速
|
|
{
|
|
_paperSpeed = 5;
|
|
_ps = "5mm/s";
|
|
}
|
|
|
|
if (cBoxSpeed.SelectedIndex == 1)
|
|
{
|
|
_paperSpeed = 10;
|
|
_ps = "10mm/s";
|
|
}
|
|
|
|
if (cBoxSpeed.SelectedIndex == 2) //走速
|
|
{
|
|
_paperSpeed = 12.5;
|
|
_ps = "12.5mm/s";
|
|
}
|
|
|
|
if (cBoxSpeed.SelectedIndex == 3)
|
|
{
|
|
_paperSpeed = 25.0;
|
|
_ps = "25mm/s";
|
|
}
|
|
|
|
if (cBoxSpeed.SelectedIndex == 4)
|
|
{
|
|
_paperSpeed = 50.0;
|
|
_ps = "50mm/s";
|
|
}
|
|
|
|
if (cBoxAmplitude.SelectedIndex == 0) //振幅
|
|
{
|
|
_amplitude = 2.5;
|
|
_amp = "2.5mm/mV";
|
|
_calibrationVoltage = 0.5;
|
|
}
|
|
|
|
if (cBoxAmplitude.SelectedIndex == 1)
|
|
{
|
|
_amplitude = 5.0;
|
|
_amp = "5mm/mV";
|
|
_calibrationVoltage = 1.0;
|
|
}
|
|
|
|
if (cBoxAmplitude.SelectedIndex == 2)
|
|
{
|
|
_amplitude = 10.0;
|
|
_amp = "10mm/mV";
|
|
_calibrationVoltage = 2.0;
|
|
}
|
|
|
|
if (cBoxAmplitude.SelectedIndex == 3)
|
|
{
|
|
_amplitude = 20.0;
|
|
_amp = "20mm/mV";
|
|
_calibrationVoltage = 4.0;
|
|
}
|
|
|
|
if (cBoxAmplitude.SelectedIndex == 4)
|
|
{
|
|
_amplitude = 40.0;
|
|
_amp = "40mm/mV";
|
|
_calibrationVoltage = 8.0;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 开启服务
|
|
/// </summary>
|
|
private void Start()
|
|
{
|
|
server.SetRoot(AppDomain.CurrentDomain.BaseDirectory);
|
|
server.Logger = new ConsoleLogger(txt_msg);
|
|
server.Start();
|
|
}
|
|
#region 类型改变事件
|
|
|
|
|
|
private void combo_reportModel_SelectedIndexChanged(object sender, EventArgs e)
|
|
{
|
|
server.reportMode = combo_reportModel.SelectedIndex;
|
|
|
|
server.strreportMode = combo_reportModel.Text.Trim();
|
|
}
|
|
|
|
private void cBoxSpeed_SelectedIndexChanged(object sender, EventArgs e)
|
|
{
|
|
server.cBoxSpeed = cBoxSpeed.SelectedIndex;
|
|
}
|
|
|
|
private void cBoxAmplitude_SelectedIndexChanged(object sender, EventArgs e)
|
|
{
|
|
server.cBoxAmplitude = cBoxAmplitude.SelectedIndex;
|
|
}
|
|
#endregion
|
|
|
|
private void Form3_FormClosed(object sender, FormClosedEventArgs e)
|
|
{
|
|
server.Stop();
|
|
}
|
|
}
|
|
}
|