Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
  
  package org.apache.ctakes.temporal.eval;
  
  import java.io.File;
  import java.net.URI;
  import java.util.HashMap;
  import java.util.HashSet;
  import java.util.List;
  import java.util.Map;
  import java.util.Set;
  
  
 import  org.cleartk.util.ViewUriUtil;
 import  org.cleartk.util.ae.UriToDocumentTextAnnotator;
 import  org.cleartk.util.cr.UriCollectionReader;
 
 
 public abstract class Evaluation_ImplBase<STATISTICS_TYPE> extends
 org.cleartk.eval.Evaluation_ImplBase<Integer, STATISTICS_TYPE> {
 
 	private static Logger LOGGER = Logger.getLogger(Evaluation_ImplBase.class);
 
 	public static final String GOLD_VIEW_NAME = "GoldView";
 
 	public enum XMLFormat { Knowtator, Anafora, I2B2 }
 
 	public enum Subcorpus { Colon, Brain}
 	
   public static interface Options {
 
 		@Option(longName = "text", defaultToNull = true)
 
 		@Option(longName = "xml")
 		public File getXMLDirectory();
 
 		@Option(longName = "format", defaultValue="Anafora")
 		public XMLFormat getXMLFormat();
 
 		@Option(longName = "subcorpus", defaultValue="Colon")
 		public Subcorpus getSubcorpus();
 
 		@Option(longName = "xmi")
 		public File getXMIDirectory();
 
 		@Option(longName = "patients")
 
 		@Option(longName = "train-remainders", defaultValue = "0-2")
 
 		@Option(longName = "dev-remainders", defaultValue = "3")
 
 		@Option(longName = "test-remainders", defaultValue = "4-5")
 
 		@Option(longName = "treebank", defaultToNull=true)
 
 		public boolean getUseGoldTrees();
 
 		public boolean getGrid();
 
 		public boolean getPrintErrors();
 
 		public boolean getPrintOverlappingSpans();
 
 		public boolean getTest();
 
 		@Option(longName = "kernelParams", defaultToNull=true)
 		public String getKernelParams();
 
 		@Option(defaultToNull=true)
 		public String getI2B2Output();
 	}
 
     public static List<IntegergetTrainItems(Options options) {
         List<IntegerpatientSets = options.getPatients().getList();
         List<IntegertrainItems = THYMEData.getPatientSets(patientSetsoptions.getTrainRemainders().getList());
         if (options.getTest()) {
             trainItems.addAll(THYMEData.getPatientSets(patientSetsoptions.getDevRemainders().getList()));
         }
         return trainItems;
     }
 
     public static List<IntegergetTestItems(Options options) {
         List<IntegerpatientSets = options.getPatients().getList();
         List<IntegertestItems;
         if (options.getTest()) {
             testItems = THYMEData.getPatientSets(patientSetsoptions.getTestRemainders().getList());
         } else {
             testItems = THYMEData.getPatientSets(patientSetsoptions.getDevRemainders().getList());
         }
         return testItems;
     }
 
     protected File rawTextDirectory;
 
 	protected File xmlDirectory;
 
 	protected XMLFormat xmlFormat;
 
 	protected Subcorpus subcorpus;
 	
 	protected File xmiDirectory;
 
 	private boolean xmiExists;
 
 	protected File treebankDirectory;
 
 	protected boolean printErrors = false;
 
 	protected boolean printOverlapping = false;
 
 	protected String i2b2Output = null;
 
 	protected String[] kernelParams;
 
 			File baseDirectory,
 			File rawTextDirectory,
 			File xmlDirectory,
 			XMLFormat xmlFormat,
 			Subcorpus subcorpus,
 			File xmiDirectory,
 			File treebankDirectory) {
 		super(baseDirectory);
 		this. = rawTextDirectory;
 		this. = xmlDirectory;
 		this. = xmlFormat;
 		this. = subcorpus;
 		this. = xmiDirectory;
 		this. = this..exists() && this..listFiles().length > 0;
 		this. = treebankDirectory;
 	}
 
 	public void setI2B2Output(String outDir){
 		 = outDir;
 	}
 
 	public void prepareXMIsFor(List<IntegerpatientSetsthrows Exception {
 		boolean needsXMIs = false;
 		for (File textFile : this.getFilesFor(patientSets)) {
 			if (!getXMIFile(this.textFile).exists()) {
 				needsXMIs = true;
 				break;
 			}
 		}
 		if (needsXMIs) {
 			CollectionReader reader = this.getCollectionReader(patientSets);
 			SimplePipeline.runPipeline(readerengine);
 		}
 		this. = true;
 	}
 
 	private List<FilegetFilesFor(List<IntegerpatientSetsthrows FileNotFoundException {
 		List<Filefiles = new ArrayList<>();
 		if (this. == .) {
 			Set<Stringids = new HashSet<>();
 			for (Integer set : patientSets) {
 			  if(this. == .){
 			    ids.add(String.format("ID%03d"set));
 			  }else{
 			    ids.add(String.format("doc%04d"set));
 			  }
 			}
 			int filePrefixLen = 5; // Colon: "ID\d{3}"
 			if(this. == .){
 			  filePrefixLen = 7; // Brain: "doc\d{4}"
 			}
 			for (String section : .){
 				File xmlSubdir = new File(this.section);
 				for (File dir : xmlSubdir.listFiles()) {
 					if (dir.isDirectory()) {
 						if (ids.contains(dir.getName().substring(0, filePrefixLen))) {
 							File file = new File(dirdir.getName());
 							if (file.exists()) {
 								files.add(file);
 							} else {
 								.warn("Missing note: " + file);
 							}
 						}
 					}
 				}
 			}
 		} else if(this. == .) {
 			File trainDir = new File(this."training");
 			File testDir = new File(this."test");
 			for (Integer pt : patientSets){
 				File xmlTrain = new File(trainDirpt+".xml");
 				File train = new File(trainDirpt+".xml.txt");
 				if(train.exists()){
 					if(xmlTrain.exists()){
 						files.add(train);
 					}else{
 						..println("Text file in training has no corresponding xml -- skipping: " + train);
 					}
 				}
 				File xmlTest = new File(testDirpt+".xml");
 				File test = new File(testDirpt+".xml.txt");
 				if(xmlTest.exists()){
 					if(test.exists()){
 						files.add(test);
 					}else{
 						throw new FileNotFoundException("Could not find the test text file -- for cTAKES usage you must copy the text files into the xml directory for the test set.");
 					}
 				}
 				assert !(train.exists() && test.exists());
 			}
 		}	else if == .) {
 			.warn("This is an old annotation format -- please upgrade to using anafora files.");
 			for (Integer set : patientSets) {
 				final int setNum = set;
 					public boolean accept(File dirString name) {
 						return name.contains(String.format("ID%03d"setNum));
 					}})) {
 					// skip hidden files like .svn
 					if (!file.isHidden()) {
 						files.add(file);
 					} 
 				}
 			}
 		} else {
 			.error("Unknown data format -- please specify Anafora, i2b2, or Knowtator format.");
 		}
 		return files;
 	}
 
 	protected CollectionReader getCollectionReader(List<IntegerpatientSetsthrows Exception {
 		return UriCollectionReader.getCollectionReaderFromFiles(this.getFilesFor(patientSets));
 	}
 
 		return this.
 	}
 
 		AggregateBuilder aggregateBuilder = new AggregateBuilder();
 		aggregateBuilder.add(UriToDocumentTextAnnotator.getDescription());
 		aggregateBuilder.add(AnalysisEngineFactory.createEngineDescription(
 				XMIReader.class,
 				this.));
 		return aggregateBuilder;
 	}
 
 			throws Exception {
 		AggregateBuilder aggregateBuilder = new AggregateBuilder();
 		aggregateBuilder.add(AnalysisEngineFactory.createEngineDescription(UriToDocumentTextAnnotatorCtakes.class));
 
 		// read manual annotations into gold view
 		aggregateBuilder.add(AnalysisEngineFactory.createEngineDescription(
 		aggregateBuilder.add(AnalysisEngineFactory.createEngineDescription(
 		switch (this.) {
 		case :
 			aggregateBuilder.add(
 					THYMEAnaforaXMLReader.getDescription(this.),
 			break;
 		case :
 			aggregateBuilder.add(
 					THYMEKnowtatorXMLReader.getDescription(this.),
 			break;
 		case :
 			aggregateBuilder.add(
 					I2B2TemporalXMLReader.getDescription(this.),
 			break;
 		}
 
 		// identify segments
 		aggregateBuilder.add(AnalysisEngineFactory.createEngineDescription(SegmentsFromBracketedSectionTagsAnnotator.class));
 
 		// identify sentences
 		aggregateBuilder.add(AnalysisEngineFactory.createEngineDescription(
 				"org/apache/ctakes/core/sentdetect/sd-med-model.zip"));
 		// identify tokens
 		aggregateBuilder.add(AnalysisEngineFactory.createEngineDescription(TokenizerAnnotatorPTB.class));
 		// merge some tokens
 		aggregateBuilder.add(AnalysisEngineFactory.createEngineDescription(ContextDependentTokenizerAnnotator.class));
 
 		// identify part-of-speech tags
 		aggregateBuilder.add(AnalysisEngineFactory.createEngineDescription(
 				POSTagger.class,
 				TypeSystemDescriptionFactory.createTypeSystemDescription(),
 				TypePrioritiesFactory.createTypePriorities(Segment.classSentence.classBaseToken.class),
 				"org/apache/ctakes/postagger/models/mayo-pos.zip"));
 
 		// identify chunks
 		aggregateBuilder.add(AnalysisEngineFactory.createEngineDescription(
 				Chunker.class,
 				FileLocator.locateFile("org/apache/ctakes/chunker/models/chunker-model.zip"),
 
 		// identify UMLS named entities
 
 		// adjust NP in NP NP to span both
 		aggregateBuilder.add(AnalysisEngineFactory.createEngineDescription(
 				new String[] { "NP""NP" },
 				1));
 		// adjust NP in NP PP NP to span all three
 		aggregateBuilder.add(AnalysisEngineFactory.createEngineDescription(
 				new String[] { "NP""PP""NP" },
 				2));
 		// add lookup windows for each NP
 		aggregateBuilder.add(AnalysisEngineFactory.createEngineDescription(CopyNPChunksToLookupWindowAnnotations.class));
 		// maximize lookup windows
 		aggregateBuilder.add(AnalysisEngineFactory.createEngineDescription(
 				"A_ObjectClass",
 				"B_ObjectClass",
 				"OverlapType",
 				"A_ENV_B",
 				"ActionType",
 				"DELETE",
 				"DeleteAction",
 				new String[] { "selector=B" }));
 		// add UMLS on top of lookup windows
     try {
       aggregateBuilder.add(AnalysisEngineFactory.createEngineDescription(DefaultJCasTermAnnotator.class,
           "org.apache.ctakes.typesystem.type.textspan.Sentence",
           ExternalResourceFactory.createExternalResourceDescription(
               FileResourceImpl.class,
               FileLocator.locateFile("org/apache/ctakes/dictionary/lookup/fast/cTakesHsql.xml"))
           ));
     } catch (FileNotFoundException e) {
       e.printStackTrace();
       throw new ResourceInitializationException(e);
     }
 
 		aggregateBuilder.add(LvgAnnotator.createAnnotatorDescription());
 
 		// add dependency parser
 		aggregateBuilder.add(ClearNLPDependencyParserAE.createAnnotatorDescription());
 		
 		// add semantic role labeler
 		aggregateBuilder.add(AnalysisEngineFactory.createEngineDescription(ClearNLPSemanticRoleLabelerAE.class));
 
 		// add gold standard parses to gold view, and adjust gold view to correct a few annotation mis-steps
 		if(this. != null){
 			aggregateBuilder.add(THYMETreebankReader.getDescription(this.));
 			aggregateBuilder.add(AnalysisEngineFactory.createEngineDescription(TimexAnnotationCorrector.class));
 		}else{
 			// add ctakes constituency parses to system view
 			aggregateBuilder.add(AnalysisEngineFactory.createEngineDescription(ConstituencyParser.class,
 					"org/apache/ctakes/constituency/parser/models/thyme.bin"));
 		}
 		// write out the CAS after all the above annotations
 		aggregateBuilder.add(AnalysisEngineFactory.createEngineDescription(
 				XMIWriter.class,
 				this.));
 
 		return aggregateBuilder;
 	}
 
 	public static <T extends AnnotationList<T> selectExact(JCas jCasClass<T> annotationClassSegment segment) {
 		List<T> annotations = Lists.newArrayList();
 		for (T annotation : JCasUtil.selectCovered(jCasannotationClasssegment)) {
 			if (annotation.getClass().equals(annotationClass)) {
 				annotations.add(annotation);
 			}
 		}
 		return annotations;
 	}
 
 
 		public void process(JCas jCasthrows AnalysisEngineProcessException {
 			for (Chunk chunk : JCasUtil.select(jCasChunk.class)) {
 				if (chunk.getChunkType().equals("NP")) {
 					new LookupWindowAnnotation(jCaschunk.getBegin(), chunk.getEnd()).addToIndexes();
 				}
 			}
 		}
 	}
 
 	public static class RemoveEnclosedLookupWindows extends JCasAnnotator_ImplBase {
 
 		public void process(JCas jCasthrows AnalysisEngineProcessException {
 			List<LookupWindowAnnotationlws = new ArrayList<>(JCasUtil.select(jCasLookupWindowAnnotation.class));
 			// we'll navigate backwards so that as we delete things we shorten the list from the back
 			for(int i = lws.size()-2; i >= 0; i--){
 				LookupWindowAnnotation lw1 = lws.get(i);
 				LookupWindowAnnotation lw2 = lws.get(i+1);
 				if(lw1.getBegin() <= lw2.getBegin() && lw1.getEnd() >= lw2.getEnd()){
 					/// lw1 envelops or encloses lw2
 					lws.remove(i+1);
 				}
 			}
 
 		}
 
 	}
 
 	public static class EntityMentionRemover extends JCasAnnotator_ImplBase {
 
 		public void process(JCas jCasthrows AnalysisEngineProcessException {
 			for (EntityMention mention : Lists.newArrayList(JCasUtil.select(jCasEntityMention.class))) {
 				mention.removeFromIndexes();
 			}
 		}
 	}
 
 	public static class EventMentionRemover extends JCasAnnotator_ImplBase {
 
 		public void process(JCas jCasthrows AnalysisEngineProcessException {
 			for (EventMention mention : Lists.newArrayList(JCasUtil.select(jCasEventMention.class))) {
 				mention.removeFromIndexes();
 			}
 		}
 	}
 
 	// replace this with SimpleSegmentWithTagsAnnotator if that code ever gets fixed
 		private static Pattern SECTION_PATTERN = Pattern.compile(
 				"(\\[start section id=\"?(.*?)\"?\\]).*?(\\[end section id=\"?(.*?)\"?\\])",
 
 		public void process(JCas jCasthrows AnalysisEngineProcessException {
 			boolean foundSections = false;
 			while (matcher.find()) {
 				Segment segment = new Segment(jCas);
 				segment.setBegin(matcher.start() + matcher.group(1).length());
 				segment.setEnd(matcher.end() - matcher.group(3).length());
 				segment.setId(matcher.group(2));
 				segment.addToIndexes();
 				foundSections = true;
 			}
 			if(!foundSections){
 				Segment segment = new Segment(jCas);
 				segment.setBegin(0);
 				segment.setEnd(jCas.getDocumentText().length());
 				segment.setId("SIMPLE_SEGMENT");
 				segment.addToIndexes();
 			}
 		}
 	}
 
 	static File getXMIFile(File xmiDirectoryFile textFile) {
 		return new File(xmiDirectorytextFile.getName() + ".xmi");
 	}
 
 	static File getXMIFile(File xmiDirectoryJCas jCasthrows AnalysisEngineProcessException {
 		return getXMIFile(xmiDirectorynew File(ViewUriUtil.getURI(jCas).getPath()));
 	}
 
 	public static class XMIWriter extends JCasAnnotator_ImplBase {
 
 		public static final String PARAM_XMI_DIRECTORY = "XMIDirectory";
 
 		@ConfigurationParameter(name = , mandatory = true)
 		private File xmiDirectory;
 
 		public void initialize(UimaContext contextthrows ResourceInitializationException {
 			super.initialize(context);
 			if (!this..exists()) {
 			}
 		}
 
 		public void process(JCas jCasthrows AnalysisEngineProcessException {
 			File xmiFile = getXMIFile(this.jCas);
 			try {
 				FileOutputStream outputStream = new FileOutputStream(xmiFile);
 				try {
 					XmiCasSerializer serializer = new XmiCasSerializer(jCas.getTypeSystem());
 					ContentHandler handler = new XMLSerializer(outputStreamfalse).getContentHandler();
 					serializer.serialize(jCas.getCas(), handler);
 				} finally {
 					outputStream.close();
 				}
 			} catch (SAXException e) {
 			} catch (IOException e) {
 			}
 		}
 	}
 
 	public static class XMIReader extends JCasAnnotator_ImplBase {
 
 		public static final String PARAM_XMI_DIRECTORY = "XMIDirectory";
 
 		@ConfigurationParameter(name = , mandatory = true)
 		private File xmiDirectory;
 
 		public void process(JCas jCasthrows AnalysisEngineProcessException {
 			File xmiFile = getXMIFile(this.jCas);
 			try {
 				FileInputStream inputStream = new FileInputStream(xmiFile);
 				try {
 					XmiCasDeserializer.deserialize(inputStreamjCas.getCas());
 				} finally {
 					inputStream.close();
 				}
 			} catch (SAXException e) {
 			} catch (IOException e) {
 			}
 		}
 	}
 
 	public static class TimexAnnotationCorrector extends JCasAnnotator_ImplBase {
 		public void process(JCas jCasthrows AnalysisEngineProcessException {
 			JCas goldViewsystemView;
 			try {
 				goldView = jCas.getView();
 				systemView = jCas.getView(.);
 			} catch (CASException e) {
 			}
 			for(TimeMention mention : JCasUtil.select(goldViewTimeMention.class)){
 				// for each time expression, get the treebank node with the same span.
 				List<TreebankNodenodes = JCasUtil.selectCovered(systemViewTreebankNode.classmention);
 				TreebankNode sameSpanNode = null;
 				for(TreebankNode node : nodes){
 					if(node.getBegin() == mention.getBegin() && node.getEnd() == mention.getEnd()){
 						sameSpanNode = node;
 						break;
 					}
 				}
 				if(sameSpanNode != null){
 					// look at node at the position of the timex3.
 					if(sameSpanNode.getNodeType().equals("PP")){
 						// if it is a PP it should be moved down to the NP
 						int numChildren = sameSpanNode.getChildren().size();
 						if(numChildren == 2 && sameSpanNode.getChildren(0).getNodeType().equals("IN") && sameSpanNode.getChildren(1).getNodeType().equals("NP")){
 							// move the time span to this node:
 							TreebankNode mentionNode = sameSpanNode.getChildren(numChildren-1);
 							mention.setBegin(mentionNode.getBegin());
 							mention.setEnd(mentionNode.getEnd());
 						}
 					}
 				}else{
 					// if there is no matching tree span, see if the DT to the left would help.
 					// now adjust for missing DT to the left
 					List<TerminalTreebankNodeprecedingPreterms = JCasUtil.selectPreceding(systemViewTerminalTreebankNode.classmention, 1);
 					if(precedingPreterms != null && precedingPreterms.size() == 1){
 						TerminalTreebankNode leftTerm = precedingPreterms.get(0);
 						if(leftTerm.getNodeType().equals("DT")){
 							// now see if adding this would make it match a tree
 							List<TreebankNodematchingNodes = JCasUtil.selectCovered(systemViewTreebankNode.classleftTerm.getBegin(), mention.getEnd());
 							for(TreebankNode node : matchingNodes){
 								if(node.getBegin() == leftTerm.getBegin() && node.getEnd() == mention.getEnd()){
 									sameSpanNode = node;
 									break;
 								}
 							}
 							if(sameSpanNode != null){
 								// adding the DT to the left of th emention made it match a tree:
 								..println("Adding DT: " + leftTerm.getCoveredText() + " to TIMEX: " + mention.getCoveredText());
 								mention.setBegin(leftTerm.getBegin());
 							}
 						}
 					}
 				}
 			}
 		}
 	}
 
 
 	public static class CopyFromGold extends JCasAnnotator_ImplBase {
 
 		public static AnalysisEngineDescription getDescription(Class<?>... classes)
 			return AnalysisEngineFactory.createEngineDescription(
 					CopyFromGold.class,
 					classes);
 		}
 
 		public static final String PARAM_ANNOTATION_CLASSES = "AnnotationClasses";
 
 		@ConfigurationParameter(name = , mandatory = true)
 		private Class<? extends TOP>[] annotationClasses;
 
 		public void process(JCas jCasthrows AnalysisEngineProcessException {
 			JCas goldViewsystemView;
 			try {
 				goldView = jCas.getView();
 				systemView = jCas.getView(.);
 			} catch (CASException e) {
 			}
 			for (Class<? extends TOPannotationClass : this.) {
 				for (TOP annotation : Lists.newArrayList(JCasUtil.select(systemViewannotationClass))) {
 					if (annotation.getClass().equals(annotationClass)) {
 						annotation.removeFromIndexes();
 					}
 				}
 			}
 			CasCopier copier = new CasCopier(goldView.getCas(), systemView.getCas());
 			for (Class<? extends TOPannotationClass : this.) {
 				for (TOP annotation : JCasUtil.select(goldViewannotationClass)) {
 					TOP copy = (TOPcopier.copyFs(annotation);
 					if (copy instanceof Annotation) {
 						copy.setFeatureValue(sofaFeaturesystemView.getSofa());
 					}
 					copy.addToIndexes(systemView);
 				}
 			}
 		}
 	}
 	
   /* 
    * The following class overrides a ClearTK utility annotator class for reading
    * a text file into a JCas. The code is copy/pasted so that one tiny modification
    * can be made for this corpus -- replace a single odd character (0xc) with a 
    * space since it trips up xml output.  
    */
   public static class UriToDocumentTextAnnotatorCtakes extends UriToDocumentTextAnnotator {
 
     @Override
     public void process(JCas jCasthrows AnalysisEngineProcessException {
       URI uri = ViewUriUtil.getURI(jCas);
       String content;
 
       try {
         content = CharStreams.toString(new InputStreamReader(uri.toURL().openStream()));
         content = content.replace((char) 0xc, ' ');
         jCas.setSofaDataString(content"text/plain");
       } catch (MalformedURLException e) {
         throw new AnalysisEngineProcessException(e);
       } catch (IOException e) {
         throw new AnalysisEngineProcessException(e);
       }
     }  
   }
 
 	public static class WriteI2B2XML extends JCasAnnotator_ImplBase {
 		public static final String PARAM_OUTPUT_DIR="PARAM_OUTPUT_DIR";
 		@ConfigurationParameter(mandatory=true,description="Output directory to write xml files to.",name=)
 		protected String outputDir;
 
 		public void process(JCas jcasthrows AnalysisEngineProcessException {
 			try {
 				// get the output file name from the input file name and output directory.
 				File outDir = new File();
 				if(!outDir.exists()) outDir.mkdirs();
 				File inFile = new File(ViewUriUtil.getURI(jcas));
 				String outFile = inFile.getName().replace(".txt""");
 
 				// build the xml
 				DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
 				DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
 				Document doc = docBuilder.newDocument();
 				Element rootElement = doc.createElement("ClinicalNarrativeTemporalAnnotation");
 				Element textElement = doc.createElement("TEXT");
 				Element tagsElement = doc.createElement("TAGS");
 				textElement.setTextContent(jcas.getDocumentText());
 				rootElement.appendChild(textElement);
 				rootElement.appendChild(tagsElement);
 				doc.appendChild(rootElement);
 
 				Map<IdentifiedAnnotation,StringargToId = new HashMap<>();
 				int id=0;
 				for(TimeMention timex : JCasUtil.select(jcasTimeMention.class)){
 					Element timexElement = doc.createElement("TIMEX3");
 					String timexID = "T"+idid++;
 					argToId.put(timextimexID);
 					timexElement.setAttribute("id"timexID);
 					timexElement.setAttribute("start", String.valueOf(timex.getBegin()+1));
 					timexElement.setAttribute("end", String.valueOf(timex.getEnd()+1));
 					timexElement.setAttribute("text"timex.getCoveredText());
 					timexElement.setAttribute("type""NA");
 					timexElement.setAttribute("val""NA");
 					timexElement.setAttribute("mod""NA");
 					tagsElement.appendChild(timexElement);
 				}
 
 				id = 0;
 				for(EventMention event : JCasUtil.select(jcasEventMention.class)){
 					if (event.getClass().equals(EventMention.class)) {
 						// this ensures we are only looking at THYME events and not ctakes-dictionary-lookup events
 						Element eventEl = doc.createElement("EVENT");
 						String eventID = "E"+id;  id++;
 						argToId.put(eventeventID);
 						eventEl.setAttribute("id"eventID);
 						eventEl.setAttribute("start", String.valueOf(event.getBegin()+1));
 						eventEl.setAttribute("end", String.valueOf(event.getEnd()+1));
 						eventEl.setAttribute("text"event.getCoveredText());
 						eventEl.setAttribute("modality""NA");
 						eventEl.setAttribute("polarity""NA");
 						eventEl.setAttribute("type""NA");
 						tagsElement.appendChild(eventEl);
 					}
 				}
 
 				id = 0;
 				for(TemporalTextRelation rel : JCasUtil.select(jcasTemporalTextRelation.class)){
 					Element linkEl = doc.createElement("TLINK");
 					String linkID = "TL"+idid++;
 					linkEl.setAttribute("id"linkID);
 					Annotation arg1 = rel.getArg1().getArgument();
 					linkEl.setAttribute("fromID"argToId.get(arg1));
 					linkEl.setAttribute("fromText"arg1.getCoveredText());
 					Annotation arg2 = rel.getArg2().getArgument();
 					if(arg2!=null){
 						linkEl.setAttribute("toID"argToId.get(arg2));
 						linkEl.setAttribute("toText"arg2.getCoveredText());
 					}else{
 						linkEl.setAttribute("toID""Discharge");
 						linkEl.setAttribute("toText""Discharge");
 					}
 					linkEl.setAttribute("type"rel.getCategory());
 					tagsElement.appendChild(linkEl);
 				}
 
 				// boilerplate xml-writing code:
 				TransformerFactory transformerFactory = TransformerFactory.newInstance();
 				Transformer transformer = transformerFactory.newTransformer();
 				transformer.setOutputProperty(."yes");
 				transformer.setOutputProperty(."xml");
 				DOMSource source = new DOMSource(doc);
 				StreamResult result = new StreamResult(new File(outFile));
 				transformer.transform(sourceresult);
 			} catch (ParserConfigurationException e) {
 			} catch (TransformerException e) {
 			}
 
 		}
 
 	}
 	
 	public static class WriteAnaforaXML extends JCasAnnotator_ImplBase {
 		public static final String PARAM_OUTPUT_DIR="PARAM_OUTPUT_DIR";
 		@ConfigurationParameter(mandatory=true,description="Output directory to write xml files to.",name=)
 		protected String outputDir;
 
 		public void process(JCas jcasthrows AnalysisEngineProcessException {
 			try {
 				// get the output file name from the input file name and output directory.
 				
 				File inFile = new File(ViewUriUtil.getURI(jcas));
 				String outFile = inFile.getName().replace(".txt""");
 				File outDir = new File(outFile);
 				if(!outDir.exists()) outDir.mkdirs();
 
 				// build the xml
 				DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
 				DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
 				Document doc = docBuilder.newDocument();
 
 				Element rootElement = doc.createElement("data");
 				
 				//info element
 				Element infoElement = doc.createElement("info");
 				Element saveTime = doc.createElement("savetime");
 				saveTime.setTextContent("2015-0123-10:21");
 				Element progress = doc.createElement("progress");
 				progress.setTextContent("completed");
 				infoElement.appendChild(saveTime);
 				infoElement.appendChild(progress);
 				
 				//schema element
 				Element schema = doc.createElement("schema");
 				schema.setAttribute("path""./");
 				schema.setAttribute("protocol""file");
 				schema.setTextContent("temporal-schema.xml");
 				
 				Element annoElement = doc.createElement("annotations");
 				Map<IdentifiedAnnotation,StringargToId = new HashMap<>();
 				int id=1;
 				for(EventMention event : JCasUtil.select(jcasEventMention.class)){
 					if (event.getClass().equals(EventMention.class)) {
 						// this ensures we are only looking at THYME events and not ctakes-dictionary-lookup events
 						Element eventEl = doc.createElement("entity");
 						String eventID = id+"@e@"+outFile+"@system"id++;
 						argToId.put(eventeventID);
 						Element idE = doc.createElement("id");
 						idE.setTextContent(eventID);
 						Element spanE = doc.createElement("span");
 						spanE.setTextContent(String.valueOf(event.getBegin())+","+String.valueOf(event.getEnd()));
 						Element typeE = doc.createElement("type");
 						typeE.setTextContent("EVENT");
 						Element parentTE = doc.createElement("parentsType");
 						parentTE.setTextContent("TemporalEntities");
 						//add properties
 						Element property = doc.createElement("properties");
 						Element docTimeRE = doc.createElement("DocTimeRel");
 						Element eventTypeE = doc.createElement("Type");
 						eventTypeE.setTextContent("N/A");
 						Element degreeE = doc.createElement("Degree");
 						degreeE.setTextContent("N/A");
 						Element polarityE = doc.createElement("Polarity");
 						String polarity = event.getPolarity()==0? "POS":"NEG";
 						polarityE.setTextContent(polarity);
 						Element ctexModE = doc.createElement("ContextualModality");
 						Element ctexAspE = doc.createElement("ContextualAspect");
 						Element permE = doc.createElement("Permanence");
 						permE.setTextContent("UNDETERMINED");
 						property.appendChild(docTimeRE);
 						property.appendChild(polarityE);
 						property.appendChild(degreeE);
 						property.appendChild(eventTypeE);
 						property.appendChild(ctexModE);
 						property.appendChild(ctexAspE);
 						property.appendChild(permE);
 						eventEl.appendChild(idE);
 						eventEl.appendChild(spanE);
 						eventEl.appendChild(typeE);
 						eventEl.appendChild(parentTE);
 						eventEl.appendChild(property);
 						annoElement.appendChild(eventEl);
 					}
 				}
 				for(TimeMention timex : JCasUtil.select(jcasTimeMention.class)){
 					Element timexElement = doc.createElement("entity");
 					String timexID = id+"@e@"+outFile+"@system"id++;//18@e@ID006_clinic_016@gold
 					argToId.put(timextimexID);
 					Element idE = doc.createElement("id");
 					idE.setTextContent(timexID);
 					Element spanE = doc.createElement("span");
 					spanE.setTextContent(String.valueOf(timex.getBegin())+","+String.valueOf(timex.getEnd()));
 					Element typeE = doc.createElement("type");
 					Element parentTE = doc.createElement("parentsType");
 					parentTE.setTextContent("TemporalEntities");
 					//add properties
 					Element property = doc.createElement("properties");
 					String timeClass = timex.getTimeClass();
 					if(timeClass.equals("DOCTIME")||timeClass.equals("SECTIONTIME")){
 						typeE.setTextContent(timeClass);
 						property.setTextContent("");
 					}else{
						typeE.setTextContent("TIMEX3");
						Element classE = doc.createElement("Class");
						classE.setTextContent(timeClass);
						property.appendChild(classE);
					timexElement.appendChild(idE);
					timexElement.appendChild(spanE);
					timexElement.appendChild(typeE);
					timexElement.appendChild(property);
					annoElement.appendChild(timexElement);
				id = 1;
				for(TemporalTextRelation rel : JCasUtil.select(jcasTemporalTextRelation.class)){
					Element linkEl = doc.createElement("relation");
					String linkID = id+"@r@"+outFile+"@system";id++;
					Element idE = doc.createElement("id");
					idE.setTextContent(linkID);
					Element typeE = doc.createElement("type");
					typeE.setTextContent("TLINK");
					Element parentTE = doc.createElement("parentsType");
					parentTE.setTextContent("TemporalRelations");
					//add properties
					Element property = doc.createElement("properties");
					Annotation arg1 = rel.getArg1().getArgument();