Author: seanfinan
Date: Tue Jul  5 13:38:53 2022
New Revision: 1902485

URL: http://svn.apache.org/viewvc?rev=1902485&view=rev
Log:
New ConceptBuilder for convenience
Update IdentifiedAnnotationBuilder

Added:
    
ctakes/trunk/ctakes-core/src/main/java/org/apache/ctakes/core/util/annotation/ConceptBuilder.java
Modified:
    
ctakes/trunk/ctakes-core/src/main/java/org/apache/ctakes/core/util/annotation/IdentifiedAnnotationBuilder.java

Added: 
ctakes/trunk/ctakes-core/src/main/java/org/apache/ctakes/core/util/annotation/ConceptBuilder.java
URL: 
http://svn.apache.org/viewvc/ctakes/trunk/ctakes-core/src/main/java/org/apache/ctakes/core/util/annotation/ConceptBuilder.java?rev=1902485&view=auto
==============================================================================
--- 
ctakes/trunk/ctakes-core/src/main/java/org/apache/ctakes/core/util/annotation/ConceptBuilder.java
 (added)
+++ 
ctakes/trunk/ctakes-core/src/main/java/org/apache/ctakes/core/util/annotation/ConceptBuilder.java
 Tue Jul  5 13:38:53 2022
@@ -0,0 +1,165 @@
+package org.apache.ctakes.core.util.annotation;
+
+import org.apache.ctakes.typesystem.type.refsem.OntologyConcept;
+import org.apache.ctakes.typesystem.type.refsem.UmlsConcept;
+import org.apache.uima.jcas.JCas;
+
+
+/**
+ * @author SPF , chip-nlp
+ * @since {1/4/2022}
+ */
+final public class ConceptBuilder {
+
+   private String _schema = "";
+   private String _code = "";
+   private double _score = Double.MIN_VALUE;
+   private boolean _disambiguated = false;
+
+
+   // A value in any of these will create a UmlsConcept
+   private SemanticTui _type = SemanticTui.UNKNOWN;
+   private String _cui = "C0000000";
+   private String _prefText = "Unknown UMLS Concept";
+   private boolean _isUmls = false;
+
+
+   /**
+    * @param schema name of an encoding schema.  e.g. SNOMEDCT_US
+    * @return this builder
+    */
+   public ConceptBuilder schema( final String schema ) {
+      _schema = schema;
+      return this;
+   }
+
+   /**
+    * @param code code for this annotation in that schema
+    * @return this builder
+    */
+   public ConceptBuilder code( final String code ) {
+      _code = code;
+      return this;
+   }
+
+   /**
+    * @param score score for something like confidence
+    * @return this builder
+    */
+   public ConceptBuilder score( final double score ) {
+      _score = score;
+      return this;
+   }
+
+   /**
+    * set disambiguated = true
+    *
+    * @return this builder
+    */
+   public ConceptBuilder disambiguated() {
+      return disambiguated( true );
+   }
+
+   /**
+    * @param disambiguated true if this concept has been disambiguated
+    * @return this builder
+    */
+   public ConceptBuilder disambiguated( final boolean disambiguated ) {
+      _disambiguated = disambiguated;
+      return this;
+   }
+
+
+   // If any of these is set then a UmlsConcept is created
+
+   /**
+    * @param semanticType for the annotation
+    * @return this builder
+    */
+   public ConceptBuilder type( final SemanticTui semanticType ) {
+      _type = semanticType;
+      _isUmls = true;
+      return this;
+   }
+
+   /**
+    * @param semanticType name for the annotation
+    * @return this builder
+    */
+   public ConceptBuilder type( final String semanticType ) {
+      return type( SemanticTui.getTui( semanticType ) );
+   }
+
+   /**
+    * @param tui representing the primary semantic type.
+    * @return this builder
+    */
+   public ConceptBuilder tui( final int tui ) {
+      return type( SemanticTui.getTui( tui ) );
+   }
+
+   /**
+    * @param tui representing the primary semantic type.
+    * @return this builder
+    */
+   public ConceptBuilder tui( final String tui ) {
+      return type( SemanticTui.getTui( tui ) );
+   }
+
+   /**
+    * @param cui concept unique identifier
+    * @return this builder
+    */
+   public ConceptBuilder cui( final String cui ) {
+      _cui = cui;
+      _isUmls = true;
+      return this;
+   }
+
+   /**
+    * @param text preferred
+    * @return this builder
+    */
+   public ConceptBuilder preferredText( final String text ) {
+      _prefText = text;
+      _isUmls = true;
+      return this;
+   }
+
+   private boolean isUmls() {
+      return _isUmls;
+   }
+
+   /**
+    * @param jcas ye olde ...
+    * @return a UmlsConcept
+    */
+   public OntologyConcept build( final JCas jcas ) {
+      OntologyConcept concept;
+      if ( isUmls() ) {
+         concept = new UmlsConcept( jcas );
+         ( (UmlsConcept) concept ).setCui( _cui );
+         if ( _type != SemanticTui.UNKNOWN ) {
+            ( (UmlsConcept) concept ).setTui( _type.name() );
+         }
+         if ( !_prefText.isEmpty() ) {
+            ( (UmlsConcept) concept ).setPreferredText( _prefText );
+         }
+      } else {
+         concept = new OntologyConcept( jcas );
+      }
+      if ( !_schema.isEmpty() ) {
+         concept.setCodingScheme( _schema );
+         concept.setCode( _code );
+         if ( _score != Double.MIN_VALUE ) {
+            concept.setScore( _score );
+         }
+         if ( _disambiguated ) {
+            concept.setDisambiguated( true );
+         }
+      }
+      return concept;
+   }
+
+
+}

Modified: 
ctakes/trunk/ctakes-core/src/main/java/org/apache/ctakes/core/util/annotation/IdentifiedAnnotationBuilder.java
URL: 
http://svn.apache.org/viewvc/ctakes/trunk/ctakes-core/src/main/java/org/apache/ctakes/core/util/annotation/IdentifiedAnnotationBuilder.java?rev=1902485&r1=1902484&r2=1902485&view=diff
==============================================================================
--- 
ctakes/trunk/ctakes-core/src/main/java/org/apache/ctakes/core/util/annotation/IdentifiedAnnotationBuilder.java
 (original)
+++ 
ctakes/trunk/ctakes-core/src/main/java/org/apache/ctakes/core/util/annotation/IdentifiedAnnotationBuilder.java
 Tue Jul  5 13:38:53 2022
@@ -3,13 +3,17 @@ package org.apache.ctakes.core.util.anno
 
 import org.apache.ctakes.core.util.Pair;
 import org.apache.ctakes.typesystem.type.constants.CONST;
+import org.apache.ctakes.typesystem.type.refsem.OntologyConcept;
 import org.apache.ctakes.typesystem.type.refsem.UmlsConcept;
 import org.apache.ctakes.typesystem.type.textsem.IdentifiedAnnotation;
 import org.apache.log4j.Logger;
 import org.apache.uima.jcas.JCas;
 import org.apache.uima.jcas.cas.FSArray;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Objects;
 import java.util.stream.Collectors;
 
 /**
@@ -25,12 +29,19 @@ final public class IdentifiedAnnotationB
    private Pair<Integer> _textSpan = NULL_SPAN;
    private SemanticGroup _group = SemanticGroup.UNKNOWN;
    private SemanticTui _type = SemanticTui.UNKNOWN;
-   private final Collection<SemanticTui> _tuis = EnumSet.noneOf( 
SemanticTui.class );
-   private String _cui = "";
-   private String _prefText = "";
-   private final Map<String, Collection<String>> _schemaCodes = new 
HashMap<>();
+   private final Collection<OntologyConcept> _concepts = new HashSet<>();
+   private boolean _negated = false;
+   private boolean _uncertain = false;
+   private boolean _generic = false;
+   private boolean _conditional = false;
+   private boolean _historic = false;
+   private String _subject = CONST.ATTR_SUBJECT_PATIENT;
+   private int _discoveredBy = 0;
+   private float _confidence = Float.MIN_VALUE;
 
 
+   // TODO Make a similar abstract builder for BinaryTextRelation.  abstract 
createRelation( JCas )  called by build()
+
    /**
     * @param begin text span character index
     * @param end   text span character index
@@ -83,47 +94,137 @@ final public class IdentifiedAnnotationB
       return type( SemanticTui.getTui( semanticType ) );
    }
 
+   public IdentifiedAnnotationBuilder concept( final OntologyConcept concept ) 
{
+      _concepts.add( concept );
+      return this;
+   }
+
+   public IdentifiedAnnotationBuilder concept( final JCas jCas, final String 
cui ) {
+      return concept( jCas, cui, _type );
+   }
+
+   public IdentifiedAnnotationBuilder concept( final JCas jCas, final String 
cui, final SemanticTui type ) {
+      final OntologyConcept concept = new ConceptBuilder().cui( cui )
+                                                          .type( type )
+                                                          .build( jCas );
+      return concept( concept );
+   }
+
    /**
     * @param tui representing the primary semantic type.
     * @return this builder
     */
-   public IdentifiedAnnotationBuilder tui( final String tui ) {
+   public IdentifiedAnnotationBuilder tui( final int tui ) {
       return type( SemanticTui.getTui( tui ) );
    }
 
    /**
-    * @param semanticType representing possibly secondary semantic type.
+    * @param tui representing the primary semantic type.
     * @return this builder
     */
-   public IdentifiedAnnotationBuilder addTui( final SemanticTui semanticType ) 
{
-      _tuis.add( semanticType );
+   public IdentifiedAnnotationBuilder tui( final String tui ) {
+      return type( SemanticTui.getTui( tui ) );
+   }
+
+   public IdentifiedAnnotationBuilder negated() {
+      _negated = true;
       return this;
    }
 
-   /**
-    * @param tui representing possibly secondary semantic type.
-    * @return this builder
-    */
-   public IdentifiedAnnotationBuilder addTui( final String tui ) {
-      return addTui( SemanticTui.getTui( tui ) );
+   public IdentifiedAnnotationBuilder uncertain() {
+      _uncertain = true;
+      return this;
+   }
+
+   public IdentifiedAnnotationBuilder generic() {
+      _generic = true;
+      return this;
+   }
+
+   public IdentifiedAnnotationBuilder conditional() {
+      _conditional = true;
+      return this;
+   }
+
+   public IdentifiedAnnotationBuilder historic() {
+      _historic = true;
+      return this;
+   }
+
+   public IdentifiedAnnotationBuilder subject( final String subject ) {
+      _subject = subject;
+      return this;
    }
 
+
+   public IdentifiedAnnotationBuilder discoveredBy( final int 
discoveryTechnique ) {
+      _discoveredBy = discoveryTechnique;
+      return this;
+   }
+
+   public IdentifiedAnnotationBuilder confidence( final float confidence ) {
+      _confidence = confidence;
+      return this;
+   }
+
+   private SemanticGroup getGroup() {
+      if ( _group != SemanticGroup.UNKNOWN ) {
+         return _group;
+      }
+      if ( _type != SemanticTui.UNKNOWN ) {
+         return _type.getGroup();
+      }
+      if ( !_concepts.isEmpty() ) {
+         final Collection<SemanticGroup> groups
+               = _concepts.stream()
+                          .filter( UmlsConcept.class::isInstance )
+                          .map( c -> ( (UmlsConcept) c ).getTui() )
+                          .filter( Objects::nonNull )
+                          .filter( t -> !t.isEmpty() )
+                          .map( SemanticTui::getTui )
+                          .map( SemanticTui::getGroup )
+                          .collect( Collectors.toSet() );
+         if ( !groups.isEmpty() ) {
+            if ( groups.size() == 1 ) {
+               return new ArrayList<>( groups ).get( 0 );
+            }
+         }
+         return SemanticGroup.getBestGroup( groups );
+      }
+      return _group;
+   }
+
+   private void addConcepts( final JCas jCas, final IdentifiedAnnotation 
annotation ) {
+      if ( !_concepts.isEmpty() ) {
+         final FSArray conceptArr = new FSArray( jCas, _concepts.size() );
+         int arrIdx = 0;
+         for ( OntologyConcept concept : _concepts ) {
+            conceptArr.set( arrIdx, concept );
+            arrIdx++;
+         }
+         annotation.setOntologyConceptArr( conceptArr );
+      }
+   }
+
+
    /**
     * @param cui concept unique identifier
     * @return this builder
+    * @deprecated use ConceptBuilder
     */
+   @Deprecated
    public IdentifiedAnnotationBuilder cui( final String cui ) {
-      _cui = cui;
-      return this;
+      throw new UnsupportedOperationException();
    }
 
    /**
     * @param text preferred
     * @return this builder
+    * @deprecated use ConceptBuilder
     */
+   @Deprecated
    public IdentifiedAnnotationBuilder preferredText( final String text ) {
-      _prefText = text;
-      return this;
+      throw new UnsupportedOperationException();
    }
 
    /**
@@ -132,10 +233,11 @@ final public class IdentifiedAnnotationB
     * @param schema name of an encoding schema.  e.g. SNOMEDCT_US
     * @param code   code for this annotation in that schema
     * @return this builder
+    * @deprecated use ConceptBuilder
     */
+   @Deprecated
    public IdentifiedAnnotationBuilder addSchemaCode( final String schema, 
final String code ) {
-      _schemaCodes.computeIfAbsent( schema, s -> new HashSet<>() ).add( code );
-      return this;
+      throw new UnsupportedOperationException();
    }
 
 
@@ -167,37 +269,6 @@ final public class IdentifiedAnnotationB
 
 
    /**
-    * @param jcas          ye olde ...
-    * @param cui           -
-    * @param type          -
-    * @param preferredText may be empty
-    * @param schema        may be empty
-    * @param code          may be empty
-    * @return a UmlsConcept for the annotation
-    */
-   static private UmlsConcept createUmlsConcept( final JCas jcas,
-                                                 final String cui,
-                                                 final SemanticTui type,
-                                                 final String preferredText,
-                                                 final String schema,
-                                                 final String code ) {
-      final UmlsConcept umlsConcept = new UmlsConcept( jcas );
-      umlsConcept.setCui( cui );
-      if ( type != SemanticTui.UNKNOWN ) {
-         umlsConcept.setTui( type.name() );
-      }
-      if ( !preferredText.isEmpty() ) {
-         umlsConcept.setPreferredText( preferredText );
-      }
-      if ( !schema.isEmpty() ) {
-         umlsConcept.setCodingScheme( schema );
-         umlsConcept.setCode( code );
-      }
-      return umlsConcept;
-   }
-
-
-   /**
     * Builds the IdentifiedAnnotation and stores it in the jCas.  The same as 
.build( jcas )
     *
     * @param jcas ye olde ...
@@ -214,60 +285,40 @@ final public class IdentifiedAnnotationB
     * @return an IdentifiedAnnotation with properties specified or null if the 
cui or span are illegal.
     */
    public IdentifiedAnnotation build( final JCas jcas ) {
-      if ( !isSpanValid( _textSpan, jcas.getDocumentText().length() ) ) {
-         return null;
-      }
-      if ( _cui.isEmpty() ) {
-         LOGGER.error( "A Concept Unique Identifier (CUI) must be specified to 
build an IdentifiedAnnotation." );
+      if ( !isSpanValid( _textSpan, jcas.getDocumentText()
+                                        .length() ) ) {
+         LOGGER.error( "Invalid text span " + _textSpan.getValue1() + "," + 
_textSpan.getValue2() + " in document of "
+                       + "length " + jcas.getDocumentText()
+                                         .length() );
          return null;
       }
-      if ( _group == SemanticGroup.UNKNOWN && _type != SemanticTui.UNKNOWN ) {
-         _group = _type.getGroup();
-      }
-      if ( _group == SemanticGroup.UNKNOWN && !_tuis.isEmpty() ) {
-         final Collection<SemanticGroup> groups = _tuis.stream()
-                                                       .map( 
SemanticTui::getGroup )
-                                                       .collect( 
Collectors.toSet() );
-         _group = SemanticGroup.getBestGroup( groups );
-      }
-      if ( _type == SemanticTui.UNKNOWN && !_tuis.isEmpty() ) {
-         _type = _tuis.stream()
-                      .filter( t -> t.getGroup() == _group )
-                      .min( Comparator.comparing( SemanticTui::name ) )
-                      .orElse( SemanticTui.UNKNOWN );
-      }
-      final IdentifiedAnnotation annotation = _group
-            .getCreator()
-            .apply( jcas );
-      annotation.setTypeID( _group.getCode() );
+      final SemanticGroup group = getGroup();
+      final IdentifiedAnnotation annotation = group.getCreator()
+                                                   .apply( jcas );
+      annotation.setTypeID( group.getCode() );
       annotation.setBegin( _textSpan.getValue1() );
       annotation.setEnd( _textSpan.getValue2() );
-      annotation.setDiscoveryTechnique( CONST.NE_DISCOVERY_TECH_EXPLICIT_AE );
-
-      final Collection<UmlsConcept> umlsConcepts = new HashSet<>();
-      if ( _schemaCodes.isEmpty() ) {
-         umlsConcepts.add( createUmlsConcept( jcas, _cui, _type, _prefText, 
"", "" ) );
-      } else {
-         for ( Map.Entry<String, Collection<String>> schemaCodes : 
_schemaCodes.entrySet() ) {
-            for ( String code : schemaCodes.getValue() ) {
-               umlsConcepts.add( createUmlsConcept( jcas, _cui, _type, 
_prefText, schemaCodes.getKey(), code ) );
-            }
-         }
+      if ( _negated ) {
+         annotation.setPolarity( CONST.NE_POLARITY_NEGATION_PRESENT );
+      }
+      if ( _uncertain ) {
+         annotation.setUncertainty( CONST.NE_UNCERTAINTY_PRESENT );
+      }
+      if ( _generic ) {
+         annotation.setGeneric( true );
+      }
+      if ( _conditional ) {
+         annotation.setConditional( true );
+      }
+      if ( _historic ) {
+         annotation.setHistoryOf( CONST.NE_HISTORY_OF_PRESENT );
       }
-      if ( !_tuis.isEmpty() ) {
-         _tuis.stream()
-              .filter( t -> t != _type )
-              .filter( t -> t != SemanticTui.UNKNOWN )
-              .map( t -> createUmlsConcept( jcas, _cui, t, "", "", "" ) )
-              .forEach( umlsConcepts::add );
-      }
-      final FSArray conceptArr = new FSArray( jcas, umlsConcepts.size() );
-      int arrIdx = 0;
-      for ( UmlsConcept umlsConcept : umlsConcepts ) {
-         conceptArr.set( arrIdx, umlsConcept );
-         arrIdx++;
+      if ( !_subject.isEmpty() ) {
+         annotation.setSubject( _subject );
       }
-      annotation.setOntologyConceptArr( conceptArr );
+      annotation.setDiscoveryTechnique( _discoveredBy );
+      annotation.setConfidence( _confidence );
+      addConcepts( jcas, annotation );
       annotation.addToIndexes();
       return annotation;
    }


Reply via email to