You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ctakes.apache.org by cl...@apache.org on 2014/04/17 22:12:28 UTC

svn commit: r1588359 - in /ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal: ae/ eval/ utils/

Author: clin
Date: Thu Apr 17 20:12:28 2014
New Revision: 1588359

URL: http://svn.apache.org/r1588359
Log:
add transitive closure for event-time relation discovery. Closure was added for both training and testing, and both gold relations and system predictions.

Added:
    ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/utils/AnnotationIdCollection.java   (with props)
    ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/utils/TLinkTypeArray2.java   (with props)
    ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/utils/TimeRelationConstants.java   (with props)
    ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/utils/TlinkType.java   (with props)
    ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/utils/TlinkTypeSet.java   (with props)
Modified:
    ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/ae/EventTimeRelationAnnotator.java
    ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/eval/EvaluationOfEventTimeRelations.java

Modified: ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/ae/EventTimeRelationAnnotator.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/ae/EventTimeRelationAnnotator.java?rev=1588359&r1=1588358&r2=1588359&view=diff
==============================================================================
--- ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/ae/EventTimeRelationAnnotator.java (original)
+++ ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/ae/EventTimeRelationAnnotator.java Thu Apr 17 20:12:28 2014
@@ -9,12 +9,16 @@ import org.apache.ctakes.relationextract
 import org.apache.ctakes.relationextractor.ae.features.PartOfSpeechFeaturesExtractor;
 import org.apache.ctakes.relationextractor.ae.features.RelationFeaturesExtractor;
 import org.apache.ctakes.relationextractor.ae.features.TokenFeaturesExtractor;
-import org.apache.ctakes.temporal.ae.feature.DependencyFeatureExtractor;
+import org.apache.ctakes.temporal.ae.feature.CheckSpecialWordRelationExtractor;
+import org.apache.ctakes.temporal.ae.feature.DependencyPathFeaturesExtractor;
+import org.apache.ctakes.temporal.ae.feature.NearbyVerbTenseRelationExtractor;
 import org.apache.ctakes.temporal.ae.feature.NearestFlagFeatureExtractor;
+import org.apache.ctakes.temporal.ae.feature.SectionHeaderRelationExtractor;
 //import org.apache.ctakes.temporal.ae.feature.TemporalAttributeFeatureExtractor;
-import org.apache.ctakes.temporal.ae.feature.treekernel.EventTimeFlatTreeFeatureExtractor;
+//import org.apache.ctakes.temporal.ae.feature.treekernel.EventTimeFlatTreeFeatureExtractor;
+//import org.apache.ctakes.temporal.ae.feature.treekernel.EventVerbRelationTreeExtractor;
 import org.apache.ctakes.temporal.ae.feature.treekernel.TemporalPETExtractor;
-import org.apache.ctakes.temporal.ae.feature.treekernel.TemporalPathExtractor;
+//import org.apache.ctakes.temporal.ae.feature.treekernel.TemporalPathExtractor;
 import org.apache.ctakes.typesystem.type.relation.BinaryTextRelation;
 import org.apache.ctakes.typesystem.type.textsem.EventMention;
 import org.apache.ctakes.typesystem.type.textsem.IdentifiedAnnotation;
@@ -69,11 +73,16 @@ public class EventTimeRelationAnnotator 
 				new TokenFeaturesExtractor()
 				, new PartOfSpeechFeaturesExtractor()
 				//    						, new TemporalAttributeFeatureExtractor()
-				, new EventTimeFlatTreeFeatureExtractor()
+//				, new EventTimeFlatTreeFeatureExtractor()
 				, new TemporalPETExtractor()
-				, new TemporalPathExtractor()
+//				, new TemporalPathExtractor()
+//				, new EventVerbRelationTreeExtractor()
+				, new SectionHeaderRelationExtractor()
+				, new NearbyVerbTenseRelationExtractor()
+				, new CheckSpecialWordRelationExtractor()
 				, new NearestFlagFeatureExtractor()
-				, new DependencyFeatureExtractor()
+				, new DependencyPathFeaturesExtractor()
+//				, new DependencyFeatureExtractor()
 				);
 	}
 
@@ -95,9 +104,32 @@ public class EventTimeRelationAnnotator 
 				}
 			}
 		}
+		
+		//only use gold pairs:
+//		for (BinaryTextRelation relation : JCasUtil.select(jCas, BinaryTextRelation.class)) {
+//			Annotation arg1 = relation.getArg1().getArgument();
+//			Annotation arg2 = relation.getArg2().getArgument();
+//			EventMention event = null;
+//			TimeMention time = null;
+//			if(arg1 instanceof EventMention){
+//				 event = (EventMention) arg1;
+//			}else if(arg1 instanceof TimeMention){
+//				time = (TimeMention) arg1;
+//			}
+//			if(arg2 instanceof EventMention){
+//				 event = (EventMention) arg2;
+//			}else if(arg2 instanceof TimeMention){
+//				time = (TimeMention) arg2;
+//			}
+//			if(event != null && time != null){
+//				pairs.add(new IdentifiedAnnotationPair(event, time));
+//			}
+//		}
+		
 		return pairs;
 	}
 
+
 	@Override
 	protected String getRelationCategory(
 			Map<List<Annotation>, BinaryTextRelation> relationLookup,
@@ -110,7 +142,11 @@ public class EventTimeRelationAnnotator 
 		} else {
 			relation = relationLookup.get(Arrays.asList(arg2, arg1));
 			if (relation != null) {
-				category = relation.getCategory() + "-1";
+				if(relation.getCategory().equals("OVERLAP")){
+					category = relation.getCategory();
+				}else{
+					category = relation.getCategory() + "-1";
+				}
 			}
 		}
 		if (category == null && coin.nextDouble() <= this.probabilityOfKeepingANegativeExample) {

Modified: ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/eval/EvaluationOfEventTimeRelations.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/eval/EvaluationOfEventTimeRelations.java?rev=1588359&r1=1588358&r2=1588359&view=diff
==============================================================================
--- ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/eval/EvaluationOfEventTimeRelations.java (original)
+++ ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/eval/EvaluationOfEventTimeRelations.java Thu Apr 17 20:12:28 2014
@@ -34,6 +34,8 @@ import org.apache.ctakes.relationextract
 import org.apache.ctakes.temporal.ae.EventTimeRelationAnnotator;
 import org.apache.ctakes.temporal.ae.baselines.RecallBaselineEventTimeRelationAnnotator;
 import org.apache.ctakes.temporal.eval.EvaluationOfTemporalRelations_ImplBase.RemoveNonContainsRelations.RemoveGoldAttributes;
+import org.apache.ctakes.temporal.utils.AnnotationIdCollection;
+import org.apache.ctakes.temporal.utils.TLinkTypeArray2;
 import org.apache.ctakes.typesystem.type.relation.BinaryTextRelation;
 import org.apache.ctakes.typesystem.type.relation.RelationArgument;
 import org.apache.ctakes.typesystem.type.textsem.EventMention;
@@ -221,15 +223,18 @@ EvaluationOfTemporalRelations_ImplBase{
 		//	  if(this.baseline) return;
 		AggregateBuilder aggregateBuilder = this.getPreprocessorAggregateBuilder();
 		aggregateBuilder.add(CopyFromGold.getDescription(EventMention.class, TimeMention.class, BinaryTextRelation.class));
-		aggregateBuilder.add(AnalysisEngineFactory.createPrimitiveDescription(RemoveNonContainsRelations.class));
 		aggregateBuilder.add(AnalysisEngineFactory.createPrimitiveDescription(RemoveCrossSentenceRelations.class));
 		if(!this.useGoldAttributes){
 			aggregateBuilder.add(AnalysisEngineFactory.createPrimitiveDescription(RemoveGoldAttributes.class));
 		}
 		if (this.useClosure) {
-			aggregateBuilder.add(AnalysisEngineFactory.createPrimitiveDescription(AddTransitiveContainsRelations.class));
+			aggregateBuilder.add(AnalysisEngineFactory.createPrimitiveDescription(AddClosure.class));//aggregateBuilder.add(AnalysisEngineFactory.createPrimitiveDescription(AddTransitiveContainsRelations.class));
+//			aggregateBuilder.add(AnalysisEngineFactory.createPrimitiveDescription(AddContain2Overlap.class));
 			//			aggregateBuilder.add(AnalysisEngineFactory.createPrimitiveDescription(AddTransitiveBeforeAndOnRelations.class));
 		}
+//		aggregateBuilder.add(AnalysisEngineFactory.createPrimitiveDescription(RemoveNonContainsRelations.class));
+		aggregateBuilder.add(AnalysisEngineFactory.createPrimitiveDescription(AddFlippedOverlap.class));//add flipped overlap instances to training data
+		
 		aggregateBuilder.add(AnalysisEngineFactory.createPrimitiveDescription(RemoveEventEventRelations.class));
 		aggregateBuilder.add(EventTimeRelationAnnotator.createDataWriterDescription(
 				//                LIBSVMStringOutcomeDataWriter.class,
@@ -274,10 +279,7 @@ EvaluationOfTemporalRelations_ImplBase{
 			throws Exception {
 		AggregateBuilder aggregateBuilder = this.getPreprocessorAggregateBuilder();
 		aggregateBuilder.add(CopyFromGold.getDescription(EventMention.class, TimeMention.class));
-		aggregateBuilder.add(
-				AnalysisEngineFactory.createPrimitiveDescription(RemoveNonContainsRelations.class,
-						RemoveNonContainsRelations.PARAM_RELATION_VIEW,
-						GOLD_VIEW_NAME));
+		
 		aggregateBuilder.add(AnalysisEngineFactory.createPrimitiveDescription(
 				RemoveCrossSentenceRelations.class,
 				RemoveCrossSentenceRelations.PARAM_SENTENCE_VIEW,
@@ -286,14 +288,24 @@ EvaluationOfTemporalRelations_ImplBase{
 				GOLD_VIEW_NAME));
 		if (this.useClosure) {
 			aggregateBuilder.add(
-					AnalysisEngineFactory.createPrimitiveDescription(AddTransitiveContainsRelations.class),
+					AnalysisEngineFactory.createPrimitiveDescription(AddClosure.class),//AnalysisEngineFactory.createPrimitiveDescription(AddTransitiveContainsRelations.class),
 					CAS.NAME_DEFAULT_SOFA,
 					GOLD_VIEW_NAME);
+					
+//			aggregateBuilder.add(
+//					AnalysisEngineFactory.createPrimitiveDescription(AddContain2Overlap.class),
+//					CAS.NAME_DEFAULT_SOFA,
+//					GOLD_VIEW_NAME);
 			//			aggregateBuilder.add(
 			//					AnalysisEngineFactory.createPrimitiveDescription(AddTransitiveBeforeAndOnRelations.class),
 			//					CAS.NAME_DEFAULT_SOFA,
 			//					GOLD_VIEW_NAME);
 		}
+		
+//		aggregateBuilder.add(
+//				AnalysisEngineFactory.createPrimitiveDescription(RemoveNonContainsRelations.class,
+//						RemoveNonContainsRelations.PARAM_RELATION_VIEW,
+//						GOLD_VIEW_NAME));
 		aggregateBuilder.add(
 				AnalysisEngineFactory.createPrimitiveDescription(RemoveEventEventRelations.class),
 				CAS.NAME_DEFAULT_SOFA,
@@ -302,7 +314,15 @@ EvaluationOfTemporalRelations_ImplBase{
 		aggregateBuilder.add(AnalysisEngineFactory.createPrimitiveDescription(RemoveRelations.class));
 		aggregateBuilder.add(this.baseline ? RecallBaselineEventTimeRelationAnnotator.createAnnotatorDescription(directory) :
 			EventTimeRelationAnnotator.createAnnotatorDescription(directory));
-
+		
+		if (this.useClosure) {//add closure for system output
+			aggregateBuilder.add(
+					AnalysisEngineFactory.createPrimitiveDescription(AddClosure.class),//AnalysisEngineFactory.createPrimitiveDescription(AddTransitiveContainsRelations.class),
+					GOLD_VIEW_NAME,
+					CAS.NAME_DEFAULT_SOFA
+					);
+		}
+		
 		Function<BinaryTextRelation, ?> getSpan = new Function<BinaryTextRelation, HashableArguments>() {
 			public HashableArguments apply(BinaryTextRelation relation) {
 				return new HashableArguments(relation);
@@ -416,25 +436,25 @@ EvaluationOfTemporalRelations_ImplBase{
   }
 	 */
 
-	//	private static <SPAN_TYPE> Collection<BinaryTextRelation> removeNonGoldRelations(
-	//			Collection<BinaryTextRelation> systemRelations,
-	//			Collection<BinaryTextRelation> goldRelations, Function<BinaryTextRelation, ?> getSpan) {
-	//		//remove non-gold pairs from system relations:
-	//		Set<BinaryTextRelation> goodSys = Sets.newHashSet();
-	//		Set<SPAN_TYPE> goldspans = new HashSet<SPAN_TYPE>();
-	//		
-	//		for (BinaryTextRelation relation : goldRelations) {
-	//			goldspans.add(((SPAN_TYPE) getSpan.apply(relation)));			
-	//		}
-	//		
-	//		for (BinaryTextRelation relation : systemRelations) {
-	//			if (goldspans.contains(((SPAN_TYPE) getSpan.apply(relation)))) {
-	//				goodSys.add(relation);
-	//			}
-	//		}
-	//		
-	//		return goodSys;
-	//	}
+//		private static <SPAN_TYPE> Collection<BinaryTextRelation> removeNonGoldRelations(
+//				Collection<BinaryTextRelation> systemRelations,
+//				Collection<BinaryTextRelation> goldRelations, Function<BinaryTextRelation, ?> getSpan) {
+//			//remove non-gold pairs from system relations:
+//			Set<BinaryTextRelation> goodSys = Sets.newHashSet();
+//			Set<SPAN_TYPE> goldspans = new HashSet<SPAN_TYPE>();
+//			
+//			for (BinaryTextRelation relation : goldRelations) {
+//				goldspans.add(((SPAN_TYPE) getSpan.apply(relation)));			
+//			}
+//			
+//			for (BinaryTextRelation relation : systemRelations) {
+//				if (goldspans.contains(((SPAN_TYPE) getSpan.apply(relation)))) {
+//					goodSys.add(relation);
+//				}
+//			}
+//			
+//			return goodSys;
+//		}
 
 	private static Collection<BinaryTextRelation> correctArgOrder(
 			Collection<BinaryTextRelation> systemRelations,
@@ -776,108 +796,270 @@ EvaluationOfTemporalRelations_ImplBase{
 		}
 
 	}
-
-	public static class AddTransitiveBeforeAndOnRelations extends JCasAnnotator_ImplBase {
+	
+	public static class AddContain2Overlap extends JCasAnnotator_ImplBase {
 
 		@Override
 		public void process(JCas jCas) throws AnalysisEngineProcessException {
 
-			// collect many-to-many mappings of containment relations 
-			Multimap<Annotation, Annotation> contains = HashMultimap.create();
-			Multimap<Annotation, Annotation> before = HashMultimap.create();
-			Multimap<Annotation, Annotation> endson = HashMultimap.create();
-			Multimap<Annotation, Annotation> beginson = HashMultimap.create();
-			Set<BinaryTextRelation> beforeRel = Sets.newHashSet();
-
+			Set<BinaryTextRelation> containsRelations = Sets.newHashSet();
 			for (BinaryTextRelation relation : JCasUtil.select(jCas, BinaryTextRelation.class)) {
 				if (relation.getCategory().equals("CONTAINS")) {
+					containsRelations.add(relation);
+				}
+			}
+
+			for (BinaryTextRelation relation : containsRelations) {
+				RelationArgument arg1 = (RelationArgument) relation.getArg1().clone();
+				RelationArgument arg2 = (RelationArgument) relation.getArg2().clone();
+				BinaryTextRelation newrelation = new BinaryTextRelation(jCas);
+				newrelation.setArg1(arg1);
+				newrelation.setArg2(arg2);
+				newrelation.setCategory("OVERLAP");
+				arg1.addToIndexes();
+				arg2.addToIndexes();
+				newrelation.addToIndexes();
+			}
+		}
+	}
+	
+	public static class AddFlippedOverlap extends JCasAnnotator_ImplBase {
+
+		@Override
+		public void process(JCas jCas) throws AnalysisEngineProcessException {
+
+			Set<BinaryTextRelation> overlapRelations = Sets.newHashSet();
+			Multimap<Annotation, Annotation> overlaps = HashMultimap.create();
+			for (BinaryTextRelation relation : JCasUtil.select(jCas, BinaryTextRelation.class)) {
+				if (relation.getCategory().equals("OVERLAP")) {
+					overlapRelations.add(relation);
 					Annotation arg1 = relation.getArg1().getArgument();
 					Annotation arg2 = relation.getArg2().getArgument();
-					contains.put(arg1, arg2);
-				}else if (relation.getCategory().equals("BEFORE")) {
-					Annotation arg1 = relation.getArg1().getArgument();
-					Annotation arg2 = relation.getArg2().getArgument();
-					before.put(arg1, arg2);
-					beforeRel.add(relation);
-				}else if (relation.getCategory().equals("ENDS-ON")) {
-					Annotation arg1 = relation.getArg1().getArgument();
-					Annotation arg2 = relation.getArg2().getArgument();
-					endson.put(arg1, arg2);
-					if (!endson.containsEntry(arg2, arg1)) {
-						endson.put(arg2, arg1);
-					}
-				}else if (relation.getCategory().equals("BEGINS-ON")) {
-					Annotation arg1 = relation.getArg1().getArgument();
-					Annotation arg2 = relation.getArg2().getArgument();
-					beginson.put(arg1, arg2);
-					if (!beginson.containsEntry(arg2, arg1)) {
-						beginson.put(arg2, arg1);
-					}
+					overlaps.put(arg1, arg2);
 				}
 			}
 
-			// for A BEFORE B, check if A and B Contain anything
-			for (BinaryTextRelation brelation : beforeRel) {
-				Annotation argA = brelation.getArg1().getArgument();
-				Annotation argB = brelation.getArg2().getArgument();
-				//add contained before
-				for (Annotation childA : contains.get(argA)) {
-					for (Annotation childB : contains.get(argB)) {
-						if (!before.containsEntry(childA, childB)) {
-							//create a new before relation:
-							RelationArgument arg1 = new RelationArgument(jCas);
-							arg1.setArgument(childA);
-							RelationArgument arg2 = new RelationArgument(jCas);
-							arg2.setArgument(childB);
-							BinaryTextRelation relation = new BinaryTextRelation(jCas);
-							relation.setArg1(arg1);
-							relation.setArg2(arg2);
-							relation.setCategory("BEFORE");
-							arg1.addToIndexes();
-							arg2.addToIndexes();
-							relation.addToIndexes();
-							before.put(childA, childB);
+			for (BinaryTextRelation orelation : overlapRelations) {
+				Annotation argA = orelation.getArg1().getArgument();
+				Annotation argB = orelation.getArg2().getArgument();
+				//add overlap 
+				if (!overlaps.containsEntry(argB, argA)) {
+					//create a new flipped relation:
+					RelationArgument arg1 = new RelationArgument(jCas);
+					arg1.setArgument(argB);
+					RelationArgument arg2 = new RelationArgument(jCas);
+					arg2.setArgument(argA);
+					BinaryTextRelation relation = new BinaryTextRelation(jCas);
+					relation.setArg1(arg1);
+					relation.setArg2(arg2);
+					relation.setCategory("OVERLAP");
+					arg1.addToIndexes();
+					arg2.addToIndexes();
+					relation.addToIndexes();
+					overlaps.put(argB, argA);
+				}
+
+			}
+		}
+	}
+	
+	public static class AddClosure extends JCasAnnotator_ImplBase {
+
+		@Override
+		public void process(JCas jCas) throws AnalysisEngineProcessException {
+			
+			Multimap<List<Annotation>, BinaryTextRelation> annotationsToRelation = HashMultimap.create();
+			for (BinaryTextRelation relation : JCasUtil.select(jCas, BinaryTextRelation.class)){
+				String relationType = relation.getCategory();
+				if(validTemporalType(relationType)){
+					Annotation arg1 = relation.getArg1().getArgument();
+			        Annotation arg2 = relation.getArg2().getArgument();
+			        annotationsToRelation.put(Arrays.asList(arg1, arg2), relation);
+				}
+			}
+			for (List<Annotation> span: Lists.newArrayList(annotationsToRelation.keySet())){
+				Collection<BinaryTextRelation> relations = annotationsToRelation.get(span);
+				if(relations.size()>1){//if same span maps to multiple relations
+					Set<String> types = Sets.newHashSet();
+					for(BinaryTextRelation relation: relations){
+						types.add(relation.getCategory());
+					}
+					if(types.size()>1){
+						for(BinaryTextRelation relation: Lists.newArrayList(relations)){
+							annotationsToRelation.remove(span, relation);
+							relation.getArg1().removeFromIndexes();
+							relation.getArg2().removeFromIndexes();
+							relation.removeFromIndexes();
+						}
+					}else if(types.size()==1){
+						for (int i =1; i< relations.size(); i++){
+							BinaryTextRelation relation = (BinaryTextRelation) relations.toArray()[i];
+							annotationsToRelation.remove(span, relation);
+							relation.getArg1().removeFromIndexes();
+							relation.getArg2().removeFromIndexes();
+							relation.removeFromIndexes();
 						}
 					}
 				}
-				//add ends-on A
-				for (Annotation endsOnA : endson.get(argA)) {
-					if (!before.containsEntry(endsOnA, argB)) {
-						//create a new before relation:
-						RelationArgument arg1 = new RelationArgument(jCas);
-						arg1.setArgument(endsOnA);
-						RelationArgument arg2 = new RelationArgument(jCas);
-						arg2.setArgument(argB);
-						BinaryTextRelation relation = new BinaryTextRelation(jCas);
-						relation.setArg1(arg1);
-						relation.setArg2(arg2);
-						relation.setCategory("BEFORE");
-						arg1.addToIndexes();
-						arg2.addToIndexes();
-						relation.addToIndexes();
-						before.put(endsOnA, argB);
+			}
+
+			ArrayList<BinaryTextRelation> temporalRelation = new ArrayList<BinaryTextRelation>(annotationsToRelation.values());//new ArrayList<BinaryTextRelation>();
+//			Map<List<Annotation>, BinaryTextRelation> temporalRelationLookup = new HashMap<List<Annotation>, BinaryTextRelation>();
+//
+//			for (BinaryTextRelation relation : JCasUtil.select(jCas, BinaryTextRelation.class)){
+//				String relationType = relation.getCategory();
+//				if(validTemporalType(relationType)){
+//					Annotation arg1 = relation.getArg1().getArgument();
+//			        Annotation arg2 = relation.getArg2().getArgument();
+//			        BinaryTextRelation tempRelation = temporalRelationLookup.get(Arrays.asList(arg1, arg2));
+//					if( tempRelation == null){
+//						temporalRelation.add(relation);					
+//				        temporalRelationLookup.put(Arrays.asList(arg1, arg2), relation);
+//					}else{//if there is duplicate
+//						relation.getArg1().removeFromIndexes();
+//						relation.getArg2().removeFromIndexes();
+//						relation.removeFromIndexes();
+//					}
+//					
+//				}
+//			}
+
+			if (!temporalRelation.isEmpty()){
+				TLinkTypeArray2 relationArray = new TLinkTypeArray2(temporalRelation, new AnnotationIdCollection(temporalRelation));
+
+				int addedCount = 0;
+				for (BinaryTextRelation relation : relationArray.getClosedTlinks(jCas)) {
+					RelationArgument arg1 = relation.getArg1();
+					RelationArgument arg2 = relation.getArg2();
+					String relationType = relation.getCategory();
+					if(relationType.equals("CONTAINED-BY")||relationType.equals("AFTER")){//ignore these two categories, because their reciprocal already exist.
+						continue;
 					}
-				}
-				//add begins-on B
-				for (Annotation beginsOnB : beginson.get(argB)) {
-					if (!before.containsEntry(argA, beginsOnB)) {
-						//create a new before relation:
-						RelationArgument arg1 = new RelationArgument(jCas);
-						arg1.setArgument(argA);
-						RelationArgument arg2 = new RelationArgument(jCas);
-						arg2.setArgument(beginsOnB);
-						BinaryTextRelation relation = new BinaryTextRelation(jCas);
-						relation.setArg1(arg1);
-						relation.setArg2(arg2);
-						relation.setCategory("BEFORE");
+					//check if the inferred relation new:
+					Collection<BinaryTextRelation> relations = annotationsToRelation.get(Arrays.asList(arg1.getArgument(), arg2.getArgument()));
+					if(relations.isEmpty()){ //if haven't seen this inferred relation before, then add this relation
 						arg1.addToIndexes();
 						arg2.addToIndexes();
 						relation.addToIndexes();
-						before.put(argA, beginsOnB);
-					}
+						addedCount++;
+					}		
 				}
-			}
+				
+				System.out.println( "**************************************************************");
+			    System.out.println( "Finally added closure relations: " + addedCount );
+			    System.out.println( "**************************************************************");
+			}			
+
 		}
 
+		private static boolean validTemporalType(String relationType) {
+			if(relationType.equals("CONTAINS")||relationType.equals("OVERLAP")||relationType.equals("BEFORE")||relationType.equals("ENDS-ON")||relationType.equals("BEGINS-ON"))
+				return true;
+			return false;
+		}
 	}
+
+//	public static class AddTransitiveBeforeAndOnRelations extends JCasAnnotator_ImplBase {
+//
+//		@Override
+//		public void process(JCas jCas) throws AnalysisEngineProcessException {
+//
+//			// collect many-to-many mappings of containment relations 
+//			Multimap<Annotation, Annotation> contains = HashMultimap.create();
+//			Multimap<Annotation, Annotation> before = HashMultimap.create();
+//			Multimap<Annotation, Annotation> endson = HashMultimap.create();
+//			Multimap<Annotation, Annotation> beginson = HashMultimap.create();
+//			Set<BinaryTextRelation> beforeRel = Sets.newHashSet();
+//
+//			for (BinaryTextRelation relation : JCasUtil.select(jCas, BinaryTextRelation.class)) {
+//				if (relation.getCategory().equals("CONTAINS")) {
+//					Annotation arg1 = relation.getArg1().getArgument();
+//					Annotation arg2 = relation.getArg2().getArgument();
+//					contains.put(arg1, arg2);
+//				}else if (relation.getCategory().equals("BEFORE")) {
+//					Annotation arg1 = relation.getArg1().getArgument();
+//					Annotation arg2 = relation.getArg2().getArgument();
+//					before.put(arg1, arg2);
+//					beforeRel.add(relation);
+//				}else if (relation.getCategory().equals("ENDS-ON")) {
+//					Annotation arg1 = relation.getArg1().getArgument();
+//					Annotation arg2 = relation.getArg2().getArgument();
+//					endson.put(arg1, arg2);
+//					if (!endson.containsEntry(arg2, arg1)) {
+//						endson.put(arg2, arg1);
+//					}
+//				}else if (relation.getCategory().equals("BEGINS-ON")) {
+//					Annotation arg1 = relation.getArg1().getArgument();
+//					Annotation arg2 = relation.getArg2().getArgument();
+//					beginson.put(arg1, arg2);
+//					if (!beginson.containsEntry(arg2, arg1)) {
+//						beginson.put(arg2, arg1);
+//					}
+//				}
+//			}
+//
+//			// for A BEFORE B, check if A and B Contain anything
+//			for (BinaryTextRelation brelation : beforeRel) {
+//				Annotation argA = brelation.getArg1().getArgument();
+//				Annotation argB = brelation.getArg2().getArgument();
+//				//add contained before
+//				for (Annotation childA : contains.get(argA)) {
+//					for (Annotation childB : contains.get(argB)) {
+//						if (!before.containsEntry(childA, childB)) {
+//							//create a new before relation:
+//							RelationArgument arg1 = new RelationArgument(jCas);
+//							arg1.setArgument(childA);
+//							RelationArgument arg2 = new RelationArgument(jCas);
+//							arg2.setArgument(childB);
+//							BinaryTextRelation relation = new BinaryTextRelation(jCas);
+//							relation.setArg1(arg1);
+//							relation.setArg2(arg2);
+//							relation.setCategory("BEFORE");
+//							arg1.addToIndexes();
+//							arg2.addToIndexes();
+//							relation.addToIndexes();
+//							before.put(childA, childB);
+//						}
+//					}
+//				}
+//				//add ends-on A
+//				for (Annotation endsOnA : endson.get(argA)) {
+//					if (!before.containsEntry(endsOnA, argB)) {
+//						//create a new before relation:
+//						RelationArgument arg1 = new RelationArgument(jCas);
+//						arg1.setArgument(endsOnA);
+//						RelationArgument arg2 = new RelationArgument(jCas);
+//						arg2.setArgument(argB);
+//						BinaryTextRelation relation = new BinaryTextRelation(jCas);
+//						relation.setArg1(arg1);
+//						relation.setArg2(arg2);
+//						relation.setCategory("BEFORE");
+//						arg1.addToIndexes();
+//						arg2.addToIndexes();
+//						relation.addToIndexes();
+//						before.put(endsOnA, argB);
+//					}
+//				}
+//				//add begins-on B
+//				for (Annotation beginsOnB : beginson.get(argB)) {
+//					if (!before.containsEntry(argA, beginsOnB)) {
+//						//create a new before relation:
+//						RelationArgument arg1 = new RelationArgument(jCas);
+//						arg1.setArgument(argA);
+//						RelationArgument arg2 = new RelationArgument(jCas);
+//						arg2.setArgument(beginsOnB);
+//						BinaryTextRelation relation = new BinaryTextRelation(jCas);
+//						relation.setArg1(arg1);
+//						relation.setArg2(arg2);
+//						relation.setCategory("BEFORE");
+//						arg1.addToIndexes();
+//						arg2.addToIndexes();
+//						relation.addToIndexes();
+//						before.put(argA, beginsOnB);
+//					}
+//				}
+//			}
+//		}
+//
+//	}
 }

Added: ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/utils/AnnotationIdCollection.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/utils/AnnotationIdCollection.java?rev=1588359&view=auto
==============================================================================
--- ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/utils/AnnotationIdCollection.java (added)
+++ ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/utils/AnnotationIdCollection.java Thu Apr 17 20:12:28 2014
@@ -0,0 +1,160 @@
+package org.apache.ctakes.temporal.utils;
+
+import org.apache.ctakes.typesystem.type.relation.BinaryTextRelation;
+import org.apache.uima.jcas.tcas.Annotation;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Author: SPF
+ * Affiliation: CHIP-NLP
+ * Date: 6/17/13
+ */
+public class AnnotationIdCollection {
+
+	static public final int NO_ENTITY_ID = Integer.MIN_VALUE;
+
+
+	// Key = Annotation (named, event, timex), Value = id number for each "unique" reference.
+	// Co-referent entities will have the same id number
+	private final Map<Annotation,Integer> _entityIdMap;
+	// Key = id number for each "unique" reference, value = primary entity
+	private final Map<Integer,Annotation> _idAnnotationMap;
+
+
+	public AnnotationIdCollection(ArrayList<BinaryTextRelation> temporalRelation){ //final AnnotationCollection annotationCollection ) {
+		_entityIdMap = new HashMap<Annotation, Integer>();
+		_idAnnotationMap = new HashMap<Integer, Annotation>();
+		
+		Set<Annotation> allAnnotations = new HashSet<Annotation>();
+		for (BinaryTextRelation relation : temporalRelation) {
+			allAnnotations.add(relation.getArg1().getArgument());
+			allAnnotations.add(relation.getArg2().getArgument());
+		}
+		final List<Annotation> annotationsList = new ArrayList<Annotation>( allAnnotations );
+		Collections.sort( annotationsList, ArgComparator.INSTANCE );// just so that closure counts are consistent
+		
+		int id = 0;
+		for (Annotation annotation : annotationsList) {
+			_entityIdMap.put( annotation, id );
+			_idAnnotationMap.put( id, annotation );
+			id++;			
+		}
+
+		//      int id = 0;
+		//      for ( Annotation entity : annotationCollection.getNamedEntities() ) {
+		//         _entityIdMap.put( entity, id );
+		//         _idAnnotationMap.put( id, entity );
+		//         id++;
+		//      }
+		//      for ( Annotation entity : annotationCollection.getTimes() ) {
+		//         _entityIdMap.put( entity, id );
+		//         _idAnnotationMap.put( id, entity );
+		//         id++;
+		//      }
+		//      for ( Annotation entity : annotationCollection.getEvents() ) {
+		//         _entityIdMap.put( entity, id );
+		//         _idAnnotationMap.put( id, entity );
+		//         id++;
+		//      }
+		//      for ( CoreferenceChain chain : annotationCollection.getCoreferenceEntities() ) {
+		//         for ( Annotation entity : chain ) {
+		//            _entityIdMap.put( entity, id );
+		//         }
+		//         _entityIdMap.put( chain, id );
+		//         _idAnnotationMap.put( id, chain );
+		//         id++;
+		//      }
+
+	}
+
+
+	/**
+	 * @return a collection of unique ids for all unique entities
+	 */
+	public Set<Integer> getAnnotationIds() {
+		//      return Collections.unmodifiableSet( _idAnnotationMap.keySet() );
+		return Collections.unmodifiableSet( new HashSet<Integer>( _entityIdMap.values() ) );
+	}
+
+	/**
+	 * @param entity some entity, be it unique on its own or part of a coreference chain
+	 * @return an id for the entity
+	 */
+	public int getAnnotationId( final Annotation entity ) {
+		final Integer id = _entityIdMap.get( entity );
+		if ( id != null ) {
+			return id;
+		}
+		return getIdByAnnotationEqual( entity );
+	}
+
+	private int getIdByAnnotationEqual( final Annotation entity ) {
+		for ( Annotation referenceAnnotation : _entityIdMap.keySet() ) {
+			if ( referenceAnnotation.equals( entity ) ) {
+				final int id = _entityIdMap.get( referenceAnnotation );
+				// Prevent future iteration searches
+				_entityIdMap.put( entity, id );
+				return id;
+			}
+		}
+		return getIdByTextSpan( entity.getBegin(), entity.getEnd() );
+	}
+
+	private int getIdByTextSpan( final int begin, int end ) {
+		for ( Annotation referenceAnnotation : _entityIdMap.keySet() ) {
+			if ( referenceAnnotation.getBegin()==begin &&  referenceAnnotation.getEnd()==end){//.getTextSpan().equals( textSpan ) ) {
+				return _entityIdMap.get( referenceAnnotation );
+			}
+//			// TODO necessary?
+//			if ( referenceAnnotation instanceof CoreferenceChain ) {
+//				for ( Annotation coreference : (CoreferenceChain)referenceAnnotation ) {
+//					if ( coreference.getTextSpan().equals( textSpan ) ) {
+//						return _entityIdMap.get( referenceAnnotation );
+//					}
+//				}
+//			}
+		}
+		return NO_ENTITY_ID;
+	}
+
+
+	/**
+	 * @param entityId some id
+	 * @return the NamedAnnotation, Event, Timex, or CoreferenceChain with the given referenceId
+	 */
+	public Annotation getAnnotation( final int entityId ) {
+		return _idAnnotationMap.get( entityId );
+	}
+
+	public Annotation getAnnotation( final Annotation entity ) {
+		final int id = getAnnotationId( entity );
+		if ( id != NO_ENTITY_ID ) {
+			return getAnnotation( id );
+		}
+		return null;
+	}
+	
+	
+	static private enum ArgComparator implements Comparator<Annotation> {
+		INSTANCE;
+		/**
+		 * {@inheritDoc}
+		 */
+		public int compare( final Annotation arg1, final Annotation arg2 ) {
+			final int startDiff = arg1.getBegin() - arg2.getBegin();
+			if ( startDiff != 0 ) {
+				return startDiff;
+			}
+			return arg1.getEnd() - arg2.getEnd();
+		}		
+	}
+
+}

Propchange: ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/utils/AnnotationIdCollection.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/utils/TLinkTypeArray2.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/utils/TLinkTypeArray2.java?rev=1588359&view=auto
==============================================================================
--- ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/utils/TLinkTypeArray2.java (added)
+++ ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/utils/TLinkTypeArray2.java Thu Apr 17 20:12:28 2014
@@ -0,0 +1,477 @@
+package org.apache.ctakes.temporal.utils;
+
+import org.apache.ctakes.temporal.utils.AnnotationIdCollection;
+import org.apache.ctakes.typesystem.type.relation.BinaryTextRelation;
+import org.apache.ctakes.typesystem.type.relation.RelationArgument;
+import org.apache.uima.jcas.JCas;
+import org.apache.uima.jcas.tcas.Annotation;
+
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import static org.apache.ctakes.temporal.utils.TlinkType.AFTER;
+import static org.apache.ctakes.temporal.utils.TlinkType.BEFORE;
+import static org.apache.ctakes.temporal.utils.TlinkType.BEGINS_ON;
+import static org.apache.ctakes.temporal.utils.TlinkType.CONTAINS;
+import static org.apache.ctakes.temporal.utils.TlinkType.ENDS_ON;
+import static org.apache.ctakes.temporal.utils.TlinkType.OVERLAP;
+
+/**
+ * Author: SPF
+ * Affiliation: CHIP-NLP
+ * Date: 6/18/13
+ */
+public class TLinkTypeArray2 {
+
+   // given relation A to B and relation B to C, return relation A to C
+
+   /**
+    * @param tlinkTypesAtoB for a relation with an end argument coincidental with (relationType23's relation), the store
+    * @param tlinkTypesBtoC for a relation with a start argument coincidental with (relationType12's relation), the store
+    * @return for a relation with the start argument of (relationTypeAtoB's relations) and the end argument of
+    *         (relationTypeBtoC's relations), the set of time relations if one can be derived from the first two other sets, else null
+    */
+   static private TlinkTypeSet getTlinkTypesAtoC( final TlinkTypeSet tlinkTypesAtoB,
+                                                  final TlinkTypeSet tlinkTypesBtoC ) {
+      if ( tlinkTypesAtoB == null || tlinkTypesBtoC == null
+            || tlinkTypesAtoB.isEmpty() || tlinkTypesBtoC.isEmpty() ) {
+         return null;
+      }
+      final TlinkTypeSet tlinkTypeSetAtoC = new TlinkTypeSet();
+      for ( TlinkType tlinkTypeAtoB : tlinkTypesAtoB ) {
+         for ( TlinkType tlinkTypeBtoC : tlinkTypesBtoC ) {
+            final TlinkType tertiary = tlinkTypeAtoB.getTimeRelationTypeAtoC( tlinkTypeBtoC );
+            if ( tertiary != null ) {
+               tlinkTypeSetAtoC.add( tertiary );
+            }
+         }
+      }
+      return tlinkTypeSetAtoC;
+   }
+
+
+
+   //  Array of relation types for each event/time to other event/time
+   private final TlinkTypeSet[][] _tlinkTypesArray;
+   //  map of entity ids in relations and their corresponding column/row indices in _tlinkTypesArray
+   // Key = entity id, Value = column/row index
+//   private final Map<Integer, Integer> _entityIdIndices;
+
+   private final AnnotationIdCollection _entityIdCollection;
+   private final List<Integer> _entityIdList;
+
+//   public TLinkTypeArray2( final AnnotationCollection annotationCollection ) {
+//      this( annotationCollection.getTimeRelations(), annotationCollection.getReferenceCollection() );
+//   }
+
+   public TLinkTypeArray2( final List<BinaryTextRelation> tlinkList, final AnnotationIdCollection entityIdCollection ) {
+      final Set<Integer> tlinkAnnotationIds = new HashSet<Integer>();
+      for ( BinaryTextRelation tlink : tlinkList ) {
+         // Add all entities, even for relations that have no valid relation type
+         tlinkAnnotationIds.add( entityIdCollection.getAnnotationId( tlink.getArg1().getArgument() ) );
+         tlinkAnnotationIds.add( entityIdCollection.getAnnotationId( tlink.getArg2().getArgument() ) );
+      }
+      _entityIdList = new ArrayList<Integer>( tlinkAnnotationIds );
+      Collections.sort( _entityIdList ); // just so that -reported- closure counts are consistent
+      final int entityCount = _entityIdList.size();
+      _tlinkTypesArray = new TlinkTypeSet[entityCount][entityCount];
+      _entityIdCollection = entityIdCollection;
+      populateTlinkTypesArray( tlinkList );
+   }
+
+   public TlinkTypeSet getTlinkTypes( final BinaryTextRelation tlink ) {
+      final Annotation entityA = tlink.getArg1().getArgument();
+      final Annotation entityB = tlink.getArg2().getArgument();
+      final int entityIdA = _entityIdCollection.getAnnotationId( entityA );
+      final int entityIdB = _entityIdCollection.getAnnotationId( entityB );
+      final int indexA = _entityIdList.indexOf( entityIdA );
+      final int indexB = _entityIdList.indexOf( entityIdB );
+      return getTlinkTypes( indexA, indexB );
+   }
+
+   public List<BinaryTextRelation> getClosedTlinks(JCas jCas) {
+      final int length = getAnnotationIdCount();
+      if ( length == 0 ) {
+         return Collections.emptyList();
+      }
+      final List<BinaryTextRelation> closedTlinks = new ArrayList<BinaryTextRelation>();
+      for ( int row = 0; row<length; row++ ) {
+         for ( int column = 0; column<length; column++ ) {
+            if ( row == column ) {
+               continue;
+            }
+            final TlinkTypeSet tlinkTypeSet = _tlinkTypesArray[row][column];
+            if (  tlinkTypeSet == null || tlinkTypeSet.isEmpty() ) {
+               continue;
+            }
+            for ( TlinkType tlinkType : tlinkTypeSet ) {
+               final BinaryTextRelation tlink = createTlink(jCas, row, column, tlinkType );
+               if ( tlink != null ) {
+//                  System.out.println(row+","+column+" "+tlink.getFirstAnnotation().getSpannedText()+ " " + tlinkType + " " + tlink.getSecondAnnotation().getSpannedText());
+                  closedTlinks.add( tlink );
+               }
+            }
+         }
+      }
+      return closedTlinks;
+   }
+
+   private BinaryTextRelation createTlink( final JCas jCas, int row, final int column, final TlinkType tlinkType ) {
+	   //      final ClassType tlinkClass = new CustomClassType( "TLINK" );
+	   final Annotation entityA = getAnnotation( row );
+	   final Annotation entityB = getAnnotation( column );
+	   if ( entityA == null || entityB == null ) {
+		   return null;
+	   }
+	   //      final Attribute tlinkAttribute = tlinkType.getAsAttribute();
+	   ////      if ( entityB instanceof Timex ) {
+	   ////         System.out.println( "TRTA2 " + entityA.getSpannedText() + " " + tlinkType.getValue() + " " + entityB.getSpannedText() + " " + timeRelationType );
+	   ////      }
+	   //      return new DefaultRelation( entityA, entityB, tlinkClass, "Closure", tlinkAttribute );
+	   RelationArgument arg1 = new RelationArgument(jCas);
+	   arg1.setArgument(entityA);
+	   RelationArgument arg2 = new RelationArgument(jCas);
+	   arg2.setArgument(entityB);
+	   BinaryTextRelation relation = new BinaryTextRelation(jCas);
+	   relation.setArg1(arg1);
+	   relation.setArg2(arg2);
+	   relation.setCategory(tlinkType.name().replace( "_", "-" ));//check if this is correct
+	   return relation;
+   }
+
+   private int getAnnotationId( final int index ) {
+      return _entityIdList.get( index );
+   }
+
+   private Annotation getAnnotation( final int index ) {
+      final int entityId = getAnnotationId( index );
+      return _entityIdCollection.getAnnotation( entityId );
+   }
+
+   //   --------------------  Population of array  --------------------   //
+
+   private void populateTlinkTypesArray( final List<BinaryTextRelation> tlinkList ) {
+      // initialize array with existing known time relation types
+      int explicitCount = 0;
+      for ( BinaryTextRelation tlink : tlinkList ) {
+         if ( addTlinkType( tlink ) ) {
+            explicitCount += 2;
+         }
+      }
+      // add to array inferred time relation types
+      final int entityIdCount = getAnnotationIdCount();
+      // column
+      int inferredInIteration = -1; // seed
+      int iterations = 0;
+      int totalInferred = 0;
+      while (inferredInIteration != 0 ) {
+         inferredInIteration = 0;
+         for ( int index = 0; index < entityIdCount; index++ ) {
+            inferredInIteration += inferForIndex( index );
+         }
+         totalInferred += inferredInIteration;
+         iterations++;
+      }
+      // TODO What follows is just info
+      int tlinkCount = 0;
+      for ( int i=0; i<entityIdCount; i++ ) {
+          for ( int j=0; j<entityIdCount; j++ ) {
+             if ( _tlinkTypesArray[i][j] != null ) {
+                tlinkCount += _tlinkTypesArray[i][j].size();
+//                System.out.println( i+","+j+" " + getAnnotation( i ).getSpannedText() + " " +_tlinkTypesArray[i][j] + " " + getAnnotation( j ).getSpannedText());
+             }
+          }
+      }
+      System.out.println( "===================================================================================");
+      System.out.println( "   Marked Entities: " + entityIdCount
+                          + ", Marked TLinks: " + tlinkList.size()
+                          + ", Proper TLinks: " + explicitCount
+                          + ", Inferred TLinks: " + totalInferred
+                          + ", Total TLinks: " + tlinkCount
+                          + ", Iterations: " + iterations );
+      System.out.println( "===================================================================================");
+   }
+
+
+   private int inferForIndex( final int indexA ) {
+      final int entityIdCount = getAnnotationIdCount();
+      int inferredCount = 0;
+      for ( int indexB = 0; indexB < entityIdCount; indexB++ ) {
+         if ( indexA == indexB ) {
+            continue;
+         }
+         final TlinkTypeSet tlinkTypesAtoB = getTlinkTypes( indexA, indexB );
+         if ( tlinkTypesAtoB == null ) {
+            // No time relation types for cell, can't infer something from nothing, move on
+            continue;
+         }
+         for ( int indexC = 0; indexC < entityIdCount; indexC++ ) {
+            if ( indexC == indexA || indexC == indexB ) {
+               continue;
+            }
+            final TlinkTypeSet tlinkTypesBtoC = getTlinkTypes( indexB, indexC );
+            if ( tlinkTypesBtoC == null ) {
+               // No time relation types for cell, can't infer something from nothing, move on
+               continue;
+            }
+            inferredCount += inferTlinkTypesForIndexAtoBtoC( indexA, indexB, indexC,
+                                                             tlinkTypesAtoB, tlinkTypesBtoC );
+            if ( !hasTlinkType( indexA, indexB, OVERLAP ) ) {
+               // search for overlap between two nodes marked overlap
+               inferredCount += inferTlinkTypesForAnnotationAtoBwithCandD( indexA, indexB, indexC, OVERLAP );
+            }
+            if ( !hasTlinkType( indexA, indexB, CONTAINS ) ) {
+               // search for overlap between two nodes marked contains
+               inferredCount += inferTlinkTypesForAnnotationAtoBwithCandD( indexA, indexB, indexC, CONTAINS );
+            }
+         }
+      }
+      return inferredCount;
+   }
+
+   private int inferTlinkTypesForIndexAtoBtoC( final int indexA, @SuppressWarnings("unused") final int indexB, final int indexC,
+                                               final TlinkTypeSet tlinkTypesAtoB,
+                                               final TlinkTypeSet tlinkTypesBtoC ) {
+      int addedCount = 0;
+      final TlinkTypeSet tlinkTypesAtoC = getTlinkTypesAtoC( tlinkTypesAtoB,
+                                                                    tlinkTypesBtoC );
+      //         // DEBUG
+//               final int lastCount = addedCount;
+      //         // END DEBUG
+      addedCount += addTlinkTypes( indexA, indexC, tlinkTypesAtoC );
+      //         // DEBUG
+//               if ( addedCount > lastCount ) {
+//                  System.out.println( indexA + " " + timeRelationTypesAtoB + " " + indexB + ", "
+//                                            + indexB  + " " + timeRelationTypesBtoC + " " + indexC + " "
+//                                            + " ~ " + indexA + " " + timeRelationTypesAtoC + " " + indexC
+//                                            + " & " + indexC + " " + timeRelationTypesAtoC.createReciprocals() + " " + indexA );
+//               }
+      //         // END DEBUG
+      return addedCount;
+   }
+
+   // search overlap between two nodes marked overlap   or  contains between two nodes marked contains
+   private int inferTlinkTypesForAnnotationAtoBwithCandD( final int indexA, final int indexB, final int indexC,
+                                                      final TlinkType tlinkType ) {
+      final int entityCount = getAnnotationIdCount();
+      int addedCount = 0;
+      // if A ov C && A ov D, C < B || C eo B, B < D || D bo B, then A ov B   ( A ov C < B < D ov A )
+      // if A cn C && A cn D, (C < B || C eo B), (B < D || D bo B), then A cn B   ( A cn C < B < D cn A )
+      if ( hasTlinkType( indexA, indexC, tlinkType ) ) {
+         // A ov C   or   A cn C
+         for ( int indexD = 0; indexD < entityCount; indexD++ ) {
+            if ( indexD == indexA || indexD == indexB || indexD == indexC ) {
+               continue;
+            }
+            if ( hasTlinkType( indexA, indexD, tlinkType ) ) {
+               // A ov D   or   A cn D
+               // TODO This needs to be changed so two before/after make a contained and begins/ends-on makes overlap
+               if ( (hasTlinkType( indexB, indexC, AFTER )
+                     || hasTlinkType( indexB, indexC, BEGINS_ON ))
+                     && (hasTlinkType( indexB, indexD, BEFORE )
+                     || hasTlinkType( indexB, indexD, ENDS_ON )) ) {
+                  // A ov C < B < D ov A, therefore A ov B   or   A cn C < B < D cn A, therefore A cn B
+                  if ( addTlinkType( indexA, indexB, tlinkType ) ) {
+                     addedCount++;
+                  }
+               }
+            }
+         }
+      }
+      return addedCount;
+   }
+
+
+   private boolean isIndexOk( final int entityIndex ) {
+      return entityIndex >= 0 && entityIndex < getAnnotationIdCount();
+   }
+
+   private int getAnnotationIdCount() {
+      return _entityIdList.size();
+   }
+
+   private boolean hasTlinkType( final int indexA, final int indexB,
+                                 final TlinkType tlinkType ) {
+      if ( indexA == indexB ) {
+         // entities are the same, therefore no relationship
+         return false;
+      }
+      final TlinkTypeSet tlinkTypes = getTlinkTypes( indexA, indexB );
+      return tlinkTypes != null && tlinkTypes.contains( tlinkType );
+   }
+
+   private TlinkTypeSet getTlinkTypes( final int indexA, final int indexB ) {
+      if ( indexA == indexB || !isIndexOk( indexA ) || !isIndexOk( indexB ) ) {
+         return null;
+      }
+      return _tlinkTypesArray[indexA][indexB];
+   }
+
+   private int addTlinkTypes( final int indexA, final int indexC,
+                              final TlinkTypeSet tlinkTypes ) {
+      if ( tlinkTypes == null || tlinkTypes.isEmpty()
+            || !isIndexOk( indexA ) || !isIndexOk( indexC ) ) {
+         return 0;
+      }
+      if ( _tlinkTypesArray[indexA][indexC] == null ) {
+         _tlinkTypesArray[indexA][indexC] = tlinkTypes;
+         _tlinkTypesArray[indexC][indexA] = tlinkTypes.createReciprocals();
+         return 2;
+      }
+      int addedCount = 0;
+      if ( _tlinkTypesArray[indexC][indexA] == null ) {
+         _tlinkTypesArray[indexC][indexA] =  new TlinkTypeSet();
+      }
+      for ( TlinkType tlinkType : tlinkTypes ) {
+//         if  ( getAnnotation(indexC) instanceof Timex && getAnnotation(indexA) instanceof Timex ) {
+//            System.out.println( getAnnotation(indexA).getSpannedText() + " " + relationType  + " " + getAnnotation(indexC).getSpannedText() );
+//         }
+         boolean added = _tlinkTypesArray[indexA][indexC].add( tlinkType );
+         if ( added ) {
+            addedCount++;
+         }
+         added = _tlinkTypesArray[indexC][indexA].add( tlinkType.getReciprocal() );
+         if ( added ) {
+            addedCount++;
+         }
+      }
+      return addedCount;
+   }
+
+
+
+
+
+   ///////////       Add TlinkType       /////////////
+
+   private boolean addTlinkType( final BinaryTextRelation tlink ) {
+      // Checked and ok 7/10/13 spf
+      final TlinkType tlinkType = TlinkType.getTlinkType( tlink );
+      if ( tlinkType == null ) {
+         return false;
+      }
+      final boolean added1 = addTlinkType( tlink.getArg1().getArgument(), tlink.getArg2().getArgument(),
+                                           tlinkType );
+      // Add reciprocal
+      final boolean added2 = addTlinkType( tlink.getArg2().getArgument(), tlink.getArg1().getArgument(),
+                                           tlinkType.getReciprocal() );
+      return added1 || added2;
+   }
+
+   private boolean addTlinkType( final Annotation entityA, final Annotation entityB,
+                                 final TlinkType tlinkType ) {
+      // Checked and ok 7/12/13 spf
+      final int entityIdA = _entityIdCollection.getAnnotationId( entityA );
+      final int entityIdB = _entityIdCollection.getAnnotationId( entityB );
+      return addTlinkType( entityIdA, entityIdB, tlinkType );
+   }
+
+   private boolean addTlinkType( final int entityIdA, final int entityIdB,
+                                 final TlinkType tlinkType ) {
+      // Checked and ok 7/12/13 spf
+      final int indexA = _entityIdList.indexOf( entityIdA );
+      final int indexB = _entityIdList.indexOf( entityIdB );
+      if ( tlinkType == null || !isIndexOk( indexA ) || !isIndexOk( indexB ) ) {
+         return false;
+      }
+      if ( _tlinkTypesArray[indexA][indexB] == null ) {
+         _tlinkTypesArray[indexA][indexB] = new TlinkTypeSet();
+      }
+      return _tlinkTypesArray[indexA][indexB].add( tlinkType );
+   }
+
+
+
+
+//
+//      // for testing
+//   static private final String XML_UMLS_FILE_PATH
+//         = "C:\\Spiffy\\Data\\THYME2\\Gold\\UMLS\\set08\\ID008_clinic_024.knowtator.xml";
+//   static private final String XML_THYME_FILE_PATH
+//         = "C:\\Spiffy\\Data\\THYME2\\Gold\\THYME\\Set08\\ID008_clinic_024.knowtator.xml";
+//   static private final String XML_CHAIN_FILE_PATH
+//         = "C:\\Spiffy\\Data\\THYME2\\Gold\\THYME_Chains\\Set08\\ID008_clinic_024.chains";
+//
+//
+//   static private AnnotationCollection getAnnotationCollection( final String filePath ) {
+//      final KnowtatorXmlParser xmlParser = new KnowtatorXmlParser();
+//      xmlParser.parseFile( filePath );
+//      return xmlParser.getAnnotationCollection();
+//   }
+//
+//   static private java.util.List<CoreferenceChain> getCoreferenceCollection( final String filePath,
+//                                                                             final Collection<Event> eventCollection,
+//                                                                             final Collection<Annotation> entityCollection ) {
+//      final java.util.List<Set<TextSpan>> textSpanChains = new ArrayList<Set<TextSpan>>();
+//      try {
+//         final BufferedReader reader = new BufferedReader( new FileReader( filePath ) );
+//         String line = reader.readLine();
+//         while ( line != null ) {
+//            final Set<TextSpan> textSpans = new HashSet<TextSpan>();
+//            final String[] indicesArray = line.split( "\\s+" );
+//            for ( String textSpanIndices : indicesArray ) {
+//               final String[] indices = textSpanIndices.split( "-" );
+//               final int start = Integer.parseInt( indices[0] );
+//               final int end = Integer.parseInt( indices[1] );
+//               textSpans.add( new DefaultTextSpan( start, end ) );
+//            }
+//            textSpanChains.add( textSpans );
+//            line = reader.readLine();
+//         }
+//      } catch ( IOException ioE ) {
+//         System.err.println( "Couldn't read coreference chain file " + filePath );
+//         System.err.println( ioE.getMessage() );
+//         return Collections.emptyList();
+//      }
+//
+//      final Set<CoreferenceChain> chains = new HashSet<CoreferenceChain>();
+//      for ( Set<TextSpan> textSpanChain : textSpanChains ) {
+//         final HashSet<Annotation> entitySet = new HashSet<Annotation>(0);
+//         for ( TextSpan elementSpan : textSpanChain ) {
+//            for ( Event event : eventCollection ) {
+//               final TextSpan overlapSpan = elementSpan.getIntersectionSpan( event.getTextSpan() );
+//               if ( overlapSpan != null && overlapSpan.getLength() > 0 ) {
+//                  entitySet.add( event );
+//               }
+//            }
+//            for ( Annotation entity : entityCollection ) {
+//               final TextSpan overlapSpan = elementSpan.getIntersectionSpan( entity.getTextSpan() );
+//               if ( overlapSpan != null && overlapSpan.getLength() > 0 ) {
+//                  entitySet.add( entity );
+//               }
+//            }
+//         }
+//         if ( entitySet.size() > 1 ) {
+//            chains.add( new DefaultAnnotationChain( "TLinkTypeArray2", entitySet.toArray( new Annotation[entitySet.size()] ) ) );
+//         }
+//      }
+//
+//      return new ArrayList<CoreferenceChain>( chains );
+//   }
+//
+//
+//   public static void main( String[] args ) {
+//      final AnnotationCollection thymeAnnotationCollection = getAnnotationCollection( XML_THYME_FILE_PATH );
+//      final AnnotationCollection umlsAnnotationCollection = getAnnotationCollection( XML_UMLS_FILE_PATH );
+//      final java.util.List<CoreferenceChain> coreferenceChains = getCoreferenceCollection( XML_CHAIN_FILE_PATH,
+//                                                                                           thymeAnnotationCollection.getEvents(),
+//                                                                                           umlsAnnotationCollection.getNamedEntities() );
+//      final AnnotationCollection coreferenceCollection
+//            = new ImmutableAnnotationCollection.AnnoteCollectBuilder().coreferenceChains( coreferenceChains ).build();
+//
+//      final java.util.List<AnnotationCollection> annotationCollectionList = new ArrayList<AnnotationCollection>( 2 );
+//      annotationCollectionList.add( thymeAnnotationCollection );
+//      annotationCollectionList.add( umlsAnnotationCollection );
+//      annotationCollectionList.add( coreferenceCollection );
+//      final AnnotationCollection annotationCollection
+//            = new ImmutableAnnotationCollection.AnnoteCollectMerger().all( annotationCollectionList ).build();
+//
+//      new TLinkTypeArray2( annotationCollection );
+//   }
+
+
+}

Propchange: ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/utils/TLinkTypeArray2.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/utils/TimeRelationConstants.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/utils/TimeRelationConstants.java?rev=1588359&view=auto
==============================================================================
--- ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/utils/TimeRelationConstants.java (added)
+++ ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/utils/TimeRelationConstants.java Thu Apr 17 20:12:28 2014
@@ -0,0 +1,17 @@
+package org.apache.ctakes.temporal.utils;
+
+/**
+ * Author: SPF
+ * Affiliation: CHIP-NLP
+ * Date: 4/17/13
+ */
+public interface TimeRelationConstants {
+   int NO = -1;
+   int BF = 0;
+   int AF = 1;
+   int CN = 2;
+   int CB = 3;
+   int BO = 4;
+   int EO = 5;
+   int OV = 6;
+}

Propchange: ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/utils/TimeRelationConstants.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/utils/TlinkType.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/utils/TlinkType.java?rev=1588359&view=auto
==============================================================================
--- ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/utils/TlinkType.java (added)
+++ ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/utils/TlinkType.java Thu Apr 17 20:12:28 2014
@@ -0,0 +1,261 @@
+package org.apache.ctakes.temporal.utils;
+
+import org.apache.ctakes.typesystem.type.relation.BinaryTextRelation;
+
+import static org.apache.ctakes.temporal.utils.TimeRelationConstants.AF;
+import static org.apache.ctakes.temporal.utils.TimeRelationConstants.BF;
+import static org.apache.ctakes.temporal.utils.TimeRelationConstants.BO;
+import static org.apache.ctakes.temporal.utils.TimeRelationConstants.CB;
+import static org.apache.ctakes.temporal.utils.TimeRelationConstants.CN;
+import static org.apache.ctakes.temporal.utils.TimeRelationConstants.EO;
+import static org.apache.ctakes.temporal.utils.TimeRelationConstants.NO;
+import static org.apache.ctakes.temporal.utils.TimeRelationConstants.OV;
+
+/**
+ * Enumeration of the three temporal relation types used in THYME (before, overlap, contains)
+ * and their reciprocals (after, overlap, contained_by)
+ * Begins-on and Ends-on added 4-11-2013
+ */
+public enum TlinkType {
+   BEFORE( BF ),        // A+ < B-        where + is end, - is start
+   AFTER( AF ),         // A- > B+
+   OVERLAP( OV ),       // A- < B- < A+  ||  B- < A- < B+
+   CONTAINS( CN ),      // A- < B- && A+ > B+
+   CONTAINED_BY( CB ),  // A- > B- && A+ < B+
+   BEGINS_ON( BO ),     // A- = B+
+   ENDS_ON( EO );       // A+ = B-
+//   INITIATES( IN )
+//   CONTINUES( CT )
+//   REINITIATES( RE )
+
+   // TODO refactor to use TlinkAttributeValue enum
+
+   static public TlinkType getTlinkType( final BinaryTextRelation tlink ) {
+      final String type = tlink.getCategory();
+      if ( type == null ) {
+         return null;
+      }
+      return getTimeRelationType( type );
+   }
+
+   static public TlinkType getTimeRelationType( final String name ) {
+      final String upper = name.toUpperCase().replace( "_", "-" );
+      if ( upper.equals( "BEFORE" ) ) {
+         return BEFORE;
+      } else if ( upper.equals( "AFTER" ) ) {
+         return AFTER; // Special case for symmetry
+      } else if ( upper.equals( "OVERLAP" ) || upper.equals( "UNDEFINED" ) || upper.isEmpty() ) {
+         return OVERLAP;
+      } else if ( upper.equals( "CONTAINS" ) ) {
+         return CONTAINS;
+      } else if ( upper.equals( "CONTAINED-BY" ) ) {
+         return CONTAINED_BY; // Special case for symmetry
+//      } else if ( upper.equals( "BEGINS-ON" ) ) {
+      } else if ( upper.equals( "BEGINS-ON" ) || upper.equals( "CONTINUES" ) || upper.equals( "TERMINATES" ) ) {
+         return BEGINS_ON;
+//      } else if ( upper.equals( "ENDS-ON" ) ) {
+      } else if ( upper.equals( "ENDS-ON" ) || upper.equals( "INITIATES" ) || upper.equals( "REINITIATES" ) ) {
+         return ENDS_ON;
+      }
+      return null;
+   }
+
+   static public TlinkType getTimeRelationType( final long startA, final long startB,
+                                                       final long endA, final long endB ) {
+      if ( endA < startB ) {
+         return BEFORE;
+      } else if ( startA > endB ) {
+         return AFTER;
+      } else if ( endA == startB ) {
+         return ENDS_ON;
+      } else if ( startA == endB ) {
+         return BEGINS_ON;
+      }
+      final long startCompare = startA - startB;
+      final long endCompare = endA - endB;
+      if ( startCompare < 0 && endCompare > 0 ) {
+         return CONTAINS;
+      } else if ( startCompare > 0 && endCompare < 0 ) {
+         return CONTAINED_BY;
+      } else if ( startCompare == 0 && endCompare > 0 ) {
+         return BEGINS_ON;
+      } else if ( startCompare < 0 && endCompare == 0 ) {
+         return ENDS_ON;
+      }
+      return OVERLAP;
+   }
+
+   static public TlinkType getCombinedTypeConservative( final TlinkType typeA,
+                                                               final TlinkType typeB ) {
+      if ( typeA == typeB ) {
+         return typeA;
+      }
+      return OVERLAP;
+   }
+
+   @SuppressWarnings("incomplete-switch")
+static public TlinkType getCombinedTypeLiberal( final TlinkType typeA,
+                                                          final TlinkType typeB ) {
+      if ( typeA == typeB ) {
+         return typeA;
+      }
+      if ( typeA == typeB.getReciprocal() ) {
+         return OVERLAP;
+      }
+      switch ( typeA ) {
+         case BEFORE: {
+            switch ( typeB ) {
+               case CONTAINS: return ENDS_ON;
+               case CONTAINED_BY: return ENDS_ON;
+               case BEGINS_ON: return CONTAINS;
+               case ENDS_ON: return ENDS_ON;
+               case OVERLAP: return ENDS_ON;
+            }
+         }
+         case AFTER: {
+            switch ( typeB ) {
+               case CONTAINS: return BEGINS_ON;
+               case CONTAINED_BY: return BEGINS_ON;
+               case BEGINS_ON: return BEGINS_ON;
+               case ENDS_ON: return CONTAINS;
+               case OVERLAP: return BEGINS_ON;
+            }
+         }
+         case CONTAINS: {
+            switch ( typeB ) {
+               case BEGINS_ON: return BEGINS_ON;
+               case ENDS_ON: return ENDS_ON;
+               case OVERLAP: return CONTAINS;
+            }
+         }
+         case CONTAINED_BY: {
+            switch ( typeB ) {
+               case BEGINS_ON: return BEGINS_ON;
+               case ENDS_ON: return ENDS_ON;
+               case OVERLAP: return CONTAINED_BY;
+            }
+         }
+         case OVERLAP: {
+            switch ( typeB ) {
+               case BEGINS_ON: return BEGINS_ON;
+               case ENDS_ON: return ENDS_ON;
+            }
+         }
+      }
+      return getCombinedTypeLiberal( typeB, typeA );
+   }
+
+
+   static private TlinkType getTimeRelationType( final int index ) {
+      switch ( index ) {
+         case BF : return BEFORE;
+         case AF : return AFTER;
+         case CN : return CONTAINS;
+         case CB : return CONTAINED_BY;
+         case BO : return BEGINS_ON;
+         case EO : return ENDS_ON;
+         case OV : return OVERLAP;
+      }
+      return null;
+   }
+
+   // Given relation A to B and relation B to C, return relation A to C
+   // This is a very conservative interpretation.
+   // There are several OV possibilities that are left out because CN is an equal possibility
+//   static private final int[][] TML_ABC_ARRAY =
+//         //BF, AF, CN, CB, BO, EO, OV                   A to B
+//         {{BF, NO, NO, BF, NO, BF, NO},  // BF
+//          {NO, AF, NO, AF, AF, NO, NO},  // AF
+//          {BF, AF, CN, NO, AF, BF, NO},  // CN
+//          {NO, NO, OV, CB, NO, NO, NO},  // CB           B to C
+//          {NO, AF, NO, AF, AF, OV, NO},  // BO
+//          {BF, NO, NO, BF, OV, BF, NO},  // EO
+//          {NO, NO, NO, NO, NO, NO, NO}}; // OV     then A to C
+
+//   static private final int[][] TML_ABC_ARRAY =
+//         //BF, AF, CN, CB, BO, EO, OV                   A to B
+//         {{BF, NO, NO, BF, NO, BF, NO},  // BF
+//          {NO, AF, NO, AF, AF, NO, NO},  // AF
+//          {BF, AF, CN, NO, AF, BF, NO},  // CN
+//          {NO, NO, OV, CB, OV, OV, OV},  // CB           B to C
+//          {NO, AF, OV, AF, AF, OV, NO},  // BO
+//          {BF, AF, OV, BF, OV, BF, NO},  // EO
+//          {NO, NO, OV, NO, NO, NO, NO}}; // OV     then A to C
+
+   static private final int[][] TML_ABC_ARRAY =
+         //BF, AF, CN, CB, BO, EO, OV                   A to B
+         {{BF, NO, NO, BF, NO, BF, NO},  // BF
+          {NO, AF, NO, AF, AF, NO, NO},  // AF
+          {BF, AF, CN, NO, AF, BF, NO},  // CN
+          {NO, NO, OV, CB, OV, OV, OV},  // CB           B to C
+          {NO, AF, NO, AF, AF, OV, NO},  // BO
+          {BF, AF, NO, BF, OV, BF, NO},  // EO
+          {NO, NO, OV, NO, NO, NO, NO}}; // OV     then A to C
+
+   final private int _index;
+
+   private TlinkType( final int index ) {
+      _index = index;
+   }
+
+   private int getIndex() {
+      return _index;
+   }
+
+   /**
+    * @param tlinkTypeBtoC a relation with a start argument coincidental with this relation
+    * @return for this relation A to B and the given relation B to C, return relation A to C
+    */
+   public TlinkType getTimeRelationTypeAtoC( final TlinkType tlinkTypeBtoC ) {
+      // The array elements are fetched [row][column]
+      // Checked and works 7/10/13 spf
+      final int relationIndex = TML_ABC_ARRAY[tlinkTypeBtoC.getIndex()][getIndex()];
+//      System.out.println( "A " + toString() + " B and B " + relationTypeBtoC + " C so A " + getTlinkType( relationIndex ) + " C");
+      return getTimeRelationType( relationIndex );
+   }
+
+   /**
+    * @return the reciprocal Temporal Relation type of (this) relation type
+    */
+   public TlinkType getReciprocal() {
+      switch ( this ) {
+         case BEFORE:
+            return AFTER;
+         case AFTER:
+            return BEFORE;
+         case OVERLAP:
+            return OVERLAP;
+         case CONTAINS:
+            return CONTAINED_BY;
+         case CONTAINED_BY:
+            return CONTAINS;
+         case BEGINS_ON:
+            return ENDS_ON;
+         case ENDS_ON:
+            return BEGINS_ON;
+      }
+      return null;
+   }
+
+//   public Attribute getAsAttribute() {
+//      final String attributeValue  = getAttributeValue( this );
+//      return new DefaultAttribute( DefinedAttributeType.RELATION_TYPE, attributeValue );
+//   }
+
+//   static private String getAttributeValue( final TlinkType tlinkType ) {
+//      switch ( tlinkType ) {
+//         case BEFORE: return "BEFORE";
+//         case AFTER : return "AFTER";
+//         case OVERLAP : return "OVERLAP";
+//         case CONTAINS: return "CONTAINS";
+//         case CONTAINED_BY: return "CONTAINED-BY";
+//         case BEGINS_ON: return "BEGINS-ON";
+//         case ENDS_ON: return "ENDS-ON";
+//      }
+//      return null;
+//   }
+
+
+
+
+}

Propchange: ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/utils/TlinkType.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/utils/TlinkTypeSet.java
URL: http://svn.apache.org/viewvc/ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/utils/TlinkTypeSet.java?rev=1588359&view=auto
==============================================================================
--- ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/utils/TlinkTypeSet.java (added)
+++ ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/utils/TlinkTypeSet.java Thu Apr 17 20:12:28 2014
@@ -0,0 +1,109 @@
+package org.apache.ctakes.temporal.utils;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+* Author: SPF
+* Affiliation: CHIP-NLP
+* Date: 4/17/13
+*/
+public class TlinkTypeSet implements Iterable<TlinkType> {
+
+   private Set<TlinkType> _tlinkTypes;
+
+   public boolean add( final TlinkType tlinkType ) {
+      if ( _tlinkTypes == null ) {
+         _tlinkTypes = new HashSet<TlinkType>( 1 );
+      }
+      return _tlinkTypes.add( tlinkType );
+   }
+
+   public int size() {
+      return _tlinkTypes == null ? 0 : _tlinkTypes.size();
+   }
+
+   public boolean isEmpty() {
+      return _tlinkTypes == null || _tlinkTypes.isEmpty();
+   }
+
+   public boolean contains( final TlinkType tlinkType ) {
+      return _tlinkTypes != null && _tlinkTypes.contains( tlinkType );
+   }
+
+   public TlinkTypeSet createReciprocals() {
+      final TlinkTypeSet reciprocals = new TlinkTypeSet();
+      for ( TlinkType tlinkType : this ) {
+         reciprocals.add( tlinkType.getReciprocal() );
+      }
+      return reciprocals;
+   }
+
+
+   /**
+    * {@inheritDoc}
+    * @return "NONE," if empty, else a series of & separated time relation type names
+    */
+   @Override
+   public String toString() {
+      if ( isEmpty() ) {
+         return "NONE,";
+      }
+      final StringBuilder sb = new StringBuilder();
+      for ( TlinkType type : _tlinkTypes ) {
+         sb.append( type.name() ).append( " & " );
+      }
+      sb.setLength( sb.length()-3 );
+      sb.append( "," );
+      return sb.toString();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public Iterator<TlinkType> iterator() {
+      if ( isEmpty() ) {
+         return EMPTY_ITERATOR;
+      }
+      return _tlinkTypes.iterator();
+   }
+
+   static private final Iterator<TlinkType> EMPTY_ITERATOR = new Iterator<TlinkType>() {
+      @Override
+      public boolean hasNext() {
+         return false;
+      }
+
+      @Override
+      public TlinkType next() {
+         return null;
+      }
+
+      @Override
+      public void remove() {
+      }
+   };
+
+
+
+   //   /**
+   //    * Agreement between two Time Relation sets.
+   //    * 0 indicates no agreement, 1 indicates perfect agreement, anything between indicates partial agreement.
+   //    * @param otherTimeRelationTypes time relation type set to contrast with this one
+   //    * @return fraction of agreement: # common time relations(*2) divided by # total time relations
+   //    */
+   //   public double contrast( final TlinkTypeSet otherTimeRelationTypes ) {
+   //      if ( otherTimeRelationTypes == null || isEmpty() || otherTimeRelationTypes.isEmpty() ) {
+   //         return 0d;
+   //      }
+   //      final int total = size() + otherTimeRelationTypes.size();
+   //      final Set<TlinkType> commonSet = new HashSet<TlinkType>( _tlinkTypes );
+   //      commonSet.retainAll( otherTimeRelationTypes._tlinkTypes );
+   //      return 2d * (double) commonSet.size() / (double) total;
+   //   }
+
+
+
+}

Propchange: ctakes/trunk/ctakes-temporal/src/main/java/org/apache/ctakes/temporal/utils/TlinkTypeSet.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain