Hi,
Am 20.09.2016 um 21:51 schrieb Bonnie MacKellar: > Hi, > > Just getting back to this since I was off at a conference. Thanks again for > the details. This is realy helpful. I beleive that Ruta 2.5 is not yet out, > right? Yes, 2.5.0 is not yet release, but it will be soon, hopefully. > > As convenient as this rule seems > "(?i).*(must be (?:receiving|undergoing|using) (.*) for) (.*)" -> > R3Dot1CurrentPurposeConstraint ("group1" = 2, "group2" = 3); > > I do need to be able to distinguish between group1 and group2 in a Java > program that walks through the features. If they are both plain > Annotations, I am assuming I would not be able to do that, so the first > setup is probably still best. Thanks for all your help Just wanted to mention that you can distinguish between both since they are in different features. Best, Peter > Bonnie MacKellar > > On Thu, Sep 15, 2016 at 7:32 AM, Peter Klügl <peter.klu...@averbis.com> > wrote: > >> Hi, >> >> >> Am 14.09.2016 um 22:58 schrieb Bonnie MacKellar: >>> OK, thanks. I played around a little bit today with my own rules >>> >>> DECLARE Group1; >>> DECLARE Group2; >>> DECLARE R3Dot1CurrentPurposeConstraint(Annotation group1, Annotation >>> group2); >>> >>> BLOCK(eachEC) EC{}{ >>> "(?i).*(must be (?:receiving|undergoing|using) (.*) for) (.*)" -> >>> R3Dot1CurrentPurposeConstraint,2=Group1, 3=Group2; >>> "(?i).*(ongoing (.*(?:therapy|treatment).*) for) (.*)" -> >>> R3Dot1CurrentPurposeConstraint; >>> } >>> >>> I want to end up with the text marked by Group1 to be the value for the >>> group1 feature in R3Dot1CurrentPurposeConstraint (and likewise group2), >> but >>> I couldn't find a way to do it in my rules above, so I added this >>> >>> R3Dot1CurrentPurposeConstraint {-> >>> R3Dot1CurrentPurposeConstraint.group1=Group1, >>> R3Dot1CurrentPurposeConstraint.group2=Group2}; >>> >>> It appears to work on a small test case. Does that seem correct to you? >> Is >>> there a better way to do this, preferably right in the rules with the >>> regular expressions? >> Yes, this looks correct to me and it should do what you want, if there >> is only exactly one annotation of each type (Group1 and Group2) within >> the current R3Dot1CurrentPurposeConstraint annotation, or if only the >> first one matters. And if the is no sequential dependency between Group1 >> and Group2, e.g., Group1 must occur before Group2. This should be the >> case in your example. >> I personally prefer labels more and more, especially because they become >> even more powerful in ruta 2.5.0. Which is the best way to assign >> features depends on the specific situation. The examples in my last mail >> have all their advantages. >> >> I personally would write the rule this way (but this will work only in >> 2.5.0): >> c:R3Dot1CurrentPurposeConstraint{-> c.group1 = Group1, c.group2 = Group2}; >> >> Here, the annotation R3Dot1CurrentPurposeConstraint in the action part >> does not need to be resolved by the given type, but the annotation that >> was matched by the type of the rule element is directly used. If there >> are two R3Dot1CurrentPurposeConstraint annotations with the same >> offsets, your rule would cause problems. >> >> >> You can also assign the features directly in a simple regex rule, but >> regex rules do not on given annotations at all but only on text. So if >> you replace your rule with: >> >> "(?i).*(must be (?:receiving|undergoing|using) (.*) for) (.*)" -> >> R3Dot1CurrentPurposeConstraint ("group1" = 2, "group2" = 3), >> 2=Group1, 3=Group2; >> >> the two features of the created R3Dot1CurrentPurposeConstraint >> annotation will be filled with annotations. However, these annotations >> are of type Annotation and not Group1 and Group2. If you do not care >> about the actual type of the annotation, e.g., because you won't use >> additional features. You can simple write >> >> "(?i).*(must be (?:receiving|undergoing|using) (.*) for) (.*)" -> >> R3Dot1CurrentPurposeConstraint ("group1" = 2, "group2" = 3); >> >> else you need an additional rule based on annotations like above. >> >>> Also, why did you declare your features as Annotation rather than >> Employee >>> and Employer? >>> DECLARE EmplRelation (Annotation employee, Annotation employer); >>> >>> I imitated this, but to me it would seem better to use >>> DECLARE EmplRelation (Employee employee, Employer employer); >>> I am sure there is a good reason for this, but I don't see it! >> Nope, there was no good reason :-) >> >> It just did not matter for the example. >> >> When I explain these examples, I normally also explain the situation >> when there are no Employer and Employee annotations but only Person >> annotations. Then, only a subset of the rules will work, e.g., GATHER, >> annotation variables, labels. In this case, I would not need to modify >> the declare statement. >> >> Best, >> >> Peter >> >> >> >>> Thanks, this cleared up some amount of confusion >>> >>> Bonnie MacKellar >>> >>> On Wed, Sep 14, 2016 at 5:58 AM, Peter Klügl <peter.klu...@averbis.com> >>> wrote: >>> >>>> Hi, >>>> >>>> >>>> yes, the types need to be declared before. The DECLARE statements have >>>> been omitted in the example. >>>> >>>> >>>> Ruta 2.4.0 introduced annotation expressions. Before that, annotations >>>> have only ben e referenced by type expressons. Ruta tries to guess which >>>> annotation is meant by the given type expression using the context. >>>> >>>> So, if you "assign" a type to a feature that expects one annotation, >>>> then the first annotation of that type within the matching window of the >>>> rule element is selected. In that example, this is the first annotation >>>> of the type Employee within the currently matched sentence annotation. >>>> >>>> Here are some more (with declare, but without the Indicator annotation) >>>> examples how to assign feature values for the trivial text "Peter works >>>> for Frank.": >>>> >>>> >>>> DECLARE Employer, Employee; >>>> DECLARE EmplRelation (Annotation employee, Annotation employer); >>>> "Peter"-> Employee; >>>> "Frank"-> Employer; >>>> >>>> // CREATE >>>> Document{-> CREATE(EmplRelation, "employee" = Employee, "employer" = >>>> Employer)}; >>>> >>>> // GATHER >>>> Employee # Employer{-> GATHER(EmplRelation, 1, 3, "employee" = 1, >>>> "employer" = 3)}; >>>> >>>> // implicit actions >>>> (Employee # Employer){-> EmplRelation, >>>> EmplRelation.employee = Employee, >>>> EmplRelation.employer = Employer}; >>>> >>>> // annotation variables >>>> ANNOTATION e1,e2; >>>> (Employee{-> ASSIGN(e1, Employee)} # Employer{-> ASSIGN(e2, Employer)}) >>>> {-> CREATE(EmplRelation, "employee" = e1, "employer" = e2)}; >>>> >>>> // labels >>>> (e1:Employee # e2:Employer) >>>> {-> CREATE(EmplRelation, "employee" = e1, "employer" = e2)}; >>>> >>>> Best, >>>> >>>> >>>> Peter >>>> >>>> Am 14.09.2016 um 01:20 schrieb Bonnie MacKellar: >>>>> Hi, >>>>> >>>>> I need to create annotations with features, but I am struggling to >>>>> understand the one example given in the manual >>>>> >>>>> DECLARE Annotation EmplRelation >>>>> (Employee employeeRef, Employer employerRef); >>>>> Sentence{CONTAINS(EmploymentIndicator) -> CREATE(EmplRelation, >>>>> "employeeRef" = Employee, "employerRef" = Employer)}; >>>>> >>>>> I understand that this declares an Annotation with two features, one of >>>>> type Employee and one of type Employer. I am assuming these are >>>> Annotations >>>>> that have also been declared in the script? The second part really >>>> baffles >>>>> me. The way I am reading this, if a sentence contains an annotation of >>>> type >>>>> EmploymentIndicator, then create a EmplRelation annotation - and assign >>>> the >>>>> type Employer to feature employeeRef???? That makes no sense. It looks >>>>> like this assigns a type to a feature. I would have assumed we would >> want >>>>> some text as the value, no? Could anyone explain this in more detail? >>>>> >>>>> thanks, >>>>> Bonnie MacKellar >>>>> >>