sopen_hl7aecg.c
来自「c++编写的用于生物信号处理的软件库」· C语言 代码 · 共 639 行 · 第 1/2 页
C
639 行
/* $Id: sopen_hl7aecg.c,v 1.17 2008/03/14 08:30:43 schloegl Exp $ Copyright (C) 2006,2007 Alois Schloegl <a.schloegl@ieee.org> Copyright (C) 2007 Elias Apostolopoulos This file is part of the "BioSig for C/C++" repository (biosig4c++) at http://biosig.sf.net/ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. */#include <stdio.h> // system includes#include <vector>#include <string>#include <sstream>#include "../biosig-dev.h"#include "../XMLParser/tinyxml.h"#include "../XMLParser/Tokenizer.h"int sopen_HL7aECG_read(HDRTYPE* hdr){/* this function is a stub or placeholder and need to be defined in order to be useful. It will be called by the function SOPEN in "biosig.c" Input: char* Header // contains the file content Output: HDRTYPE *hdr // defines the HDR structure accoring to "biosig.h"*/ char tmp[80]; TiXmlDocument doc(hdr->FileName); if(doc.LoadFile()){ TiXmlHandle hDoc(&doc); TiXmlHandle aECG = hDoc.FirstChild("AnnotatedECG"); if(aECG.Element()){ char *strtmp = strdup(aECG.FirstChild("id").Element()->Attribute("root")); size_t len = strlen(strtmp); if (len>MAX_LENGTH_RID) fprintf(stdout,"Warning HL7aECG(read): length of Recording ID exceeds maximum length %i>%i\n",len,MAX_LENGTH_PID); strncpy(hdr->ID.Recording,strtmp,min(len,MAX_LENGTH_RID)); free(strtmp); TiXmlHandle effectiveTime = aECG.FirstChild("effectiveTime"); char *T0 = NULL; if(effectiveTime.FirstChild("low").Element()) T0 = (char *)effectiveTime.FirstChild("low").Element()->Attribute("value"); else if(effectiveTime.FirstChild("center").Element()) T0 = (char *)effectiveTime.FirstChild("center").Element()->Attribute("value"); struct tm *t0 = (struct tm *)malloc(sizeof(struct tm)); T0[14] = '\0'; // ### ?FIXME?: compensate local time and DST in mktime used in tm_time2gdf_time below t0->tm_sec = atoi(T0+12)-timezone; T0[12] = '\0'; t0->tm_min = atoi(T0+10); T0[10] = '\0'; t0->tm_hour = atoi(T0+8); T0[8] = '\0'; t0->tm_mday = atoi(T0+6); T0[6] = '\0'; t0->tm_mon = atoi(T0+4)-1; T0[4] = '\0'; t0->tm_year = atoi(T0)-1900;#ifndef __sparc__ t0->tm_gmtoff = 0;#endif t0->tm_isdst = -1; hdr->T0 = tm_time2gdf_time(t0); TiXmlHandle demographic = aECG.FirstChild("componentOf").FirstChild("timepointEvent").FirstChild("componentOf").FirstChild("subjectAssignment").FirstChild("subject").FirstChild("trialSubject"); TiXmlElement *id = demographic.FirstChild("id").Element(); if(id) { const char* tmpstr = id->Attribute("extension"); size_t len = strlen(tmpstr); if (len>MAX_LENGTH_PID) fprintf(stdout,"Warning HL7aECG(read): length of Patient Id exceeds maximum length %i>%i\n",len,MAX_LENGTH_PID); strncpy(hdr->Patient.Id,tmpstr,MAX_LENGTH_PID); } if (!hdr->FLAG.ANONYMOUS) { demographic = demographic.FirstChild("subjectDemographicPerson"); TiXmlElement *name = demographic.FirstChild("name").Element(); if (name) { size_t len = strlen(name->GetText()); if (len>MAX_LENGTH_NAME) fprintf(stdout,"Warning HL7aECG(read): length of Patient Name exceeds maximum length %i>%i\n",len,MAX_LENGTH_PID); strncpy(hdr->Patient.Name, name->GetText(), MAX_LENGTH_NAME); } else fprintf(stderr,"Warning: Patient Name could not be read.\n"); } /* non-standard fields height and weight */ TiXmlElement *weight = demographic.FirstChild("weight").Element(); if (weight) { uint16_t code = PhysDimCode(strcpy(tmp,weight->Attribute("unit"))); if ((code & 0xFFE0) != 1728) fprintf(stderr,"Warning: incorrect weight unit (%s)\n",weight->Attribute("unit")); else // convert to kilogram hdr->Patient.Weight = uint8_t(atof(weight->Attribute("value"))*PhysDimScale(code)*1e-3); } TiXmlElement *height = demographic.FirstChild("height").Element(); if (height) { uint16_t code = PhysDimCode(strcpy(tmp,height->Attribute("unit"))); if ((code & 0xFFE0) != 1280) fprintf(stderr,"Warning: incorrect height unit (%s) %i \n",height->Attribute("unit"),code); else // convert to centimeter hdr->Patient.Height = uint8_t(atof(height->Attribute("value"))*PhysDimScale(code)*1e+2); } TiXmlElement *birthday = demographic.FirstChild("birthTime").Element(); if(birthday){ T0 = (char *)birthday->Attribute("value"); if (T0==NULL) T0=(char *)birthday->GetText(); // workaround for reading two different formats } if (T0==NULL) ; else if (strlen(T0)>14) { T0[14] = '\0'; t0->tm_sec = atoi(T0+12); T0[12] = '\0'; t0->tm_min = atoi(T0+10); T0[10] = '\0'; t0->tm_hour = atoi(T0+8); T0[8] = '\0'; t0->tm_mday = atoi(T0+6); T0[6] = '\0'; t0->tm_mon = atoi(T0+4)-1; T0[4] = '\0'; t0->tm_year = atoi(T0)-1900; hdr->Patient.Birthday = tm_time2gdf_time(t0); }// else// fprintf(stderr,"Error: birthday\n"); TiXmlElement *sex = demographic.FirstChild("administrativeGenderCode").Element(); if(sex){ if (sex->Attribute("code")==NULL) hdr->Patient.Sex = 0; else if(!strcmp(sex->Attribute("code"),"F")) hdr->Patient.Sex = 2; else if(!strcmp(sex->Attribute("code"),"M")) hdr->Patient.Sex = 1; else hdr->Patient.Sex = 0; }else{ hdr->Patient.Sex = 0; } int LowPass=0, HighPass=0, Notch=0; TiXmlHandle channels = aECG.FirstChild("component").FirstChild("series").FirstChild("component").FirstChild("sequenceSet"); TiXmlHandle variables = aECG.FirstChild("component").FirstChild("series"); for(TiXmlElement *tmpvar = variables.FirstChild("controlVariable").Element(); tmpvar; tmpvar = tmpvar->NextSiblingElement("controlVariable")){ if(!strcmp(tmpvar->FirstChildElement("controlVariable")->FirstChildElement("code")->Attribute("code"), "MDC_ATTR_FILTER_NOTCH")) Notch = atoi(tmpvar->FirstChildElement("controlVariable")->FirstChildElement("component")->FirstChildElement("controlVariable")->FirstChildElement("value")->Attribute("value")); else if(!strcmp(tmpvar->FirstChildElement("controlVariable")->FirstChildElement("code")->Attribute("code"), "MDC_ATTR_FILTER_LOW_PASS")) LowPass = atoi(tmpvar->FirstChildElement("controlVariable")->FirstChildElement("component")->FirstChildElement("controlVariable")->FirstChildElement("value")->Attribute("value")); else if(!strcmp(tmpvar->FirstChildElement("controlVariable")->FirstChildElement("code")->Attribute("code"), "MDC_ATTR_FILTER_HIGH_PASS")) HighPass = atoi(tmpvar->FirstChildElement("controlVariable")->FirstChildElement("component")->FirstChildElement("controlVariable")->FirstChildElement("value")->Attribute("value")); } hdr->NRec = 1; hdr->SPR = 1; hdr->AS.rawdata = (uint8_t *)malloc(hdr->SPR); int32_t *data; hdr->SampleRate = atof(channels.FirstChild("component").FirstChild("sequence").FirstChild("value").FirstChild("increment").Element()->Attribute("value")); TiXmlHandle channel = channels.Child("component", 1).FirstChild("sequence"); for(hdr->NS = 0; channel.Element(); ++(hdr->NS), channel = channels.Child("component", hdr->NS+1).FirstChild("sequence")); hdr->CHANNEL = (CHANNEL_TYPE*) calloc(hdr->NS,sizeof(CHANNEL_TYPE)); channel = channels.Child("component", 1).FirstChild("sequence"); for(int i = 0; channel.Element(); ++i, channel = channels.Child("component", i+1).FirstChild("sequence")){ const char *code = channel.FirstChild("code").Element()->Attribute("code"); strncpy(hdr->CHANNEL[i].Label,code,min(40,MAX_LENGTH_LABEL)); hdr->CHANNEL[i].Transducer[0] = '\0'; hdr->CHANNEL[i].GDFTYP = 5; // int32 std::vector<std::string> vector; stringtokenizer(vector, channel.FirstChild("value").FirstChild("digits").Element()->GetText()); hdr->CHANNEL[i].SPR = vector.size(); if (i==0) { hdr->SPR = hdr->CHANNEL[i].SPR; hdr->AS.rawdata = (uint8_t *)realloc(hdr->AS.rawdata, 4*(i+1)*hdr->NS*hdr->SPR*hdr->NRec); } else if (hdr->SPR != hdr->CHANNEL[i].SPR) { fprintf(stderr,"Error: number of samples %i of #%i differ from %i in #0.\n",hdr->CHANNEL[i].SPR,i+1,hdr->SPR,1); exit(-5); } /* read data samples */ data = (int32_t*)(hdr->AS.rawdata + 4*i*(hdr->SPR)); for(unsigned int j=0; j<hdr->SPR; ++j) { data[j] = atoi(vector[j].c_str()); /* get Min/Max */ if(data[j] > hdr->CHANNEL[i].DigMax) { hdr->CHANNEL[i].DigMax = data[j]; } if(data[j] < hdr->CHANNEL[i].DigMin){ hdr->CHANNEL[i].DigMin = data[j]; } } /* scaling factors */ hdr->CHANNEL[i].Cal = atof(channel.FirstChild("value").FirstChild("scale").Element()->Attribute("value")); hdr->CHANNEL[i].Off = atof(channel.FirstChild("value").FirstChild("origin").Element()->Attribute("value")); hdr->CHANNEL[i].DigMax += 1; hdr->CHANNEL[i].DigMin -= 1; hdr->CHANNEL[i].PhysMax = hdr->CHANNEL[i].DigMax*hdr->CHANNEL[i].Cal + hdr->CHANNEL[i].Off; hdr->CHANNEL[i].PhysMin = hdr->CHANNEL[i].DigMin*hdr->CHANNEL[i].Cal + hdr->CHANNEL[i].Off; /* Physical units */ strncpy(tmp, channel.FirstChild("value").FirstChild("origin").Element()->Attribute("unit"),20); hdr->CHANNEL[i].PhysDimCode = PhysDimCode(tmp); hdr->CHANNEL[i].LowPass = LowPass; hdr->CHANNEL[i].HighPass = HighPass; hdr->CHANNEL[i].Notch = Notch;// hdr->CHANNEL[i].XYZ[0] = l_endian_f32( *(float*) (Header2+ 4*k + 224*hdr->NS) );// hdr->CHANNEL[i].XYZ[1] = l_endian_f32( *(float*) (Header2+ 4*k + 228*hdr->NS) );// hdr->CHANNEL[i].XYZ[2] = l_endian_f32( *(float*) (Header2+ 4*k + 232*hdr->NS) );// //memcpy(&hdr->CHANNEL[k].XYZ,Header2 + 4*k + 224*hdr->NS,12);// hdr->CHANNEL[i].Impedance= ldexp(1.0, (uint8_t)Header2[k + 236*hdr->NS]/8);// hdr->CHANNEL[i].Impedance = INF;// for(int k1=0; k1<3; hdr->CHANNEL[index].XYZ[k1++] = 0.0); }// hdr2ascii(hdr,stdout,2); if (VERBOSE_LEVEL>8) fprintf(stdout,"[320] \n"); hdr->SampleRate *= hdr->SPR; hdr->SampleRate = hdr->SPR/hdr->SampleRate; hdr->FLAG.OVERFLOWDETECTION = 0; }else{ fprintf(stderr, "%s : failed to parse (2)\n", hdr->FileName); } } else fprintf(stderr, "%s : failed to parse (1)\n", hdr->FileName); return(0);};int sopen_HL7aECG_write(HDRTYPE* hdr){ size_t k; for (k=0; k<hdr->NS; k++) { hdr->CHANNEL[k].GDFTYP = 5; //int32 } hdr->SPR *= hdr->NRec; hdr->NRec = 1; hdr->FILE.OPEN=2; return(0);};int sclose_HL7aECG_write(HDRTYPE* hdr){/* this function is a stub or placeholder and need to be defined in order to be useful. It will be called by the function SOPEN in "biosig.c" Input: HDR structure Output: char* HDR.AS.Header // contains the content which will be written to the file in SOPEN*/ char tmp[80]; TiXmlDocument doc; TiXmlDeclaration* decl = new TiXmlDeclaration("1.0", "UTF-8", ""); doc.LinkEndChild(decl); TiXmlElement *root = new TiXmlElement("AnnotatedECG"); root->SetAttribute("xmlns", "urn:hl7-org:v3"); root->SetAttribute("xmlns:voc", "urn:hl7-org:v3/voc"); root->SetAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); root->SetAttribute("xsi:schemaLocation", "urn:hl7-org:v3/HL7/aECG/2003-12/schema/PORT_MT020001.xsd"); root->SetAttribute("classCode", "OBS"); root->SetAttribute("moodCode", "EVN"); doc.LinkEndChild(root); TiXmlElement *rootid = new TiXmlElement("id"); rootid->SetAttribute("root", strdup(hdr->ID.Recording)); root->LinkEndChild(rootid); TiXmlElement *rootCode = new TiXmlElement("code"); rootCode->SetAttribute("code", "93000"); rootCode->SetAttribute("codeSystem", "2.16.840.1.113883.6.12"); rootCode->SetAttribute("codeSystemName", "CPT-4"); root->LinkEndChild(rootCode); char timelow[19], timehigh[19]; time_t T0 = gdf_time2t_time(hdr->T0); struct tm *t0 = gmtime(&T0);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?