All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.ctakes.assertion.medfacts.AssertionAnalysisEngineFit Maven / Gradle / Ivy

package org.apache.ctakes.assertion.medfacts;

import org.apache.ctakes.assertion.medfacts.i2b2.api.CharacterOffsetToLineTokenConverterCtakesImpl;
import org.apache.ctakes.assertion.medfacts.i2b2.api.SingleDocumentProcessorCtakes;
import org.apache.ctakes.assertion.medfacts.types.Concept;
import org.apache.ctakes.assertion.stub.*;
import org.apache.ctakes.core.pipeline.PipeBitInfo;
import org.apache.ctakes.core.resource.FileLocator;
import org.apache.ctakes.typesystem.type.textsem.IdentifiedAnnotation;
import org.apache.log4j.Logger;
import org.apache.uima.UimaContext;
import org.apache.uima.analysis_engine.AnalysisEngineProcessException;
import org.apache.uima.fit.component.JCasAnnotator_ImplBase;
import org.apache.uima.fit.descriptor.ConfigurationParameter;
import org.apache.uima.fit.util.JCasUtil;
import org.apache.uima.jcas.JCas;
import org.apache.uima.jcas.tcas.Annotation;
import org.apache.uima.resource.ResourceInitializationException;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.*;

import static org.apache.ctakes.typesystem.type.constants.CONST.ATTR_SUBJECT_FAMILY_MEMBER;
import static org.apache.ctakes.typesystem.type.constants.CONST.ATTR_SUBJECT_PATIENT;


/**
 * Stub classes must be replaced.  See https://issues.apache.org/jira/browse/CTAKES-76
 *
 * @author SPF , chip-nlp
 * @version %I%
 * @since 10/19/2016
 */
@PipeBitInfo(
      name = "Assertion Engine (FIT)",
      description = "Adds Negation, Uncertainty, Conditional and Subject to annotations.",
      role = PipeBitInfo.Role.ANNOTATOR,
      dependencies = { PipeBitInfo.TypeProduct.IDENTIFIED_ANNOTATION }
)
public class AssertionAnalysisEngineFit extends JCasAnnotator_ImplBase {

   static private final Logger LOGGER = Logger.getLogger( "AssertionAnalysisEngineFit" );

   static public final String ASSERTION_MODEL_PARAM = "assertionModelResource";
   static public final String SCOPE_MODEL_PARAM = "scopeModelResource";
   static public final String CUE_MODEL_PARAM = "cueModelResource";
   static public final String POS_MODEL_PARAM = "posModelResource";
   static public final String ENABLED_FEATURES_PARAM = "enabledFeaturesResource";


   @ConfigurationParameter(
         name = ASSERTION_MODEL_PARAM,
         defaultValue = "org/apache/ctakes/assertion/models/i2b2.model" )
   private String _assertionModelPath;

   @ConfigurationParameter(
         name = SCOPE_MODEL_PARAM,
         defaultValue = "org/apache/ctakes/assertion/models/scope.model" )
   private String _scopeModelPath;

   @ConfigurationParameter(
         name = CUE_MODEL_PARAM,
         defaultValue = "org/apache/ctakes/assertion/models/cue.model" )
   private String _cueModelPath;

   @ConfigurationParameter(
         name = POS_MODEL_PARAM,
         defaultValue = "org/apache/ctakes/assertion/models/pos.model" )
   private String _posModelPath;

   @ConfigurationParameter(
         name = ENABLED_FEATURES_PARAM,
         defaultValue = "org/apache/ctakes/assertion/models/featureFile11b" )
   private String _enabledFeaturesPath;

   private AssertionDecoderConfiguration _assertionDecoderConfiguration;

   @Override
   public void initialize( final UimaContext uimaContext ) throws ResourceInitializationException {
      super.initialize( uimaContext );
      // byte assertionModelContents[];
      File assertionModelFile;
      String scopeModelFilePath;
      String cueModelFilePath;
      String posModelFilePath;
      File enabledFeaturesFile;
      try {
         assertionModelFile = FileLocator.getFile( _assertionModelPath );
         // assertionModelContents = StringHandling.readEntireContentsBinary(assertionModelFile);
         scopeModelFilePath = FileLocator.getFile( _scopeModelPath ).getAbsolutePath();
         cueModelFilePath = FileLocator.getFile( _cueModelPath ).getAbsolutePath();
         posModelFilePath = FileLocator.getFile( _posModelPath ).getAbsolutePath();
         enabledFeaturesFile = FileLocator.getFile( _enabledFeaturesPath );
      } catch ( FileNotFoundException fnfE ) {
         throw new ResourceInitializationException( fnfE );
      }
      LOGGER.info( "scope model file: " + scopeModelFilePath );
      LOGGER.info( "cue model file: " + cueModelFilePath );
      LOGGER.info( "pos model file: " + posModelFilePath );
      final AssertionDecoderConfiguration assertionDecoderConfiguration = new AssertionDecoderConfiguration();
      final ScopeParser scopeParser = new ScopeParser( scopeModelFilePath, cueModelFilePath );
      assertionDecoderConfiguration.setScopeParser( scopeParser );
      final PartOfSpeechTagger posTagger = new PartOfSpeechTagger( posModelFilePath );
      assertionDecoderConfiguration.setPosTagger( posTagger );
      final Set enabledFeatureIdSet = BatchRunner.loadEnabledFeaturesFromFile( enabledFeaturesFile );
      assertionDecoderConfiguration.setEnabledFeatureIdSet( enabledFeatureIdSet );
      final JarafeMEDecoder assertionDecoder = new JarafeMEDecoder( assertionModelFile );
      assertionDecoderConfiguration.setAssertionDecoder( assertionDecoder );
      _assertionDecoderConfiguration = assertionDecoderConfiguration;
   }


   /**
    * {@inheritDoc}
    */
   @Override
   public void process( final JCas jcas ) throws AnalysisEngineProcessException {
      LOGGER.info( "Starting processing" );
      final String documentText = jcas.getDocumentText();
      final List apiConceptList = new ArrayList<>();
      final Collection concepts = JCasUtil.select( jcas, Concept.class );
      for ( Concept concept : concepts ) {
         final int begin = concept.getBegin();
         final int end = concept.getEnd();
         final String conceptText = documentText.substring( begin, end );
         final ApiConcept apiConcept = new ApiConcept();
         apiConcept.setBegin( begin );
         apiConcept.setEnd( end );
         apiConcept.setText( conceptText );
         apiConcept.setType( concept.getConceptType() );
         apiConcept.setExternalId( concept.getAddress() );
         apiConceptList.add( apiConcept );
      }
      final SingleDocumentProcessorCtakes processor = new SingleDocumentProcessorCtakes();
      processor.setJcas( jcas );
      processor.setAssertionDecoderConfiguration( _assertionDecoderConfiguration );
      processor.setContents( documentText );
      final CharacterOffsetToLineTokenConverter converter = new CharacterOffsetToLineTokenConverterCtakesImpl( jcas );
      processor.setConverter2( converter );
      apiConceptList.forEach( processor::addConcept );
      LOGGER.debug( "BEFORE CALLING processor.processSingleDocument()" );
      processor.processSingleDocument();
      LOGGER.debug( "AFTER CALLING processor.processSingleDocument()" );
      final Map assertionTypeMap = processor.getAssertionTypeMap();
      final CasIndexer indexer = new CasIndexer<>( jcas, null );
      for ( Map.Entry current : assertionTypeMap.entrySet() ) {
         final Integer currentIndex = current.getKey();
         final String currentAssertionType = current.getValue();
         final ApiConcept originalConcept = apiConceptList.get( currentIndex );
         final Concept associatedConcept = (Concept)indexer.lookupByAddress( originalConcept.getExternalId() );
         final int entityAddress = associatedConcept.getOriginalEntityExternalId();
         final IdentifiedAnnotation annotation = (IdentifiedAnnotation)indexer.lookupByAddress( entityAddress );
         mapI2B2AssertionValueToCtakes( currentAssertionType, annotation );
      }
      LOGGER.info( "Processing Finished" );
   }


   static private void fillProperties( final IdentifiedAnnotation annotation,
                                       final int polarity, final int uncertainty,
                                       final boolean generic, final boolean conditional,
                                       final String subject, final float confidence ) {
      annotation.setPolarity( polarity );
      annotation.setUncertainty( uncertainty );
      annotation.setGeneric( generic );
      annotation.setConditional( conditional );
      annotation.setSubject( subject );
      annotation.setConfidence( confidence );
   }


   // possible values for currentAssertionType:
   // present
   // absent
   // associated_with_someone_else
   // conditional
   // hypothetical
   // possible
   // Changed from original implementation by information in https://www.mitre.org/sites/default/files/pdf/10_4676.pdf
   static public void mapI2B2AssertionValueToCtakes( final String assertionType,
                                                      final IdentifiedAnnotation annotation )
         throws AnalysisEngineProcessException {
      if ( assertionType == null ) {
         LOGGER.error( "current assertion type is null" );
         fillProperties( annotation, -2, -2, false, false, "skipped", -2.0f );
         return;
      }
      switch ( assertionType ) {
         case "present":
            fillProperties( annotation, 1, 0, false, false, ATTR_SUBJECT_PATIENT, 1.0f );
            break;
         case "absent":
            fillProperties( annotation, -1, 0, false, false, ATTR_SUBJECT_PATIENT, 1.0f );
            break;
         case "associated_with_someone_else":
            // OLD:   annotation.setSubject( "CONST.ATTR_SUBJECT_FAMILY_MEMBER" );
            fillProperties( annotation, 1, 0, false, false, ATTR_SUBJECT_FAMILY_MEMBER, 1.0f );
            break;
         case "conditional":
            // OLD:   currently no mapping to sharp type...all sharp properties are defaults!
            // OLD:   annotation.setConditional( false );
            fillProperties( annotation, 1, 0, false, true, ATTR_SUBJECT_PATIENT, 1.0f );
            break;
         case "hypothetical":
            // OLD:   annotation.setConditional( true ); annotation.setGeneric( false );
            fillProperties( annotation, 1, 0, true, false, ATTR_SUBJECT_PATIENT, 1.0f );
            break;
         case "possible":
            fillProperties( annotation, 1, 1, false, false, ATTR_SUBJECT_PATIENT, 1.0f );
            break;
         default:
            LOGGER.error( "unexpected assertion value returned: " + assertionType );
            fillProperties( annotation, -2, -2, false, false, "skipped", -2.0f );
            break;
      }
   }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy