XML annotations can be created by hand but the process is prone to error. The creation of XML annotations is greatly facilitated if the programming language allows handling this way of encoding. A nice tutorial about the use of XML with Java can be found in Sun's site.
In a companion tutorial it was discussed the translation from Physionet annotations to EDF XML annotations.
We are going to list the code to do the work. Since it is outside of the scope of this tutorial the creation of XML documents, it will not be described. It was conceived as an example of how to implement small programs (using line options) in Java. These programs are able to do specific tasks such as the applications used in Physionet.
This is the code included in the file called ann2xml.java
We are going to run the program. It is a very long code but most of it is dedicated to the creation of the interface with the user. Now we can try with the annotations included with the record 100s included in WFDB Software Package.
We begin by creating an ASCII file with the annotations
The first ten lines of the annotation file are shown. Now we compile and run the program
We can create an XML document but we are going to create a file that could serve as the basis of an EDF+ file
This is the listing of the first 10 lines of a file ready to be included as EDF+ annotations. Although not represented in the listing, each annotation is wrapped by character 20 and at the end of each annotation a character 0 is included.
This chapter was included only to illustrate the creation of an XML document and the creation of a stand-alone application ready to be used. It can be easily tailored to adapt to other needs.
import java.io.*;
import org.w3c.dom.*;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;
import javax.xml.transform.dom.*;
class ann2xml {
//This program converts an ASCII WFDB annotation
// file in an XML file
static boolean flag_p = false;
static String[] input ;
public static void main(String[] args)
throws IOException,
ParserConfigurationException,
TransformerException {
// adapted from WFDB
char option = ' ';
String filename = "";
if (args.length == 0){
System.out.println(HelpString());
System.exit(0);
}
for (int i=0; i<args.length; i++){
if (args[i].startsWith("-")){
if(args[i].length() > 2) {
System.out.println("Incorrect option: "+args[i]);
System.exit(0);
}
else{
option = args[i].charAt(1);
}
switch (option){
case 'h':
System.out.println(HelpString());
System.exit(0);
case 'p':
flag_p = true;
break;
case 'i':
if (i+1 > args.length-1){
System.out.println(HelpString());
System.exit(0);
}
else{
filename = args[i+1];
break;
}
}
}
}
convert(filename);
}
static private void convert(String filename)
throws IOException,
ParserConfigurationException,
TransformerException {
String line="";
String[] fieldInLine ;
String str="";
// Opening of the file
FileInputStream fis = new FileInputStream(filename);
InputStreamReader isr = new InputStreamReader(fis);
LineNumberReader lnr = new LineNumberReader(isr);
// Creation of an XML document
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
DOMImplementation di = db.getDOMImplementation();
Document doc = di.createDocument(null, "WFDB", null);
Element root = doc.getDocumentElement();
// This element will change in each line
Element el = null;
// The same element to create EDF+ annotations
Element el_edf = null;
while(true){
line = lnr.readLine();
// detection of EOF
if (line == null) break;
fieldInLine = line.split("\\s+");
el = doc.createElement("WFDBann");
el.setAttribute("time",fieldInLine[0]);
el.setAttribute("mnem",fieldInLine[3]);
el.setAttribute("subtyp",fieldInLine[4]);
el.setAttribute("chan",fieldInLine[5]);
el.setAttribute("num",fieldInLine[6]);
root.appendChild(el);
if (flag_p){
el_edf = doc.createElement("WFDBann");
el_edf.setAttribute("mnem",fieldInLine[3]);
el_edf.setAttribute("subtyp",fieldInLine[4]);
el_edf.setAttribute("chan",fieldInLine[5]);
el_edf.setAttribute("num",fieldInLine[6]);
str = "+" + fieldInLine[0];
str = str + (char) 20 + el_edf + (char) 20 + (char) 0;
System.out.println(str);
}
}
// output of the XML document
DOMSource ds = new DOMSource(doc);
StreamResult sr = new StreamResult(new File(filename+".xml"));
TransformerFactory tf = TransformerFactory.newInstance();
Transformer trans = tf.newTransformer();
trans.transform(ds, sr);
}
static private String HelpString(){
String str = "";
str += "usage: java ann2xml [options...] \n";
str += "where OPTIONS may include: \n";
str += " -h print this usage summary \n";
str += " -p output in the form defined in EDF+ \n";
str += " -i FILE file to be translated \n";
str += "This program reads an ASCII annotation file and \n";
str += "converts to XML. Notice that the file must had \n";
str += "been obtained by using rdann with option -x in \n";
str += "this way: \n";
str += "Step 1: rdann -r 100s -a atr -x > FILE \n";
str += "Step 2: java ann2xml -i FILE \n";
str += "The result is stored in FILE.xml \n";
str += "(option -p also prints EDF+ notes in stdout) ";
return str;
}
}
[j@localhost CreatingXML]$ rdann -r 100s -x -a atr > ann_base
[j@localhost CreatingXML]$ cat ann_base | head -n 10
0.050 0.00083 0.0000139 + 0 0 0 (N
0.214 0.00356 0.0000594 N 0 0 0
1.028 0.01713 0.0002855 N 0 0 0
1.839 0.03065 0.0005108 N 0 0 0
2.628 0.04380 0.0007299 N 0 0 0
3.419 0.05699 0.0009498 N 0 0 0
4.208 0.07014 0.0011690 N 0 0 0
5.025 0.08375 0.0013958 N 0 0 0
5.678 0.09463 0.0015772 A 0 0 0
6.672 0.11120 0.0018534 N 0 0 0
[j@localhost CreatingXML]$ javac ann2xml.java
[j@localhost CreatingXML]$ java ann2xml
usage: java ann2xml [options...]
where OPTIONS may include:
-h print this usage summary
-p output in the form defined in EDF+
-i FILE file to be translated
This program reads an ASCII annotation file and
converts to XML. Notice that the file must had
been obtained by using rdann with option -x in
this way:
Step 1: rdann -r 100s -a atr -x > FILE
Step 2: java ann2xml -i FILE
The result is stored in FILE.xml
(option -p also prints EDF+ notes in stdout)
[j@localhost CreatingXML]$ java ann2xml -i ann_base -p > ann_base.edf_xml
[j@localhost CreatingXML]$ cat ann_base.edf_xml | head -n 10
+0.050<WFDBann mnem="+" subtyp="0" chan="0" num="0" />
+0.214<WFDBann mnem="N" subtyp="0" chan="0" num="0" />
+1.028<WFDBann mnem="N" subtyp="0" chan="0" num="0" />
+1.839<WFDBann mnem="N" subtyp="0" chan="0" num="0" />
+2.628<WFDBann mnem="N" subtyp="0" chan="0" num="0" />
+3.419<WFDBann mnem="N" subtyp="0" chan="0" num="0" />
+4.208<WFDBann mnem="N" subtyp="0" chan="0" num="0" />
+5.025<WFDBann mnem="N" subtyp="0" chan="0" num="0" />
+5.678<WFDBann mnem="A" subtyp="0" chan="0" num="0" />
+6.672<WFDBann mnem="N" subtyp="0" chan="0" num="0" />
Next: Summary
Up: Coding a sin wave
Previous: Viewing the result
Contents
j
2003-05-28