Fabien POULARD
Jérôme Rocheteau
Laurent Audibert
Matthieu Vernier
Nicolas Hernandez
Nicolas Hernandez
Ce billet explique comment sélectionner des annotations en appliquant des filtres sur les indexes des CASes. On prend l'exemple d'un Analysis Engine qui filtre le mot « saperlipopette » dans des textes.
La plate-forme UIMA offre des facilités pour filtrer les annotations parmi l'index d'un CAS. J'explique rapidement comment faire fonctionner ce mécanisme de filtrage en trois temps :
La partie générique du code ci-dessous correspond à la façon de créer des contraintes qui permettront d'appliquer des filtres sur les annotations. Il s'agit de créer des contraintes sur la valeur de certains traits d'annotations. Une contrainte peut-être vue avec UIMA comme la donnée d'un chemin de traits (feature path) et d'une contrainte de base (contrainte numérique entière, contrainte numérique flottante, contrainte textuelle, etc). Le mécanisme interne à UIMA consiste vérifier si la valeur du chemin de traits de chaque annotation sélectionnée satisfait effectivement la relation définie par la contrainte de base. C'est ce que fait la méthode getConstraint dans la classe ci-dessous.
La méthode getBasicConstraint renvoie la contrainte de base en fonction de la valeur et plus précisément de son type. Cette méthode s'appuie alors sur deux méthodes getIntContraint et getStringConstraint qui renvoie la contrainte de base en fonction de la relation voulue entre le chemin de traits et la valeur précédente, à savoir une relation d'égalité ou d'inégalité.
En outre, l'Analysis Engine ci-dessous définit une méthode getType qui renvoie le type à partir de son nom et une méthode getFeaturePath qui renvoie le chemin de traits correspondant au type d'annotation et au nom de ce trait.
L'Analysis Engine Filtering suivant réalise les opérations décrites ci-dessus et les met en œuvre afin d'afficher les mots « saperlipopette ». On suppose ainsi que le Type System de cet Analysis Engine contient un type d'annotation fr.free.rocheteau.jerome.Mot qui possède un trait value correspondant au texte couvert par ces mots.
public class Filtering extends JCasAnnotator_ImplBase {
private Type getType (JCas cas,String name) {
Type type = cas.getTypeSystem().getType(name);
if (type == null) {
type = cas.getTypeSystem().getType(name);
if (type == null) {
type = cas.getTypeSystem().getType(name);
if (type == null) {
String msg = "Unknown type " + name);
System.out.println(msg);
}
}
}
return type;
}
private FeaturePath getFeaturePath(JCas cas,Type type,String feat) {
Feature feature = type.getFeatureByBaseName(feat);
FeaturePath path = cas.createFeaturePath();
path.addFeature(feature);
return path;
}
private int EQ = 0;
private int LT = 1;
private int LEQ = 2;
private int GEQ = 3;
private int GT = 4;
private FSConstraint getStringConstraint(ConstraintFactory factory,int type,String string) {
FSStringConstraint constraint = factory.createStringConstraint();
if (type == this.EQ) {
constraint.equals(string);
} else {
return null;
}
return constraint;
}
private FSConstraint getIntConstraint(ConstraintFactory factory,int type,Integer integer) {
FSIntConstraint constraint = factory.createIntConstraint();
if (type == this.EQ) {
constraint.eq(integer);
} else if (type == this.LT) {
constraint.lt(integer);
} else if (type == this.LEQ) {
constraint.leq(integer);
} else if (type == this.GT) {
constraint.gt(integer);
} else if (type == this.GEQ) {
constraint.geq(integer);
} else {
return null;
}
return constraint;
}
private FSConstraint getBasicConstraint(ConstraintFactory factory,int type,Object value) {
if (value instanceof java.lang.String) {
return this.getStringConstraint(factory, type,(String) value);
} else if (value instanceof java.lang.Integer) {
return this.getIntConstraint(factory,type,(Integer) value);
} else {
return null;
}
}
private FSMatchConstraint getConstraint(JCas cas,Type type,String feat,int typ,Object value) {
ConstraintFactory factory = cas.getConstraintFactory();
FSConstraint constraint = this.getBasicConstraint(factory,typ,value);
FeaturePath path = this.getFeaturePath(cas,type,feat);
FSMatchConstraint filter = factory.embedConstraint(path,constraint);
return filter;
}
public void initialize(UimaContext context) throws ResourceInitializationException {
}
public void process(JCas cas) throws AnalysisEngineProcessException {
Type type = this.getType(cas,"fr.free.rocheteau.jerome.Mot");
FSMatchConstraint filter = this.getConstraint(cas,type,"value",this.EQ,"saperlipopette");
FSIterator iter = cas.getAnnotationIndex(type).iterator();
FSIterator res = cas.createFilteredIterator(iter,filter);
while (res.hasNext()) {
Annotation a = res.next();
System.out.println(a.toString(2));
}
}
}