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;
}