ctakes-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From c...@apache.org
Subject svn commit: r1778180 - in /ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/nn: ae/EventEventTokenAndBIOBasedAnnotator.java ae/EventTimeTokenAndBIOBasedAnnotator.java data/ArgContextProvider.java
Date Tue, 10 Jan 2017 19:57:07 GMT
Author: clin
Date: Tue Jan 10 19:57:06 2017
New Revision: 1778180

URL: http://svn.apache.org/viewvc?rev=1778180&view=rev
Log:
add BIO tag sequence for timex as additional input

Added:
    ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/nn/ae/EventEventTokenAndBIOBasedAnnotator.java
    ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/nn/ae/EventTimeTokenAndBIOBasedAnnotator.java
Modified:
    ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/nn/data/ArgContextProvider.java

Added: ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/nn/ae/EventEventTokenAndBIOBasedAnnotator.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/nn/ae/EventEventTokenAndBIOBasedAnnotator.java?rev=1778180&view=auto
==============================================================================
--- ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/nn/ae/EventEventTokenAndBIOBasedAnnotator.java
(added)
+++ ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/nn/ae/EventEventTokenAndBIOBasedAnnotator.java
Tue Jan 10 19:57:06 2017
@@ -0,0 +1,229 @@
+package org.apache.ctakes.temporal.nn.ae;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.ctakes.temporal.ae.TemporalRelationExtractorAnnotator.IdentifiedAnnotationPair;
+import org.apache.ctakes.temporal.nn.data.ArgContextProvider;
+import org.apache.ctakes.typesystem.type.relation.BinaryTextRelation;
+import org.apache.ctakes.typesystem.type.relation.RelationArgument;
+import org.apache.ctakes.typesystem.type.relation.TemporalTextRelation;
+import org.apache.ctakes.typesystem.type.textsem.EventMention;
+import org.apache.ctakes.typesystem.type.textsem.IdentifiedAnnotation;
+import org.apache.ctakes.typesystem.type.textspan.Sentence;
+import org.apache.uima.analysis_engine.AnalysisEngineProcessException;
+import org.apache.uima.fit.util.JCasUtil;
+import org.apache.uima.jcas.JCas;
+import org.apache.uima.jcas.tcas.Annotation;
+import org.cleartk.ml.CleartkAnnotator;
+import org.cleartk.ml.Feature;
+import org.cleartk.ml.Instance;
+import org.cleartk.util.ViewUriUtil;
+
+import com.google.common.collect.Lists;
+
+public class EventEventTokenAndBIOBasedAnnotator extends CleartkAnnotator<String> {
+
+  public static final String NO_RELATION_CATEGORY = "none";
+  // private Random coin = new Random(0);
+
+  @Override
+  public void process(JCas jCas) throws AnalysisEngineProcessException {
+
+    // get all gold relation lookup
+    Map<List<Annotation>, BinaryTextRelation> relationLookup;
+    relationLookup = new HashMap<>();
+    if (this.isTraining()) {
+      relationLookup = new HashMap<>();
+      for (BinaryTextRelation relation : JCasUtil.select(jCas, BinaryTextRelation.class))
{
+        Annotation arg1 = relation.getArg1().getArgument();
+        Annotation arg2 = relation.getArg2().getArgument();
+        // The key is a list of args so we can do bi-directional lookup
+        List<Annotation> key = Arrays.asList(arg1, arg2);
+        if(relationLookup.containsKey(key)){
+          String reln = relationLookup.get(key).getCategory();
+          System.err.println("Error in: "+ ViewUriUtil.getURI(jCas).toString());
+          System.err.println("Error! This attempted relation " + relation.getCategory() +

+              " already has a relation " + reln + " at this span: " + 
+              arg1.getCoveredText() + " -- " + arg2.getCoveredText());
+        } else {
+          relationLookup.put(key, relation);
+        }
+      }
+    }
+
+    for(Sentence sentence : JCasUtil.select(jCas, Sentence.class)) {
+      // collect all relevant relation arguments from the sentence
+      List<IdentifiedAnnotationPair> candidatePairs = getCandidateRelationArgumentPairs(jCas,
sentence);
+
+      // walk through the pairs of annotations
+      for (IdentifiedAnnotationPair pair : candidatePairs) {
+        IdentifiedAnnotation arg1 = pair.getArg1();
+        IdentifiedAnnotation arg2 = pair.getArg2();
+
+        String tokenContext;
+        String bioContext;
+        if(arg2.getBegin() < arg1.getBegin()) {
+          // ... event2 ... event1 ... scenario
+          System.out.println("\n-------------- THIS NEVER NAPPENS ------------\n");
+          tokenContext = ArgContextProvider.getTokenContext(jCas, sentence, arg2, "e2", arg1,
"e1", 2); 
+          bioContext = ArgContextProvider.getBIOContext(jCas, sentence, arg2, "e2", arg1,
"e1", 2); 
+        } else {
+          // ... event1 ... event2 ... scenario
+          tokenContext = ArgContextProvider.getTokenContext(jCas, sentence, arg1, "e1", arg2,
"e2", 2);
+          bioContext = ArgContextProvider.getBIOContext(jCas, sentence, arg1, "e1", arg2,
"e2", 2);
+        }
+
+        //derive features based on context:
+        List<Feature> feats = new ArrayList<>();
+        String[] tokens = (tokenContext + "|" + bioContext).split(" ");
+        for (String token: tokens){
+          feats.add(new Feature(token.toLowerCase()));
+        }
+
+        // during training, feed the features to the data writer
+        if(this.isTraining()) {
+          String category = getRelationCategory(relationLookup, arg1, arg2);
+          
+          // drop some portion of negative examples during training
+          // if(category == null && coin.nextDouble() <= 0.5) {
+          //   continue; // skip this negative example
+          // }
+          
+          if(category == null) {
+            category = NO_RELATION_CATEGORY;
+          } else{
+            category = category.toLowerCase();
+          }
+          this.dataWriter.write(new Instance<>(category, feats));
+        } else {
+          String predictedCategory = this.classifier.classify(feats);
+
+          // add a relation annotation if a true relation was predicted
+          if (predictedCategory != null && !predictedCategory.equals(NO_RELATION_CATEGORY))
{
+
+            // if we predict an inverted relation, reverse the order of the
+            // arguments
+            if (predictedCategory.endsWith("-1")) {
+              predictedCategory = predictedCategory.substring(0, predictedCategory.length()
- 2);
+              IdentifiedAnnotation temp = arg1;
+              arg1 = arg2;
+              arg2 = temp;
+            }
+
+            createRelation(jCas, arg1, arg2, predictedCategory.toUpperCase(), 0.0);
+          }
+        }
+      }
+
+    }
+  }
+
+  /**
+   * original way of getting label
+   * @param relationLookup
+   * @param arg1
+   * @param arg2
+   * @return
+   */
+  protected String getRelationCategory(
+      Map<List<Annotation>, BinaryTextRelation> relationLookup,
+      IdentifiedAnnotation arg1,
+      IdentifiedAnnotation arg2) {
+
+    BinaryTextRelation relation = relationLookup.get(Arrays.asList(arg1, arg2));
+    String category = null;
+    if (relation != null) {
+      if (arg2.getBegin() < arg1.getBegin()) {
+        category = relation.getCategory() + "-1";
+      } else {
+        category = relation.getCategory();
+      }
+    } else {
+      relation = relationLookup.get(Arrays.asList(arg2, arg1));
+      if (relation != null) {
+        if(arg2.getBegin() < arg1.getBegin()){
+          category = relation.getCategory();
+        } else {
+          category = relation.getCategory() + "-1";
+        }
+      }
+    }
+
+    return category;
+  }
+
+  protected String getRelationCategory2(Map<List<Annotation>, BinaryTextRelation>
relationLookup,
+      IdentifiedAnnotation arg1,
+      IdentifiedAnnotation arg2) {
+    
+    // gold view representation (i.e. only contains relations)
+    BinaryTextRelation arg1ContainsArg2 = relationLookup.get(Arrays.asList(arg1, arg2));
+    BinaryTextRelation arg2ContainsArg1 = relationLookup.get(Arrays.asList(arg2, arg1));
+
+    // now translate to position dependent representation (i.e. contains and contains-1)
+    if(arg1ContainsArg2 != null) {
+      // still need to know whether it's arg1 ... arg2 or arg2 ... arg1
+      // because that determines whether it's contains or contains-1
+      if(arg1.getBegin() < arg2.getBegin()) {
+        return arg1ContainsArg2.getCategory();
+      } else {
+        return arg1ContainsArg2.getCategory() + "-1";
+      }
+    } else if(arg2ContainsArg1 != null) {
+      if(arg1.getBegin() < arg2.getBegin()) {
+        return arg2ContainsArg1.getCategory() + "-1";
+      } else {
+        return arg2ContainsArg1.getCategory();
+      }
+    } else {
+      return null;      
+    }
+  }
+
+  protected void createRelation(JCas jCas, IdentifiedAnnotation arg1,
+      IdentifiedAnnotation arg2, String predictedCategory, double confidence) {
+    RelationArgument relArg1 = new RelationArgument(jCas);
+    relArg1.setArgument(arg1);
+    relArg1.setRole("Arg1");
+    relArg1.addToIndexes();
+    RelationArgument relArg2 = new RelationArgument(jCas);
+    relArg2.setArgument(arg2);
+    relArg2.setRole("Arg2");
+    relArg2.addToIndexes();
+    TemporalTextRelation relation = new TemporalTextRelation(jCas);
+    relation.setArg1(relArg1);
+    relation.setArg2(relArg2);
+    relation.setCategory(predictedCategory);
+    relation.setConfidence(confidence);
+    relation.addToIndexes();
+  }
+
+  private static List<IdentifiedAnnotationPair> getCandidateRelationArgumentPairs(JCas
jCas, Sentence sentence) {
+
+    List<IdentifiedAnnotationPair> pairs = Lists.newArrayList();
+    List<EventMention> events = new ArrayList<>(JCasUtil.selectCovered(jCas,
EventMention.class, sentence));
+    // filter events
+    List<EventMention> realEvents = Lists.newArrayList();
+    for( EventMention event : events){
+      if(event.getClass().equals(EventMention.class)){
+        realEvents.add(event);
+      }
+    }
+    events = realEvents;
+
+    int eventNum = events.size();
+    for (int i = 0; i < eventNum-1; i++) {
+      for(int j = i+1; j < eventNum; j++) {
+        EventMention eventA = events.get(i);
+        EventMention eventB = events.get(j);
+        pairs.add(new IdentifiedAnnotationPair(eventA, eventB));
+      }
+    }
+
+    return pairs;
+  }
+}

Added: ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/nn/ae/EventTimeTokenAndBIOBasedAnnotator.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/nn/ae/EventTimeTokenAndBIOBasedAnnotator.java?rev=1778180&view=auto
==============================================================================
--- ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/nn/ae/EventTimeTokenAndBIOBasedAnnotator.java
(added)
+++ ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/nn/ae/EventTimeTokenAndBIOBasedAnnotator.java
Tue Jan 10 19:57:06 2017
@@ -0,0 +1,292 @@
+package org.apache.ctakes.temporal.nn.ae;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.ctakes.temporal.ae.TemporalRelationExtractorAnnotator.IdentifiedAnnotationPair;
+import org.apache.ctakes.temporal.nn.data.ArgContextProvider;
+import org.apache.ctakes.typesystem.type.relation.BinaryTextRelation;
+import org.apache.ctakes.typesystem.type.relation.RelationArgument;
+import org.apache.ctakes.typesystem.type.relation.TemporalTextRelation;
+import org.apache.ctakes.typesystem.type.syntax.BaseToken;
+import org.apache.ctakes.typesystem.type.textsem.EventMention;
+import org.apache.ctakes.typesystem.type.textsem.IdentifiedAnnotation;
+import org.apache.ctakes.typesystem.type.textsem.TimeMention;
+import org.apache.ctakes.typesystem.type.textspan.Sentence;
+import org.apache.uima.analysis_engine.AnalysisEngineProcessException;
+import org.apache.uima.fit.util.JCasUtil;
+import org.apache.uima.jcas.JCas;
+import org.apache.uima.jcas.tcas.Annotation;
+import org.cleartk.ml.CleartkAnnotator;
+import org.cleartk.ml.Feature;
+import org.cleartk.ml.Instance;
+import org.cleartk.util.ViewUriUtil;
+
+import com.google.common.collect.Lists;
+
+public class EventTimeTokenAndBIOBasedAnnotator extends CleartkAnnotator<String> {
+
+  public static final String NO_RELATION_CATEGORY = "none";
+
+  public EventTimeTokenAndBIOBasedAnnotator() {
+    // TODO Auto-generated constructor stub
+  }
+
+  @Override
+  public void process(JCas jCas) throws AnalysisEngineProcessException {
+
+    //get all gold relation lookup
+    Map<List<Annotation>, BinaryTextRelation> relationLookup;
+    relationLookup = new HashMap<>();
+    if(this.isTraining()) {
+      relationLookup = new HashMap<>();
+      for(BinaryTextRelation relation : JCasUtil.select(jCas, BinaryTextRelation.class))
{
+        Annotation arg1 = relation.getArg1().getArgument();
+        Annotation arg2 = relation.getArg2().getArgument();
+        // The key is a list of args so we can do bi-directional lookup
+        List<Annotation> key = Arrays.asList(arg1, arg2);
+        if(relationLookup.containsKey(key)){
+          String reln = relationLookup.get(key).getCategory();
+          System.err.println("Error in: "+ ViewUriUtil.getURI(jCas).toString());
+          System.err.println("Error! This attempted relation " + relation.getCategory() +
" already has a relation " + reln + " at this span: " + arg1.getCoveredText() + " -- " + arg2.getCoveredText());
+        } else{
+          relationLookup.put(key, relation);
+        }
+      }
+    }
+
+    // go over sentences, extracting event-time relation instances
+    for(Sentence sentence : JCasUtil.select(jCas, Sentence.class)) {
+      // collect all relevant relation arguments from the sentence
+      List<IdentifiedAnnotationPair> candidatePairs =
+          getCandidateRelationArgumentPairs(jCas, sentence);
+
+      // walk through the pairs of annotations
+      for(IdentifiedAnnotationPair pair : candidatePairs) {
+        IdentifiedAnnotation arg1 = pair.getArg1();
+        IdentifiedAnnotation arg2 = pair.getArg2();
+
+        String tokenContext;
+        String posContext;
+        if(arg2.getBegin() < arg1.getBegin()) {
+          // ... time ... event ... scenario
+          tokenContext = ArgContextProvider.getTokenContext(jCas, sentence, arg2, "t", arg1,
"e", 2);
+          posContext = ArgContextProvider.getBIOContext(jCas, sentence, arg2, "t", arg1,
"e", 2);
+        } else {
+          // ... event ... time ... scenario
+          tokenContext = ArgContextProvider.getTokenContext(jCas, sentence, arg1, "e", arg2,
"t", 2);
+          posContext = ArgContextProvider.getBIOContext(jCas, sentence, arg1, "e", arg2,
"t", 2);
+        }
+
+        //derive features based on context:
+        List<Feature> features = new ArrayList<>();
+        String[] tokens = (tokenContext + "|" + posContext).split(" ");
+        for(String token: tokens){
+          features.add(new Feature(token.toLowerCase()));
+        }
+
+        // during training, feed the features to the data writer
+        if(this.isTraining()) {
+          String category = getRelationCategory(relationLookup, arg1, arg2);
+          if(category == null) {
+            category = NO_RELATION_CATEGORY;
+          } else {
+            category = category.toLowerCase();
+          }
+          this.dataWriter.write(new Instance<>(category, features));
+        }
+        // during classification feed the features to the classifier and create annotations
+        else {
+          String predictedCategory = this.classifier.classify(features);
+
+          // add a relation annotation if a true relation was predicted
+          if(predictedCategory != null && !predictedCategory.equals(NO_RELATION_CATEGORY))
{
+
+            // if we predict an inverted relation, reverse the order of the arguments
+            if(predictedCategory.endsWith("-1")) {
+              predictedCategory = predictedCategory.substring(0, predictedCategory.length()
- 2);
+              if(arg1 instanceof TimeMention){
+                IdentifiedAnnotation temp = arg1;
+                arg1 = arg2;
+                arg2 = temp;
+              }
+            } else {
+              if(arg1 instanceof EventMention){
+                IdentifiedAnnotation temp = arg1;
+                arg1 = arg2;
+                arg2 = temp;
+              }
+            }
+            
+            createRelation(jCas, arg1, arg2, predictedCategory.toUpperCase(), 0.0);
+          }
+        }
+      }
+    }
+  }
+  
+  /**
+   * Print context from left to right.
+   * @param contextSize number of tokens to include on the left of arg1 and on the right
of arg2
+   */
+  public static String getTokensBetweenExpanded(
+      JCas jCas, 
+      Sentence sent, 
+      Annotation left,
+      String leftType,
+      Annotation right,
+      String rightType,
+      int contextSize,
+      Map<EventMention, Collection<EventMention>> coveringMap) {
+
+    boolean leftIsExpanded = false;
+    Annotation longerLeft = left;
+    if(left instanceof EventMention){
+      longerLeft = getLongerEvent(coveringMap, left);
+      if(longerLeft != left){
+        leftIsExpanded = true;
+      }
+    }
+
+    boolean rightIsExpanded = false;
+    Annotation longerRight = right;
+    if(right instanceof EventMention){
+      longerRight = getLongerEvent(coveringMap, right);
+      if(longerRight != right){
+        rightIsExpanded = true;
+      }
+    }
+
+    List<String> tokens = new ArrayList<>();
+    if(leftIsExpanded){
+      for(BaseToken baseToken :  JCasUtil.selectPreceding(jCas, BaseToken.class, longerLeft,
contextSize)) {
+        if(sent.getBegin() <= baseToken.getBegin()) {
+          tokens.add(baseToken.getCoveredText()); 
+        }
+      }
+    }else{
+      for(BaseToken baseToken :  JCasUtil.selectPreceding(jCas, BaseToken.class, left, contextSize))
{
+        if(sent.getBegin() <= baseToken.getBegin()) {
+          tokens.add(baseToken.getCoveredText()); 
+        }
+      }
+    }
+    tokens.add("<" + leftType + ">");
+    tokens.add(left.getCoveredText());
+    tokens.add("</" + leftType + ">");
+    if(leftIsExpanded){
+      for(BaseToken baseToken : JCasUtil.selectBetween(jCas, BaseToken.class, longerLeft,
right)) {
+        tokens.add(baseToken.getCoveredText());
+      }
+    }else if(rightIsExpanded){
+      for(BaseToken baseToken : JCasUtil.selectBetween(jCas, BaseToken.class, left, longerRight))
{
+        tokens.add(baseToken.getCoveredText());
+      }
+    }else{
+      for(BaseToken baseToken : JCasUtil.selectBetween(jCas, BaseToken.class, left, right))
{
+        tokens.add(baseToken.getCoveredText());
+      }
+    }
+    tokens.add("<" + rightType + ">");
+    tokens.add(right.getCoveredText());
+    tokens.add("</" + rightType + ">");
+    if(rightIsExpanded){
+      for(BaseToken baseToken : JCasUtil.selectFollowing(jCas, BaseToken.class, longerRight,
contextSize)) {
+        if(baseToken.getEnd() <= sent.getEnd()) {
+          tokens.add(baseToken.getCoveredText());
+        }
+      }
+    }else{
+      for(BaseToken baseToken : JCasUtil.selectFollowing(jCas, BaseToken.class, right, contextSize))
{
+        if(baseToken.getEnd() <= sent.getEnd()) {
+          tokens.add(baseToken.getCoveredText());
+        }
+      }
+    }
+
+    return String.join(" ", tokens).replaceAll("[\r\n]", " ");
+  }
+
+  private static Annotation getLongerEvent(Map<EventMention, Collection<EventMention>>
coveringMap,
+      Annotation event) {
+    int maxSpan = getSpan(event);
+    Annotation longerEvent = event;
+    Collection<EventMention> eventList = coveringMap.get(event);
+    for(EventMention covEvent : eventList){
+      int span = getSpan(covEvent);
+      if(span > maxSpan){
+        maxSpan = span;
+        longerEvent = covEvent;
+      }
+    }
+    return longerEvent;
+  }
+
+  private static int getSpan(Annotation left) {
+    return (left.getEnd()-left.getBegin());
+  }
+
+  /** Dima's way of getting lables
+   * @param relationLookup
+   * @param arg1
+   * @param arg2
+   * @return
+   */
+  protected String getRelationCategory(Map<List<Annotation>, BinaryTextRelation>
relationLookup,
+      IdentifiedAnnotation arg1,
+      IdentifiedAnnotation arg2){
+    BinaryTextRelation relation = relationLookup.get(Arrays.asList(arg1, arg2));
+    String category = null;
+    if (relation != null) {
+      category = relation.getCategory();
+      if(arg1 instanceof EventMention){
+        category = category + "-1";
+      }
+    } else {
+      relation = relationLookup.get(Arrays.asList(arg2, arg1));
+      if (relation != null) {
+        category = relation.getCategory();
+        if(arg2 instanceof EventMention){
+          category = category + "-1";
+        }
+      }
+    }
+    return category;
+
+  }
+
+  protected void createRelation(JCas jCas, IdentifiedAnnotation arg1,
+      IdentifiedAnnotation arg2, String predictedCategory, double confidence) {
+    RelationArgument relArg1 = new RelationArgument(jCas);
+    relArg1.setArgument(arg1);
+    relArg1.setRole("Arg1");
+    relArg1.addToIndexes();
+    RelationArgument relArg2 = new RelationArgument(jCas);
+    relArg2.setArgument(arg2);
+    relArg2.setRole("Arg2");
+    relArg2.addToIndexes();
+    TemporalTextRelation relation = new TemporalTextRelation(jCas);
+    relation.setArg1(relArg1);
+    relation.setArg2(relArg2);
+    relation.setCategory(predictedCategory);
+    relation.setConfidence(confidence);
+    relation.addToIndexes();
+  }
+
+  public List<IdentifiedAnnotationPair> getCandidateRelationArgumentPairs(JCas jCas,
Annotation sentence) {
+    List<IdentifiedAnnotationPair> pairs = Lists.newArrayList();
+    for (EventMention event : JCasUtil.selectCovered(jCas, EventMention.class, sentence))
{
+      // ignore subclasses like Procedure and Disease/Disorder
+      if (event.getClass().equals(EventMention.class)) {
+        for (TimeMention time : JCasUtil.selectCovered(jCas, TimeMention.class, sentence))
{
+          pairs.add(new IdentifiedAnnotationPair(event, time));
+        }
+      }
+    }
+    return pairs;
+  }
+}

Modified: ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/nn/data/ArgContextProvider.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/nn/data/ArgContextProvider.java?rev=1778180&r1=1778179&r2=1778180&view=diff
==============================================================================
--- ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/nn/data/ArgContextProvider.java
(original)
+++ ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/nn/data/ArgContextProvider.java
Tue Jan 10 19:57:06 2017
@@ -5,6 +5,7 @@ import java.util.List;
 
 import org.apache.ctakes.typesystem.type.syntax.BaseToken;
 import org.apache.ctakes.typesystem.type.textsem.IdentifiedAnnotation;
+import org.apache.ctakes.typesystem.type.textsem.TimeMention;
 import org.apache.ctakes.typesystem.type.textspan.Sentence;
 import org.apache.uima.fit.util.JCasUtil;
 import org.apache.uima.jcas.JCas;
@@ -12,261 +13,354 @@ import org.apache.uima.jcas.tcas.Annotat
 
 public class ArgContextProvider {
 
-  /**
-   * Position features for event-time relations
-   */
-  public static String getEventTimePositionContext(
-      JCas jCas, 
-      Sentence sent, 
-      IdentifiedAnnotation time,
-      IdentifiedAnnotation event) {
-
-    // get sentence as a list of tokens
-    List<String> tokens = new ArrayList<>();
-    for(BaseToken baseToken : JCasUtil.selectCovered(jCas, BaseToken.class, sent)) {
-      tokens.add(baseToken.getCoveredText());  
-    }
-
-    // find the positions of time and event mentions
-    // assume time consists of multipe words; event of one
-    
-    int currentPosition = 0;       // current token index
-    int timeFirstPosition = -1000; // timex's start index
-    int timeLastPosition = -1000;  // timex's end index
-    int eventPosition = -1000;     // event's index
-    for(BaseToken token : JCasUtil.selectCovered(jCas, BaseToken.class, sent)) {
-      if(time.getBegin() == token.getBegin()) { 
-        timeFirstPosition = currentPosition; // start of time expression found
-      }
-      if(time.getEnd() == token.getEnd()) {
-        timeLastPosition = currentPosition;  // end of time expression found
-      }
-      if(event.getBegin() == token.getBegin()) { 
-        eventPosition = currentPosition;     // event postion found
-      } 
-      currentPosition++;
-    }
-
-    // try to locate events that weren't found
-    // e.g. "this can be re-discussed tomorrow"
-    // "discussed" not found due to incorrect tokenization
-    if(eventPosition == -1000) {
-      currentPosition = 0;
-      for(BaseToken token : JCasUtil.selectCovered(jCas, BaseToken.class, sent)) {
-        if(token.getCoveredText().contains(event.getCoveredText())) {
-          eventPosition = currentPosition; 
-        }
-        currentPosition++;
-      }
-    }
-
-    if(eventPosition == -1000) {
-      System.out.println("event not found: " + event.getCoveredText());
-      System.out.println(sent.getCoveredText());
-      System.out.println();
-      eventPosition = 0; // just set it to zero for now
-    }
-
-    // now need to see if some times weren't found
-    if(timeFirstPosition == -1000 || timeLastPosition == -1000) {
-      System.out.println("time not found: " + time.getCoveredText());
-      System.out.println(sent.getCoveredText());
-      System.out.println();
-      timeFirstPosition = 0; // just set it to zero for now
-      timeLastPosition = 0;  // just set it to zero for now
-    }
-
-    List<String> positionsWrtToTime = new ArrayList<>();
-    List<String> positionsWrtToEvent = new ArrayList<>();
-    int tokensInSentence = JCasUtil.selectCovered(jCas, BaseToken.class, sent).size();
-    for(int tokenIndex = 0; tokenIndex < tokensInSentence; tokenIndex++) {
-      if(tokenIndex < timeFirstPosition) {
-        positionsWrtToTime.add(Integer.toString(tokenIndex - timeFirstPosition));
-      } else if(tokenIndex >= timeFirstPosition && tokenIndex <= timeLastPosition)
{
-        positionsWrtToTime.add("0");
-      } else {
-        positionsWrtToTime.add(Integer.toString(tokenIndex - timeLastPosition));
-      }
-      positionsWrtToEvent.add(Integer.toString(tokenIndex - eventPosition));
-    }
-
-    String tokensAsString = String.join(" ", tokens).replaceAll("[\r\n]", " ");
-    String distanceToTime = String.join(" ", positionsWrtToTime);
-    String distanceToEvent = String.join(" ", positionsWrtToEvent);
-
-    return tokensAsString + "|" + distanceToTime + "|" + distanceToEvent;
-  } 
-
-  /**
-   * Position features for event-event relations
-   */
-  public static String getEventEventPositionContext(
-      JCas jCas, 
-      Sentence sent, 
-      IdentifiedAnnotation event1,
-      IdentifiedAnnotation event2) {
-
-    // get sentence as a list of tokens
-    List<String> tokens = new ArrayList<>();
-    for(BaseToken baseToken : JCasUtil.selectCovered(jCas, BaseToken.class, sent)) {
-      tokens.add(baseToken.getCoveredText());  
-    }
-
-    // find the positions of event mentions
-    // assume both events consists of just head words
-
-    int currentPosition = 0;       // current token index
-    int event1Position = -1000;    // event1's index
-    int event2Position = -1000;    // event2's index
-    for(BaseToken token : JCasUtil.selectCovered(jCas, BaseToken.class, sent)) {
-      if(event1.getBegin() == token.getBegin()) {
-        event1Position = currentPosition;     // event1 position found
-      }
-      if(event2.getBegin() == token.getBegin()) { 
-        event2Position = currentPosition;     // event2 postion found
-      } 
-      currentPosition++;
-    }
-
-    List<String> positionsWrtToEvent1 = new ArrayList<>();
-    List<String> positionsWrtToEvent2 = new ArrayList<>();    
-    int tokensInSentence = JCasUtil.selectCovered(jCas, BaseToken.class, sent).size();
-    for(int tokenIndex = 0; tokenIndex < tokensInSentence; tokenIndex++) {
-      positionsWrtToEvent1.add(Integer.toString(tokenIndex - event1Position));
-      positionsWrtToEvent2.add(Integer.toString(tokenIndex - event2Position));
-    }
-
-    String tokensAsString = String.join(" ", tokens).replaceAll("[\r\n]", " ");
-    String distanceToTime = String.join(" ", positionsWrtToEvent1);
-    String distanceToEvent = String.join(" ", positionsWrtToEvent2);
-
-    return tokensAsString + "|" + distanceToTime + "|" + distanceToEvent;
-  } 
-
-  /**
-   * Return tokens between arg1 and arg2 as string 
-   * @param contextSize number of tokens to include on the left of arg1 and on the right
of arg2
-   */
-  public static String getRegions(JCas jCas, Sentence sent, Annotation left, Annotation right,
int contextSize) {
-
-
-    // tokens to the left from the left argument
-    List<String> leftTokens = new ArrayList<>();
-    for(BaseToken baseToken :  JCasUtil.selectPreceding(jCas, BaseToken.class, left, contextSize))
{
-      if(sent.getBegin() <= baseToken.getBegin()) {
-        leftTokens.add(baseToken.getCoveredText()); 
-      }
-    }
-    String leftAsString = String.join(" ", leftTokens).replaceAll("[\r\n]", " ");
-
-    // left arg tokens
-    List<String> arg1Tokens = new ArrayList<>(); 
-    for(BaseToken baseToken : JCasUtil.selectCovered(jCas, BaseToken.class, left)) {
-      arg1Tokens.add(baseToken.getCoveredText());
-    }
-    String arg1AsString = String.join(" ", arg1Tokens).replaceAll("[\r\n]", " ");
-
-    // tokens between the arguments
-    List<String> betweenTokens = new ArrayList<>();
-    for(BaseToken baseToken : JCasUtil.selectBetween(jCas, BaseToken.class, left, right))
{
-      betweenTokens.add(baseToken.getCoveredText());
-    }
-    String betweenAsString = String.join(" ", betweenTokens).replaceAll("[\r\n]", " ");
-
-    // right arg tokens
-    List<String> arg2Tokens = new ArrayList<>(); 
-    for(BaseToken baseToken : JCasUtil.selectCovered(jCas, BaseToken.class, right)) {
-      arg2Tokens.add(baseToken.getCoveredText());
-    }
-    String arg2AsString = String.join(" ", arg2Tokens).replaceAll("[\r\n]", " ");
-
-    // tokens to the right from the right argument
-    List<String> rightTokens = new ArrayList<>();
-    for(BaseToken baseToken : JCasUtil.selectFollowing(jCas, BaseToken.class, right, contextSize))
{
-      if(baseToken.getEnd() <= sent.getEnd()) {
-        rightTokens.add(baseToken.getCoveredText());
-      }
-    }
-    String rightAsString = String.join(" ", rightTokens).replaceAll("[\r\n]", " ");
-
-    return leftAsString + "|" + arg1AsString + "|" + betweenAsString + "|" + arg2AsString
+ "|" + rightAsString;
-  }
-
-  /**
-   * Print words from left to right.
-   * @param contextSize number of tokens to include on the left of arg1 and on the right
of arg2
-   */
-  public static String getTokenContext(
-      JCas jCas, 
-      Sentence sent, 
-      Annotation left,
-      String leftType,
-      Annotation right,
-      String rightType,
-      int contextSize) {
-
-    List<String> tokens = new ArrayList<>();
-    for(BaseToken baseToken :  JCasUtil.selectPreceding(jCas, BaseToken.class, left, contextSize))
{
-      if(sent.getBegin() <= baseToken.getBegin()) {
-        tokens.add(baseToken.getCoveredText()); 
-      }
-    }
-    tokens.add("<" + leftType + ">");
-    tokens.add(left.getCoveredText());
-    tokens.add("</" + leftType + ">");
-    for(BaseToken baseToken : JCasUtil.selectBetween(jCas, BaseToken.class, left, right))
{
-      tokens.add(baseToken.getCoveredText());
-    }
-    tokens.add("<" + rightType + ">");
-    tokens.add(right.getCoveredText());
-    tokens.add("</" + rightType + ">");
-    for(BaseToken baseToken : JCasUtil.selectFollowing(jCas, BaseToken.class, right, contextSize))
{
-      if(baseToken.getEnd() <= sent.getEnd()) {
-        tokens.add(baseToken.getCoveredText());
-      }
-    }
-
-    return String.join(" ", tokens).replaceAll("[\r\n]", " ");
-  }
-
-  /**
-   * Print POS tags from left to right.
-   * @param contextSize number of tokens to include on the left of arg1 and on the right
of arg2
-   */
-  public static String getPosContext(
-      JCas jCas, 
-      Sentence sent, 
-      Annotation left,
-      String leftType,
-      Annotation right,
-      String rightType,
-      int contextSize) {
-
-    List<String> tokens = new ArrayList<>();
-    for(BaseToken baseToken :  JCasUtil.selectPreceding(jCas, BaseToken.class, left, contextSize))
{
-      if(sent.getBegin() <= baseToken.getBegin()) {
-        tokens.add(baseToken.getPartOfSpeech()); 
-      }
-    }
-    tokens.add("<" + leftType + ">");
-    for(BaseToken baseToken : JCasUtil.selectCovered(jCas, BaseToken.class, left)) {
-      tokens.add(baseToken.getPartOfSpeech());
-    }
-    tokens.add("</" + leftType + ">");
-    for(BaseToken baseToken : JCasUtil.selectBetween(jCas, BaseToken.class, left, right))
{
-      tokens.add(baseToken.getPartOfSpeech());
-    }
-    tokens.add("<" + rightType + ">");
-    for(BaseToken baseToken : JCasUtil.selectCovered(jCas, BaseToken.class, right)) {
-      tokens.add(baseToken.getPartOfSpeech());
-    }
-    tokens.add("</" + rightType + ">");
-    for(BaseToken baseToken : JCasUtil.selectFollowing(jCas, BaseToken.class, right, contextSize))
{
-      if(baseToken.getEnd() <= sent.getEnd()) {
-        tokens.add(baseToken.getPartOfSpeech());
-      }
-    }
+	private static TimeMention coveringTimex;
+	private static final String BTAG = "<B>";
+	private static final String OTAG = "<O>";
+	private static final String ITAG = "<I>";
+
+	/**
+	 * Position features for event-time relations
+	 */
+	public static String getEventTimePositionContext(
+			JCas jCas, 
+			Sentence sent, 
+			IdentifiedAnnotation time,
+			IdentifiedAnnotation event) {
+
+		// get sentence as a list of tokens
+		List<String> tokens = new ArrayList<>();
+		for(BaseToken baseToken : JCasUtil.selectCovered(jCas, BaseToken.class, sent)) {
+			tokens.add(baseToken.getCoveredText());  
+		}
+
+		// find the positions of time and event mentions
+		// assume time consists of multipe words; event of one
+
+		int currentPosition = 0;       // current token index
+		int timeFirstPosition = -1000; // timex's start index
+		int timeLastPosition = -1000;  // timex's end index
+		int eventPosition = -1000;     // event's index
+		for(BaseToken token : JCasUtil.selectCovered(jCas, BaseToken.class, sent)) {
+			if(time.getBegin() == token.getBegin()) { 
+				timeFirstPosition = currentPosition; // start of time expression found
+			}
+			if(time.getEnd() == token.getEnd()) {
+				timeLastPosition = currentPosition;  // end of time expression found
+			}
+			if(event.getBegin() == token.getBegin()) { 
+				eventPosition = currentPosition;     // event postion found
+			} 
+			currentPosition++;
+		}
+
+		// try to locate events that weren't found
+		// e.g. "this can be re-discussed tomorrow"
+		// "discussed" not found due to incorrect tokenization
+		if(eventPosition == -1000) {
+			currentPosition = 0;
+			for(BaseToken token : JCasUtil.selectCovered(jCas, BaseToken.class, sent)) {
+				if(token.getCoveredText().contains(event.getCoveredText())) {
+					eventPosition = currentPosition; 
+				}
+				currentPosition++;
+			}
+		}
+
+		if(eventPosition == -1000) {
+			System.out.println("event not found: " + event.getCoveredText());
+			System.out.println(sent.getCoveredText());
+			System.out.println();
+			eventPosition = 0; // just set it to zero for now
+		}
+
+		// now need to see if some times weren't found
+		if(timeFirstPosition == -1000 || timeLastPosition == -1000) {
+			System.out.println("time not found: " + time.getCoveredText());
+			System.out.println(sent.getCoveredText());
+			System.out.println();
+			timeFirstPosition = 0; // just set it to zero for now
+			timeLastPosition = 0;  // just set it to zero for now
+		}
+
+		List<String> positionsWrtToTime = new ArrayList<>();
+		List<String> positionsWrtToEvent = new ArrayList<>();
+		int tokensInSentence = JCasUtil.selectCovered(jCas, BaseToken.class, sent).size();
+		for(int tokenIndex = 0; tokenIndex < tokensInSentence; tokenIndex++) {
+			if(tokenIndex < timeFirstPosition) {
+				positionsWrtToTime.add(Integer.toString(tokenIndex - timeFirstPosition));
+			} else if(tokenIndex >= timeFirstPosition && tokenIndex <= timeLastPosition)
{
+				positionsWrtToTime.add("0");
+			} else {
+				positionsWrtToTime.add(Integer.toString(tokenIndex - timeLastPosition));
+			}
+			positionsWrtToEvent.add(Integer.toString(tokenIndex - eventPosition));
+		}
+
+		String tokensAsString = String.join(" ", tokens).replaceAll("[\r\n]", " ");
+		String distanceToTime = String.join(" ", positionsWrtToTime);
+		String distanceToEvent = String.join(" ", positionsWrtToEvent);
+
+		return tokensAsString + "|" + distanceToTime + "|" + distanceToEvent;
+	} 
+
+	/**
+	 * Position features for event-event relations
+	 */
+	public static String getEventEventPositionContext(
+			JCas jCas, 
+			Sentence sent, 
+			IdentifiedAnnotation event1,
+			IdentifiedAnnotation event2) {
+
+		// get sentence as a list of tokens
+		List<String> tokens = new ArrayList<>();
+		for(BaseToken baseToken : JCasUtil.selectCovered(jCas, BaseToken.class, sent)) {
+			tokens.add(baseToken.getCoveredText());  
+		}
+
+		// find the positions of event mentions
+		// assume both events consists of just head words
+
+		int currentPosition = 0;       // current token index
+		int event1Position = -1000;    // event1's index
+		int event2Position = -1000;    // event2's index
+		for(BaseToken token : JCasUtil.selectCovered(jCas, BaseToken.class, sent)) {
+			if(event1.getBegin() == token.getBegin()) {
+				event1Position = currentPosition;     // event1 position found
+			}
+			if(event2.getBegin() == token.getBegin()) { 
+				event2Position = currentPosition;     // event2 postion found
+			} 
+			currentPosition++;
+		}
+
+		List<String> positionsWrtToEvent1 = new ArrayList<>();
+		List<String> positionsWrtToEvent2 = new ArrayList<>();    
+		int tokensInSentence = JCasUtil.selectCovered(jCas, BaseToken.class, sent).size();
+		for(int tokenIndex = 0; tokenIndex < tokensInSentence; tokenIndex++) {
+			positionsWrtToEvent1.add(Integer.toString(tokenIndex - event1Position));
+			positionsWrtToEvent2.add(Integer.toString(tokenIndex - event2Position));
+		}
+
+		String tokensAsString = String.join(" ", tokens).replaceAll("[\r\n]", " ");
+		String distanceToTime = String.join(" ", positionsWrtToEvent1);
+		String distanceToEvent = String.join(" ", positionsWrtToEvent2);
+
+		return tokensAsString + "|" + distanceToTime + "|" + distanceToEvent;
+	} 
+
+	/**
+	 * Return tokens between arg1 and arg2 as string 
+	 * @param contextSize number of tokens to include on the left of arg1 and on the right of
arg2
+	 */
+	public static String getRegions(JCas jCas, Sentence sent, Annotation left, Annotation right,
int contextSize) {
+
+
+		// tokens to the left from the left argument
+		List<String> leftTokens = new ArrayList<>();
+		for(BaseToken baseToken :  JCasUtil.selectPreceding(jCas, BaseToken.class, left, contextSize))
{
+			if(sent.getBegin() <= baseToken.getBegin()) {
+				leftTokens.add(baseToken.getCoveredText()); 
+			}
+		}
+		String leftAsString = String.join(" ", leftTokens).replaceAll("[\r\n]", " ");
+
+		// left arg tokens
+		List<String> arg1Tokens = new ArrayList<>(); 
+		for(BaseToken baseToken : JCasUtil.selectCovered(jCas, BaseToken.class, left)) {
+			arg1Tokens.add(baseToken.getCoveredText());
+		}
+		String arg1AsString = String.join(" ", arg1Tokens).replaceAll("[\r\n]", " ");
+
+		// tokens between the arguments
+		List<String> betweenTokens = new ArrayList<>();
+		for(BaseToken baseToken : JCasUtil.selectBetween(jCas, BaseToken.class, left, right)) {
+			betweenTokens.add(baseToken.getCoveredText());
+		}
+		String betweenAsString = String.join(" ", betweenTokens).replaceAll("[\r\n]", " ");
+
+		// right arg tokens
+		List<String> arg2Tokens = new ArrayList<>(); 
+		for(BaseToken baseToken : JCasUtil.selectCovered(jCas, BaseToken.class, right)) {
+			arg2Tokens.add(baseToken.getCoveredText());
+		}
+		String arg2AsString = String.join(" ", arg2Tokens).replaceAll("[\r\n]", " ");
+
+		// tokens to the right from the right argument
+		List<String> rightTokens = new ArrayList<>();
+		for(BaseToken baseToken : JCasUtil.selectFollowing(jCas, BaseToken.class, right, contextSize))
{
+			if(baseToken.getEnd() <= sent.getEnd()) {
+				rightTokens.add(baseToken.getCoveredText());
+			}
+		}
+		String rightAsString = String.join(" ", rightTokens).replaceAll("[\r\n]", " ");
+
+		return leftAsString + "|" + arg1AsString + "|" + betweenAsString + "|" + arg2AsString +
"|" + rightAsString;
+	}
+
+	/**
+	 * Print words from left to right.
+	 * @param contextSize number of tokens to include on the left of arg1 and on the right of
arg2
+	 */
+	public static String getTokenContext(
+			JCas jCas, 
+			Sentence sent, 
+			Annotation left,
+			String leftType,
+			Annotation right,
+			String rightType,
+			int contextSize) {
+
+		List<String> tokens = new ArrayList<>();
+		for(BaseToken baseToken :  JCasUtil.selectPreceding(jCas, BaseToken.class, left, contextSize))
{
+			if(sent.getBegin() <= baseToken.getBegin()) {
+				tokens.add(baseToken.getCoveredText()); 
+			}
+		}
+		tokens.add("<" + leftType + ">");
+		tokens.add(left.getCoveredText());
+		tokens.add("</" + leftType + ">");
+		for(BaseToken baseToken : JCasUtil.selectBetween(jCas, BaseToken.class, left, right)) {
+			tokens.add(baseToken.getCoveredText());
+		}
+		tokens.add("<" + rightType + ">");
+		tokens.add(right.getCoveredText());
+		tokens.add("</" + rightType + ">");
+		for(BaseToken baseToken : JCasUtil.selectFollowing(jCas, BaseToken.class, right, contextSize))
{
+			if(baseToken.getEnd() <= sent.getEnd()) {
+				tokens.add(baseToken.getCoveredText());
+			}
+		}
+
+		return String.join(" ", tokens).replaceAll("[\r\n]", " ");
+	}
+
+	/**
+	 * Print POS tags from left to right.
+	 * @param contextSize number of tokens to include on the left of arg1 and on the right of
arg2
+	 */
+	public static String getPosContext(
+			JCas jCas, 
+			Sentence sent, 
+			Annotation left,
+			String leftType,
+			Annotation right,
+			String rightType,
+			int contextSize) {
+
+		List<String> tokens = new ArrayList<>();
+		for(BaseToken baseToken :  JCasUtil.selectPreceding(jCas, BaseToken.class, left, contextSize))
{
+			if(sent.getBegin() <= baseToken.getBegin()) {
+				tokens.add(baseToken.getPartOfSpeech()); 
+			}
+		}
+		tokens.add("<" + leftType + ">");
+		for(BaseToken baseToken : JCasUtil.selectCovered(jCas, BaseToken.class, left)) {
+			tokens.add(baseToken.getPartOfSpeech());
+		}
+		tokens.add("</" + leftType + ">");
+		for(BaseToken baseToken : JCasUtil.selectBetween(jCas, BaseToken.class, left, right)) {
+			tokens.add(baseToken.getPartOfSpeech());
+		}
+		tokens.add("<" + rightType + ">");
+		for(BaseToken baseToken : JCasUtil.selectCovered(jCas, BaseToken.class, right)) {
+			tokens.add(baseToken.getPartOfSpeech());
+		}
+		tokens.add("</" + rightType + ">");
+		for(BaseToken baseToken : JCasUtil.selectFollowing(jCas, BaseToken.class, right, contextSize))
{
+			if(baseToken.getEnd() <= sent.getEnd()) {
+				tokens.add(baseToken.getPartOfSpeech());
+			}
+		}
+
+		return String.join(" ", tokens).replaceAll("[\r\n]", " ");
+	}
+
+	public static String getBIOContext(JCas jCas, Sentence sentence, IdentifiedAnnotation arg1,
String leftType,
+			IdentifiedAnnotation arg2, String rightType, int contextSize) {
+		List<String> tokens = new ArrayList<>();
+		//select prior context:
+		List<TimeMention> preTimex = JCasUtil.selectCovered(jCas, TimeMention.class, sentence.getBegin(),
arg1.getBegin());
+		List<TimeMention> betweenTimex = JCasUtil.selectCovered(jCas, TimeMention.class,
arg1.getEnd(), arg2.getBegin());
+		List<TimeMention> afterTimex = JCasUtil.selectCovered(jCas, TimeMention.class, arg2.getEnd(),
sentence.getEnd());
+
+		tokens = addTimex2TokenSequence(jCas, tokens, JCasUtil.selectPreceding(jCas, BaseToken.class,
arg1, contextSize), preTimex, sentence);
+		//get arg1:
+		tokens.add(OTAG);//"<" + leftType + ">");
+		if (arg1 instanceof TimeMention){
+			String timeTag = generateTimeTag(jCas, (TimeMention)arg1);
+			tokens.add(timeTag);
+		}else{
+			tokens.add(OTAG);//arg1.getCoveredText());
+			//          tokens.add(getEventProperty((EventMention)arg1));
+		}
+		tokens.add(OTAG);//"</" + leftType + ">");
+		tokens = addTimex2TokenSequence(jCas, tokens, JCasUtil.selectBetween(jCas, BaseToken.class,
arg1, arg2), betweenTimex, sentence);
+		//arg2
+		tokens.add(OTAG);//"<" + rightType + ">");
+		if (arg2 instanceof TimeMention){
+			String timeTag = generateTimeTag(jCas, (TimeMention)arg2);
+			tokens.add(timeTag);
+		}else{
+			tokens.add(OTAG);//arg2.getCoveredText());
+			//          tokens.add(getEventProperty((EventMention)arg2));
+		}
+		tokens.add(OTAG);//"</" + rightType + ">");
+		tokens = addTimex2TokenSequence(jCas, tokens, JCasUtil.selectFollowing(jCas, BaseToken.class,
arg2, contextSize), afterTimex, sentence);
+
+
+		return String.join(" ", tokens).replaceAll("[\r\n]", " ");
+	}
+
+	private static String generateTimeTag(JCas jCas, TimeMention timex) {
+		String timeTag;
+		//check if there is any number token within the timex mention:
+		List<BaseToken> tokens = JCasUtil.selectCovered(jCas, BaseToken.class, timex);
+		int numTokens = tokens.size();
+		if(numTokens>0){
+			timeTag=BTAG;
+		}else{
+			return "";
+		}
+
+		if(numTokens==1){
+			return timeTag;
+		}
+		for(int i=0;i<numTokens-1; i++){
+			timeTag= timeTag+ " " + ITAG;
+		}
+		return timeTag;
+	}
+
+	private static List<String> addTimex2TokenSequence(JCas jCas, List<String> tokens,
List<BaseToken> tokenSequences, List<TimeMention> listOfTimex, Sentence sent)
{
+		coveringTimex = null;
+		for (BaseToken baseToken : tokenSequences){
+			if(baseToken.getEnd() <= sent.getEnd() && sent.getBegin() <= baseToken.getBegin()){
+				TimeMention currentTimex = findCoveringTimex(baseToken, listOfTimex);
+				if(currentTimex == null){
+					if(coveringTimex != null ){
+						coveringTimex = null;
+					}
+					tokens.add(OTAG); 
+				}else{//current timex is not null
+					if( currentTimex != coveringTimex){
+						String timeTag = generateTimeTag(jCas, currentTimex);
+						tokens.add(timeTag);
+						coveringTimex = currentTimex;
+					}
+				}
+			}
+		}
+		return tokens;
+	}
+
+	private static TimeMention findCoveringTimex(BaseToken baseToken, List<TimeMention>
timexs) {
+		for(TimeMention timex : timexs){
+			if(timex.getBegin()<= baseToken.getBegin() && timex.getEnd() >= baseToken.getEnd()){
+				return timex;
+			}
+		}
+		return null;
+	}
 
-    return String.join(" ", tokens).replaceAll("[\r\n]", " ");
-  }
 }



Mime
View raw message