sergey-tihon / Stanford.NLP.NET

Stanford NLP for .NET
http://sergey-tihon.github.io/Stanford.NLP.NET/
MIT License
597 stars 123 forks source link

How do I get constituents from a tree annotation? #97

Closed Eric-Ryan closed 5 years ago

Eric-Ryan commented 5 years ago

In this example it shows the ability to extract constituents from a tree annotation:

    // get tree
    Tree tree =
        annotation.get(CoreAnnotations.SentencesAnnotation.class).get(0).get(TreeCoreAnnotations.TreeAnnotation.class);
    System.out.println(tree);
    Set<Constituent> treeConstituents = tree.constituents(new LabeledScoredConstituentFactory());
    for (Constituent constituent : treeConstituents) {
      if (constituent.label() != null &&
          (constituent.label().toString().equals("VP") || constituent.label().toString().equals("NP"))) {
        System.err.println("found constituent: "+constituent.toString());
        System.err.println(tree.getLeaves().subList(constituent.start(), constituent.end()+1));
      }
    }

I took the above code from the Stanford CoreNLP Website (https://stanfordnlp.github.io/CoreNLP/parse.html#examples). I attempted to do this but the constituents() method does not exist:

var sentences = annotation.get(typeof(CoreAnnotations.SentencesAnnotation));

foreach(CoreMap sentence in sentences as ArrayList){

    var tree = sentence.get(typeof(TreeCoreAnnotations.TreeAnnotation));

    tree.constituents(); // Here the constituents() method does not exist
}
sergey-tihon commented 5 years ago

most probably you cannot use typeof you need java.lang.Class

public static java.lang.Class GetAnnotationClass<T>()
            => ikvm.@internal.ClassLiteral<T>.Value; // or = new T().getClass()

var sentences = annotation.get(GetAnnotationClass<CoreAnnotations.SentencesAnnotation>());
foreach(CoreMap sentence in sentences as ArrayList){
    var tree = sentence.get(GetAnnotationClass<TreeCoreAnnotations.TreeAnnotation>()) as Tree;
    tree.constituents(); // most likely Tree is edu.stanford.nlp.trees.Tree
}
Eric-Ryan commented 5 years ago

Thank you for the quick response!

Eric-Ryan commented 5 years ago

I get the error " cannot convert from 'method group' to 'Class' " on these two lines:

GetAnnotationClass<CoreAnnotations.SentencesAnnotation>
GetAnnotationClass<TreeCoreAnnotations.TreeAnnotation>
sergey-tihon commented 5 years ago

Sorry, I forgot brackets, GetAnnotationClass is a method that that we should call, so GetAnnotationClass<T>()

var sentences = annotation.get(GetAnnotationClass<CoreAnnotations.SentencesAnnotation>());
Eric-Ryan commented 5 years ago

Thank you so much it worked! I am just still new with C# so I don't understand why I'm getting "Object reference not set to an instance of an object." when using "java.util.ArrayList":

            var sentences = annotation.get(GetAnnotationClass<CoreAnnotations.SentencesAnnotation>());
            foreach (CoreMap sentence in sentences as java.util.ArrayList)
            {
                Tree tree = sentence.get(GetAnnotationClass<TreeCoreAnnotations.TreeAnnotation>()) as Tree;
                var treeConstituents = tree.constituents(new LabeledScoredConstituentFactory());
                foreach (Constituent constituent in treeConstituents as java.util.ArrayList) // I get the error here
                {
                    if (constituent.label().toString().Equals("NP"))
                    {
                        Console.WriteLine(constituent.toString());
                        Console.WriteLine(tree.getLeaves().subList(constituent.start(), constituent.end() + 1));
                    }
                }

            }

As compared with the example I showed previously by the CoreNLP website, I cannot use "Set\<Constituent>" so I used "var" instead but still get the error.

Eric-Ryan commented 5 years ago

Nevermind! I think I might have solved it by using "java.util.AbstractSet" instead of "java.util.ArrayList". Thanks again!

sergey-tihon commented 5 years ago

interior with Java/IKVM types is not very intuitive. If you not sure what exact type is returned from annotation, you can take a look in debugger it Console.WriteLine(obj.GetType())

Eric-Ryan commented 5 years ago

Oh I see now, thank you. Excuse me for bothering, and perhaps this is out of your area of expertise but, I have been using CoreNLP within Unity and since adding the lines:

    public static java.lang.Class GetAnnotationClass<T>()
            => ikvm.@internal.ClassLiteral<T>.Value;

I have been getting an error about not being able to load the file "IKVM.OpenJDK.Core, Version 8.1". I was wondering if you could think of any DLL that I could be missing which could add the "GetAnnotationClass()" functionality within Unity? The full error within the console is this:

Error: Could not load signature of NLP:GetAnnotationClass due to: Could not load file or assembly 'IKVM.OpenJDK.Core, Version=8.1.5717.0, Culture=neutral, PublicKeyToken=13235d27fcbfff58' or one of its dependencies. assembly:IKVM.OpenJDK.Core, Version=8.1.5717.0, Culture=neutral, PublicKeyToken=13235d27fcbfff58 type: member:(null) signature:

I greatly appreciate any feedback.

sergey-tihon commented 5 years ago

1) I would check that IKVM.OpenJDK.Core is actually present near you exe or 2) If you are on Windows you use Fuslogvw.exe to log all assembly resolution requests and result to find out what file was no resolved. 3) you can try to replace GetAnnotationClass<T>() call by new T().getClass() and compare results

Eric-Ryan commented 5 years ago

new T().getClass() worked perfectly. Thanks again.