javaartificial-intelligenceopennlpuimanageddocumentuima

How to get the annotated text for a DictionaryAnnotator


I have a dictionary created from the DictionaryCreator from UIMA, I would like to annotate a piece of text using the DictionaryAnnotator and the aforementioned dictionary, I could not figure out how to get the annotated text. Please let me know if you do. Any help is appreciated. The code, the dictionary-file and the descriptor is mentioned below, P.S. I'm new to Apache UIMA.

 XMLInputSource xml_in = new XMLInputSource("DictionaryAnnotatorDescriptor.xml");
         ResourceSpecifier specifier = UIMAFramework.getXMLParser().parseResourceSpecifier(xml_in);
         AnalysisEngine ae = UIMAFramework.produceAnalysisEngine(specifier);
         JCas jCas = ae.newJCas();
         String inputText = "Mark and John went down the rabbit hole to meet a wise owl and have curry with the owl.";
         jCas.setDocumentText(inputText);
         printResults(jCas);


public static void printResults(JCas jcas) {
    FSIndex<Annotation> index = jcas.getAnnotationIndex();
    for (Iterator<Annotation> it = index.iterator(); it.hasNext(); ) {
        Annotation annotation = it.next();
        List<Feature> features;
            features = annotation.getType().getFeatures();
        List<String> fasl = new ArrayList<String>();
        for (Feature feature : features) {
            try {
                String name = feature.getShortName();
                System.out.println(feature.getName());
                String value = annotation.getStringValue(feature);
                fasl.add(name + "=\"" + value + "\"");
                System.out.println(value);
            }catch (Exception e){
                continue;
            }
        }
    }
}


my_dictionary.xml
<?xml version="1.0" encoding="UTF-8"?>
<dictionary xmlns="http://incubator.apache.org/uima" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="dictionary.xsd">
<typeCollection>
<dictionaryMetaData caseNormalization="true" multiWordEntries="true" multiWordSeparator=" "/>
<languageId>en</languageId>
<typeDescription>
<typeName>org.apache.uima.DictionaryEntry</typeName>
</typeDescription>
<entries>
<entry>
<key>Mark</key>
</entry>
<entry>
<key>John</key>
</entry>
<entry>
<key>Rabbit</key>
</entry>
<entry>
<key>Owl</key>
</entry>
<entry>
<key>Curry</key>
</entry>
<entry>
<key>ATH-MX50</key>
</entry>
<entry>
<key>CC234</key>
</entry>
</entries>
</typeCollection>
</dictionary>

DictionaryAnnotatorDescriptor.xml

<?xml version="1.0" encoding="UTF-8"?>
<analysisEngineDescription xmlns="http://uima.apache.org/resourceSpecifier">
    <frameworkImplementation>org.apache.uima.java</frameworkImplementation>
    <primitive>true</primitive>
    <annotatorImplementationName>org.apache.uima.annotator.dict_annot.impl.DictionaryAnnotator</annotatorImplementationName>
    <analysisEngineMetaData>
        <name>GeneDictionaryAnnotator</name>
        <description></description>
        <version>0.1</version>
        <vendor></vendor>
        <configurationParameters>
            <configurationParameter>
                <name>DictionaryFiles</name>
                <description>list of dictionary files to configure the annotator</description>
                <type>String</type>
                <multiValued>true</multiValued>
                <mandatory>true</mandatory>
            </configurationParameter>
            <configurationParameter>
                <name>InputMatchType</name>
                <description></description>
                <type>String</type>
                <multiValued>false</multiValued>
                <mandatory>true</mandatory>
            </configurationParameter>
            <configurationParameter>
                <name>InputMatchFeaturePath</name>
                <description></description>
                <type>String</type>
                <multiValued>false</multiValued>
                <mandatory>false</mandatory>
            </configurationParameter>
            <configurationParameter>
                <name>InputMatchFilterFeaturePath</name>
                <description></description>
                <type>String</type>
                <multiValued>false</multiValued>
                <mandatory>false</mandatory>
            </configurationParameter>
            <configurationParameter>
                <name>FilterConditionOperator</name>
                <description></description>
                <type>String</type>
                <multiValued>false</multiValued>
                <mandatory>false</mandatory>
            </configurationParameter>
            <configurationParameter>
                <name>FilterConditionValue</name>
                <description></description>
                <type>String</type>
                <multiValued>false</multiValued>
                <mandatory>false</mandatory>
            </configurationParameter>
        </configurationParameters>
        <configurationParameterSettings>
            <nameValuePair>
                <name>DictionaryFiles</name>
                <value>
                    <array>
                        <string>src/main/resources/my_dictionary.xml</string>
                    </array>
                </value>
            </nameValuePair>
            <nameValuePair>
                <name>InputMatchType</name>
                <value>
                    <string>org.apache.uima.TokenAnnotation</string>
                </value>
            </nameValuePair>
        </configurationParameterSettings>
        <typeSystemDescription>
            <types>
                <typeDescription>
                    <name>org.apache.uima.DictionaryEntry</name>
                    <description></description>
                    <supertypeName>uima.tcas.Annotation</supertypeName>
                </typeDescription>
                <typeDescription>
                    <name>org.apache.uima.TokenAnnotation</name>
                    <description>Single token annotation</description>
                    <supertypeName>uima.tcas.Annotation</supertypeName>
                    <features>
                        <featureDescription>
                            <name>tokenType</name>
                            <description>token type</description>
                            <rangeTypeName>uima.cas.String</rangeTypeName>
                        </featureDescription>
                    </features>
                </typeDescription>
                <typeDescription>
                    <name>example.Name</name>
                    <description>A proper name.</description>
                    <supertypeName>uima.tcas.Annotation</supertypeName>
                </typeDescription>
            </types>
        </typeSystemDescription>
        <capabilities>
            <capability>
                <inputs/>
                <outputs>
                    <type>example.Name</type>
                </outputs>
                <languagesSupported/>
            </capability>
        </capabilities>
        <operationalProperties>
            <modifiesCas>true</modifiesCas>
            <multipleDeploymentAllowed>true</multipleDeploymentAllowed>
            <outputsNewCASes>false</outputsNewCASes>
        </operationalProperties>
    </analysisEngineMetaData>
</analysisEngineDescription>

Solution

  • Alternatively, you could also use Apache Ruta, either with the workbench (recommended to get started) or with java code.

    For the latter, I created an example project at https://github.com/renaud/annotate_ruta_example. The main parts are:

    a list of names in src/main/resources/ruta/resources/names.txt (a plain text file)

    Mark
    John
    Rabbit
    Owl
    Curry
    ATH-MX50
    CC234
    

    a Ruta script in src/main/resources/ruta/scripts/Example.ruta

    PACKAGE example.annotate;               // optional package def
    
    WORDLIST MyNames = 'names.txt';         // declare dictionary location
    DECLARE Name;                           // declare an annotation
    Document{-> MARKFAST(Name, MyNames)};   // annotate document
    

    and some java boilerplate code to launch the annotator:

    JCas jCas = JCasFactory.createJCas();
    
    // the sample text to annotate
    jCas.setDocumentText("Mark wants to buy CC234.");
    
    // configure the engine with scripts and resources
    AnalysisEngine rutaEngine = AnalysisEngineFactory.createEngine(
        RutaEngine.class, //
        RutaEngine.PARAM_RESOURCE_PATHS,
        "src/main/resources/ruta/resources",//
        RutaEngine.PARAM_SCRIPT_PATHS,
        "src/main/resources/ruta/scripts",
        RutaEngine.PARAM_MAIN_SCRIPT, "Example");
    
    // run the script. instead of a jCas, you could also provide a UIMA collection reader to process many documents
    SimplePipeline.runPipeline(jCas, rutaEngine);
    
    // a simple select to print the matched Names
    for (Name name : JCasUtil.select(jCas, Name.class)) {
        System.out.println(name.getCoveredText());
    }
    

    there is also some UIMA type (annotation) definitions, check src/main/resources/desc/type/ExampleTypes.xml, src/main/resources/META-INF/org.apache.uima.fit/types.txt and src/main/java/example/annotate.

    how to test it

    git clone https://github.com/renaud/annotate_ruta_example.git
    cd annotate_ruta_example
    mvn clean install
    mvn exec:java -Dexec.mainClass="example.Annotate"