279 lines
15 KiB
C#
279 lines
15 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Drawing;
|
||
using System.Drawing.Imaging;
|
||
using System.IO;
|
||
using System.Linq;
|
||
using System.Text;
|
||
using System.Threading.Tasks;
|
||
using System.Xml;
|
||
|
||
namespace 云心电ECG数据解析服务端
|
||
{
|
||
public class Hl7EcgOptions
|
||
{
|
||
|
||
|
||
|
||
float[] valueConvert(float[] valueArray)
|
||
{
|
||
float[] quotients = valueArray.Select(n => n / 9).ToArray();//把数值缩小9倍 这是用标准数据进行标定得到的 缩小倍数系数
|
||
return quotients;
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 读取HL7文件中的患者信息和心电分析参数
|
||
/// </summary>
|
||
/// <param name="xmlFilePath"></param>
|
||
public analysisParas getAnalysisParas(string xmlFilePath)
|
||
{
|
||
try
|
||
{
|
||
FileInfo fi = new FileInfo(xmlFilePath);
|
||
XmlDocument xmlDoc = new XmlDocument();
|
||
XmlReaderSettings settings = new XmlReaderSettings();
|
||
settings.IgnoreComments = true;//忽略文档里面的注释
|
||
XmlReader reader = XmlReader.Create(xmlFilePath, settings);
|
||
xmlDoc.Load(reader);
|
||
XmlNodeList xnList = xmlDoc.DocumentElement.GetElementsByTagName("annotation");
|
||
analysisParas ap = new analysisParas();
|
||
|
||
//先从hl7 ecg xml文件中读取心电数据
|
||
XmlNodeList xnListx1 = xmlDoc.DocumentElement.GetElementsByTagName("digits");
|
||
// Dictionary<int, List<float>> EcgTable = new Dictionary<int, List<float>>();
|
||
int leadDataIndex = 0;
|
||
for (int i = 0; i < 12; i++)
|
||
{
|
||
string[] ecgDataArray = new string[xnListx1.Item(leadDataIndex + i).InnerText.Split(' ').Length];
|
||
ecgDataArray = xnListx1.Item(leadDataIndex + i).InnerText.Split(' ');
|
||
//List<float> ecg_List = valueConvert(Array.ConvertAll(ecgDataArray, float.Parse)).ToList<float>();
|
||
List<float> ecg_List = new List<float>();
|
||
for (int b = 0; b < ecgDataArray.Length; b++)
|
||
if (!string.IsNullOrEmpty(ecgDataArray[b]))
|
||
ecg_List.Add(float.Parse(ecgDataArray[b]) / 9);
|
||
if (i == 0) ap.LEAD_I = ecg_List;
|
||
if (i == 1) ap.LEAD_II = ecg_List;
|
||
if (i == 2) ap.LEAD_III = ecg_List;
|
||
if (i == 3) ap.LEAD_AVR = ecg_List;
|
||
if (i == 4) ap.LEAD_AVL = ecg_List;
|
||
if (i == 5) ap.LEAD_AVF = ecg_List;
|
||
if (i == 6) ap.LEAD_V1 = ecg_List;
|
||
if (i == 7) ap.LEAD_V2 = ecg_List;
|
||
if (i == 8) ap.LEAD_V3 = ecg_List;
|
||
if (i == 9) ap.LEAD_V4 = ecg_List;
|
||
if (i == 10) ap.LEAD_V5 = ecg_List;
|
||
if (i == 11) ap.LEAD_V6 = ecg_List;
|
||
// EcgTable.Add(i, ecg_List);
|
||
}
|
||
|
||
|
||
XmlNodeList xnList1 = xmlDoc.DocumentElement.GetElementsByTagName("family");
|
||
ap.patientName = xnList1[0].InnerText;//姓名
|
||
XmlNodeList xnList2 = xmlDoc.DocumentElement.GetElementsByTagName("administrativeGenderCode");
|
||
string valStr = xnList2[0].OuterXml;
|
||
string sexStr = valStr.Substring(valStr.IndexOf("code="), valStr.IndexOf("codeSystem=") - valStr.IndexOf("code=")).Replace("code=", "").Replace("\"", "").Trim();//性别
|
||
if (sexStr.Trim() == "M")
|
||
ap.gender = "男";
|
||
if (sexStr.Trim() == "F")
|
||
ap.gender = "女";
|
||
|
||
XmlNodeList xnList4 = xmlDoc.DocumentElement.GetElementsByTagName("birthTime");
|
||
string birthday = xnList4[0].OuterXml;//出生日期
|
||
birthday = birthday.Substring(birthday.IndexOf("value="), birthday.IndexOf("xmlns=") - birthday.IndexOf("value=")).Replace("value=", "").Replace("\"", "").Trim();
|
||
if (birthday.Length > 0)
|
||
{
|
||
ap.birthDay = birthday;
|
||
int year = int.Parse(ap.birthDay.Substring(0, 4));
|
||
ap.age = (DateTime.Now.Year - year).ToString();
|
||
}
|
||
|
||
XmlNodeList xnList5 = xmlDoc.DocumentElement.GetElementsByTagName("patientid");
|
||
string patientId = xnList5[0].OuterXml;//患者id
|
||
patientId = patientId.Substring(patientId.IndexOf("extension="), patientId.IndexOf("xmlns=") - patientId.IndexOf("extension=")).Replace("extension=", "").Replace("\"", "").Trim();
|
||
ap.patientid = patientId;
|
||
|
||
//获取日期和时间
|
||
XmlNodeList xnList3 = xmlDoc.DocumentElement.GetElementsByTagName("effectiveTime");
|
||
string collStr = xnList3[0].FirstChild.OuterXml;
|
||
string collectTime = collStr.Substring(collStr.IndexOf("value="), collStr.IndexOf("xmlns=") - collStr.IndexOf("value=")).Replace("value=", "").Replace("\"", "").Trim();//采集时间
|
||
if (collectTime.Length > 0)
|
||
{
|
||
ap.collectTime = collectTime.Insert(4, "-").Insert(7, "-").Insert(10, " ").Insert(13, ":").Insert(16, ":");//转换成日期时间格式
|
||
}
|
||
foreach (XmlNode xnx in xnList)
|
||
{
|
||
// string sss = xnx.FirstChild.Name;
|
||
string OuterXml1 = xnx.FirstChild.OuterXml;
|
||
// string xxx = xnx.LastChild.Name;
|
||
string OuterXml2 = xnx.LastChild.OuterXml;
|
||
if (OuterXml1.Contains("MDC_ECG_HEART_RATE"))
|
||
{
|
||
string valueStr = OuterXml2.Substring(OuterXml2.IndexOf("value="), OuterXml2.IndexOf("unit=") - OuterXml2.IndexOf("value=")).Replace("value=", "").Replace("\"", "").Trim();
|
||
ap.heartRate = valueStr;
|
||
}
|
||
|
||
if (OuterXml1.Contains("MDC_ECG_TIME_PD_P") && !OuterXml1.Contains("MDC_ECG_TIME_PD_PR") && !OuterXml1.Contains("MDC_ECG_TIME_PD_PQ"))
|
||
{
|
||
string valueStr = OuterXml2.Substring(OuterXml2.IndexOf("value="), OuterXml2.IndexOf("unit=") - OuterXml2.IndexOf("value=")).Replace("value=", "").Replace("\"", "").Trim();
|
||
ap.P = valueStr;
|
||
}
|
||
|
||
if (OuterXml1.Contains("MDC_ECG_TIME_PD_QRS"))
|
||
{
|
||
string valueStr = OuterXml2.Substring(OuterXml2.IndexOf("value="), OuterXml2.IndexOf("unit=") - OuterXml2.IndexOf("value=")).Replace("value=", "").Replace("\"", "").Trim();
|
||
ap.QRS = valueStr;
|
||
}
|
||
|
||
if (OuterXml1.Contains("MDC_ECG_TIME_PD_RR"))
|
||
{
|
||
string valueStr = OuterXml2.Substring(OuterXml2.IndexOf("value="), OuterXml2.IndexOf("unit=") - OuterXml2.IndexOf("value=")).Replace("value=", "").Replace("\"", "").Trim();
|
||
ap.RR = valueStr;
|
||
}
|
||
|
||
if (OuterXml1.Contains("MDC_ECG_TIME_PD_PR"))
|
||
{
|
||
string valueStr = OuterXml2.Substring(OuterXml2.IndexOf("value="), OuterXml2.IndexOf("unit=") - OuterXml2.IndexOf("value=")).Replace("value=", "").Replace("\"", "").Trim();
|
||
ap.PR = valueStr;
|
||
}
|
||
|
||
if (OuterXml1.Contains("MDC_ECG_TIME_PD_PQ"))
|
||
{
|
||
string valueStr = OuterXml2.Substring(OuterXml2.IndexOf("value="), OuterXml2.IndexOf("unit=") - OuterXml2.IndexOf("value=")).Replace("value=", "").Replace("\"", "").Trim();
|
||
ap.PQ = valueStr;
|
||
}
|
||
|
||
if (OuterXml1.Contains("MDC_ECG_TIME_PD_QT") && !OuterXml1.Contains("MDC_ECG_TIME_PD_QTc"))
|
||
{
|
||
string valueStr = OuterXml2.Substring(OuterXml2.IndexOf("value="), OuterXml2.IndexOf("unit=") - OuterXml2.IndexOf("value=")).Replace("value=", "").Replace("\"", "").Trim();
|
||
ap.QT = valueStr;
|
||
}
|
||
|
||
if (OuterXml1.Contains("MDC_ECG_TIME_PD_QTc"))
|
||
{
|
||
string valueStr = OuterXml2.Substring(OuterXml2.IndexOf("value="), OuterXml2.IndexOf("unit=") - OuterXml2.IndexOf("value=")).Replace("value=", "").Replace("\"", "").Trim();
|
||
ap.QTc = valueStr;
|
||
}
|
||
|
||
if (OuterXml1.Contains("MDC_ECG_ANGLE_P_FRONT"))
|
||
{
|
||
string valueStr = OuterXml2.Substring(OuterXml2.IndexOf("value="), OuterXml2.IndexOf("unit=") - OuterXml2.IndexOf("value=")).Replace("value=", "").Replace("\"", "").Trim();
|
||
ap.P_degrees = valueStr;
|
||
}
|
||
|
||
if (OuterXml1.Contains("MDC_ECG_ANGLE_QRS_FRONT"))
|
||
{
|
||
string valueStr = OuterXml2.Substring(OuterXml2.IndexOf("value="), OuterXml2.IndexOf("unit=") - OuterXml2.IndexOf("value=")).Replace("value=", "").Replace("\"", "").Trim();
|
||
ap.QRS_degrees = valueStr;
|
||
}
|
||
|
||
if (OuterXml1.Contains("MDC_ECG_ANGLE_T_FRONT"))
|
||
{
|
||
string valueStr = OuterXml2.Substring(OuterXml2.IndexOf("value="), OuterXml2.IndexOf("unit=") - OuterXml2.IndexOf("value=")).Replace("value=", "").Replace("\"", "").Trim();
|
||
ap.T_degrees = valueStr;
|
||
}
|
||
|
||
if (OuterXml1.Contains("Biocare_RV5") && !OuterXml1.Contains("Biocare_RV5_PLUS_SV1"))
|
||
{
|
||
string valueStr = OuterXml2.Substring(OuterXml2.IndexOf("value="), OuterXml2.IndexOf("unit=") - OuterXml2.IndexOf("value=")).Replace("value=", "").Replace("\"", "").Trim();
|
||
ap.RV5 = valueStr;
|
||
}
|
||
|
||
if (OuterXml1.Contains("Biocare_SV1"))
|
||
{
|
||
string valueStr = OuterXml2.Substring(OuterXml2.IndexOf("value="), OuterXml2.IndexOf("unit=") - OuterXml2.IndexOf("value=")).Replace("value=", "").Replace("\"", "").Trim();
|
||
ap.SV1 = valueStr;
|
||
}
|
||
|
||
if (OuterXml1.Contains("Biocare_RV5_PLUS_SV1"))
|
||
{
|
||
string valueStr = OuterXml2.Substring(OuterXml2.IndexOf("value="), OuterXml2.IndexOf("unit=") - OuterXml2.IndexOf("value=")).Replace("value=", "").Replace("\"", "").Trim();
|
||
ap.RV5PLUSSV1 = valueStr;
|
||
}
|
||
|
||
if (OuterXml1.Contains("Biocare_PAPER_SPEED"))
|
||
{
|
||
string valueStr = OuterXml2.Substring(OuterXml2.IndexOf("value="), OuterXml2.IndexOf("unit=") - OuterXml2.IndexOf("value=")).Replace("value=", "").Replace("\"", "").Trim();
|
||
ap.paperSpeed = valueStr + "mm/s";
|
||
}
|
||
|
||
if (OuterXml1.Contains("Biocare_GAIN"))
|
||
{
|
||
string valueStr = OuterXml2.Substring(OuterXml2.IndexOf("value="), OuterXml2.IndexOf("unit=") - OuterXml2.IndexOf("value=")).Replace("value=", "").Replace("\"", "").Trim();
|
||
ap.Gain = valueStr + "mm/mV";
|
||
}
|
||
}
|
||
return ap;
|
||
}
|
||
catch (Exception ex) { }
|
||
|
||
return null;
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 根据HL7-ECG XML文件 生成心电图
|
||
/// </summary>
|
||
/// <param name="path">HL7-ECG XML 文件的路径</param>
|
||
/// <param name="reportInfo">心电图报告标题</param>
|
||
/// <returns></returns>
|
||
public string createEcgBmpByHL7XMLFile(string path, string reportInfo)
|
||
{
|
||
analysisParas ap = getAnalysisParas(path);
|
||
FileInfo fi = new FileInfo(path);
|
||
XmlDocument xmlDoc = new XmlDocument();
|
||
XmlReaderSettings settings = new XmlReaderSettings();
|
||
settings.IgnoreComments = true;//忽略文档里面的注释
|
||
XmlReader reader = XmlReader.Create(path, settings);
|
||
xmlDoc.Load(reader);
|
||
XmlNodeList xn = xmlDoc.ChildNodes;
|
||
XmlNodeList xnList = xmlDoc.DocumentElement.GetElementsByTagName("digits");
|
||
Dictionary<int, List<float>> EcgTable = new Dictionary<int, List<float>>();
|
||
int leadDataIndex = 0;
|
||
for (int i = 0; i < 12; i++)
|
||
{
|
||
string[] ecgDataArray = new string[xnList.Item(leadDataIndex + i).InnerText.Split(' ').Length];
|
||
ecgDataArray = xnList.Item(leadDataIndex + i).InnerText.Split(' ');
|
||
List<float> ecg_List = new List<float>();
|
||
for (int b = 0; b < ecgDataArray.Length; b++)
|
||
if (!string.IsNullOrEmpty(ecgDataArray[b]))
|
||
ecg_List.Add(float.Parse(ecgDataArray[b]) / 9);
|
||
EcgTable.Add(i, ecg_List);
|
||
}
|
||
EcgDataDraw_New EDDN = new EcgDataDraw_New();
|
||
var btmp = new Bitmap(3319, 2357);
|
||
Graphics Ecg_Graphics = Graphics.FromImage(btmp);
|
||
List<int> leadInfo = new List<int>();
|
||
for (int i = 0; i < 12; i++)
|
||
leadInfo.Add(i);
|
||
EDDN.InitEcgParameter(btmp, 12, EcgTable, 300, leadInfo);//初始化
|
||
EDDN.Draw_EcgBackGroundGrid(500);//画背景网格
|
||
EDDN.Draw_EcgWave(500, 0, 0);//画波形
|
||
EDDN.Draw_analysisParas(ap);//画患者信息和分析参数
|
||
EDDN.Draw_CalibrationVoltage_And_LeadName();//画定标电压和导联名称
|
||
EDDN.Draw_ReportHeadInfo(reportInfo, "", "");
|
||
//string bmpPath = fi.DirectoryName + @"\EcgDataFiles\" + reportInfo + ".jpg";
|
||
// string RotateEcgDataFilesPath = fi.DirectoryName + @"\RotateEcgDataFiles\" + reportInfo+ ".jpg";
|
||
//string xmlPath = fi.DirectoryName + @"\XmlDataFiles\" + reportInfo + ".xml";
|
||
|
||
string ecgBmpPath = fi.DirectoryName + @"\" + ap.patientName + "[" + Guid.NewGuid().ToString() + "].jpg";
|
||
btmp.Save(ecgBmpPath, ImageFormat.Jpeg);
|
||
//btmp.RotateFlip(RotateFlipType.Rotate90FlipNone);//顺时针旋转90°
|
||
//btmp.Save(RotateEcgDataFilesPath, ImageFormat.Jpeg);
|
||
btmp.Dispose();
|
||
reader.Close();
|
||
// fi.CopyTo(xmlPath, true);
|
||
//string returnStr = FtpHelper.FileUpLoad(bmpPath, ConfigurationManager.AppSettings["path1"], reportInfo + ".jpg");//上传 png文件
|
||
// textBox2.AppendText(bmpPath + "\r\n" + reportInfo + ".jpg" + "\r\n FTP:" + returnStr + "\r\n"); // FtpHelper.FileUpLoad(xmlPath, ConfigurationManager.AppSettings["path1"], reportInfo.Split('_')[0] + ".xml");//上传 xml文件
|
||
//dataSubmit(reportInfo);//提交数据
|
||
//SqliteOptions_sql.CreateInstance().SqliteAdd("INSERT INTO [dbo].[tb_Pecg] ([ID],[medicalSN],[patientName],[sex],[birthday],[createDate],[ecgFilePath]) VALUES ('" + Guid.NewGuid().ToString() + "','" + reportInfo.Split('_')[0] + "','" + reportInfo.Split('_')[1] + "','" + reportInfo.Split('_')[2] + "','" + birthday + "','" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "','" + (reportInfo.Split('_')[0] + ".jpg") + "')");
|
||
//fi.Delete();
|
||
//textBox2.AppendText(label1.Text + "\r\n");
|
||
//label1.Text = string.Empty;
|
||
return ecgBmpPath;
|
||
}
|
||
|
||
|
||
}
|
||
}
|