【发布时间】:2015-03-05 22:23:33
【问题描述】:
我在将自定义注释文档转换为 UIMA CAS 并将它们序列化为 XMI 以便通过 UIMA 注释查看器 GUI 查看注释时遇到问题。
我使用 uimaFIT 来构建我的组件,因为它更易于控制、测试和调试。管道由 3 个组件构成:
-
CollectionReader组件读取带有原始文本的文件。 -
Annotator用于将注释从自定义文档转换为 UIMA 注释的组件 -
CasConsumer将 CAS 序列化为 XMI 的组件
我的管道工作并在最后输出 XMI 文件,但没有注释。我不太清楚 CAS 对象是如何在组件之间传递的。注释器逻辑包括对某些端点进行 RESTful 调用,并使用我尝试转换注释模型的服务提供的客户端 SDK。 Annotator 组件的转换逻辑部分如下所示:
public class CustomDocumentToUimaCasConverter implements UimaCasConverter {
private TypeSystemDescription tsd;
private AnnotatedDocument startDocument;
private ArrayFS annotationFeatureStructures;
private int featureStructureArrayCapacity;
public AnnotatedDocument getStartDocument() {
return startDocument;
}
public CustomDocumentToUimaCasConverter(AnnotatedDocument startDocument) {
try {
this.tsd = TypeSystemDescriptionFactory.createTypeSystemDescription();
} catch (ResourceInitializationException e) {
LOG.error("Error when creating default type system", e);
}
this.startDocument = startDocument;
}
public TypeSystemDescription getTypeSystemDescription() {
return this.tsd;
}
@Override
public void convertAnnotations(CAS cas) {
Map<String, List<Annotation>> entities = this.startDocument.entities;
int featureStructureArrayIndex = 0;
inferCasTypeSystem(entities.keySet());
try {
/*
* This is a hack allowing the CAS object to have an updated type system.
* We are creating a new CAS by passing the new TypeSystemDescription which actually
* should have been updated by an internal call of typeSystemInit(cas.getTypeSystem())
* originally part of the CasInitializer interface that is now deprecated and the CollectionReader
* is calling it internally in its implementation. The problem consists in the fact that now the
* the typeSystemInit method of the CasInitializer_ImplBase has an empty implementation and
* nothing changes!
*/
LOG.info("Creating new CAS with updated typesystem...");
cas = CasCreationUtils.createCas(tsd, null, null);
} catch (ResourceInitializationException e) {
LOG.info("Error creating new CAS!", e);
}
TypeSystem typeSystem = cas.getTypeSystem();
this.featureStructureArrayCapacity = entities.size();
this.annotationFeatureStructures = cas.createArrayFS(featureStructureArrayCapacity);
for (Map.Entry<String, List<Annotation>> entityEntry : entities.entrySet()) {
String annotationName = entityEntry.getKey();
annotationName = UIMA_ANNOTATION_TYPES_PACKAGE + removeDashes(annotationName);
Type type = typeSystem.getType(annotationName);
List<Annotation> annotations = entityEntry.getValue();
LOG.info("Get Type -> " + type);
for (Annotation ann : annotations) {
AnnotationFS afs = cas.createAnnotation(type, (int) ann.startOffset, (int) ann.endOffset);
cas.addFsToIndexes(afs);
if (featureStructureArrayIndex + 1 == featureStructureArrayCapacity) {
resizeArrayFS(featureStructureArrayCapacity * 2, annotationFeatureStructures, cas);
}
annotationFeatureStructures.set(featureStructureArrayIndex++, afs);
}
}
cas.removeFsFromIndexes(annotationFeatureStructures);
cas.addFsToIndexes(annotationFeatureStructures);
}
@Override
public void inferCasTypeSystem(Iterable<String> originalTypes) {
for (String typeName : originalTypes) {
//UIMA Annotations are not allowed to contain dashes
typeName = removeDashes(typeName);
tsd.addType(UIMA_ANNOTATION_TYPES_PACKAGE + typeName,
"Automatically generated type for " + typeName, "uima.tcas.Annotation");
LOG.info("Inserted new type -> " + typeName);
}
}
/**
* Removes dashes from UIMA Annotations because they are not allowed to contain dashes.
*
* @param typeName the annotation name of the current annotation of the source document
* @return the transformed annotation name suited for the UIMA typesystem
*/
private String removeDashes(String typeName) {
if (typeName.contains("-")) {
typeName = typeName.replaceAll("-", "_");
}
return typeName;
}
@Override
public void setSourceDocumentText(CAS cas) {
cas.setSofaDataString(startDocument.text, "text/plain");
}
private void resizeArrayFS(int newCapacity, ArrayFS originalArray, CAS cas) {
ArrayFS biggerArrayFS = cas.createArrayFS(newCapacity);
biggerArrayFS.copyFromArray(originalArray.toArray(), 0, 0, originalArray.size());
this.annotationFeatureStructures = biggerArrayFS;
this.featureStructureArrayCapacity = annotationFeatureStructures.size();
}
}
` 如果有人处理过向 UIMA 类型的注释转换,我将不胜感激。
【问题讨论】:
-
自定义注释文档:这些是 UIMA 注释吗?
-
不,他们不是。
AnnotatedDocument和Map<String, List<Annotation>>是我正在使用的服务的客户端 SDK 的对象部分。服务输出门 json,但我直接使用解析结果。
标签: java rest annotations nlp uima