Am 08.06.2012 um 08:56 schrieb <[email protected]>:
> Hi,
>
> I like to call an annotator from another annotator as it uses annotatations
> for which annotators already exist. Calling is not a problem, but setting the
> parameter is. Can this be done at all? How? Using uimaFIT the parameter
> values are injected using the AnalysisEngineFactory.createPrimitive(). Doing
> so the parameters are set in the UIMA context of the outer annotator. The
> inner annotator has its own UIMA context, does it? How can the outer
> annotator's context be accessed while creating the inner annotator? At first
> I thought that this could be done the same way as Philip Ogren has done with
> XWriterFileNamer and XWriter. You just set the parameters for your
> XWriterFileNamer implmentation in the XWriter context. But this seems to be a
> little different as I don't instantiate a CasAnnototar_ImplBase object but
> create an annotator description which is than use to instantiate an
> AnalysisEngine object by AnalysisEngineFactory in uimaFit or UIMAFramework in
> UIMA itself. Do you have any suggestions? Or is it just me, not getting to
> understand the UIMA way again?
If I understand you correctly, you want to create an OuterAE to which you pass
parameters. The OuterAE should use some of these parameters itself and forward
the rest to an InnerAE that it creates. To accomplish that, you would like the
InnerAE to access the same UIMAContext object as the OuterAE.
I think it's not possible or wise to have two AEs access the same UIMAContext
object. But it is possible to forward parameters - NOT recommened for various
reasons (read on). I tried to hack something together here that should work
(untested):
public static class OuterAnnotator extends CasAnnotator_ImplBase
{
@Override
public void initialize(UimaContext context) throws
ResourceInitializationException {
super.initialize(context);
// Copy all parameters into an array which can be
passed as the variadic parameter list
// to createPrimitiveDesription
List<Object> parameters = new ArrayList<Object>();
for (String name : context.getConfigParameterNames()) {
parameters.add(name);
parameters.add(context.getConfigParameterValue(name));
}
// Create a new AE which has access to all the
parameters set on the outer AE
AnalysisEngineDescription aed =
createPrimitiveDescription(InnerAnnotator.class,
parameters.toArray(new
Object[parameters.size()]));
}
@Override
public void process(CAS aCAS) throws
AnalysisEngineProcessException {
//...
}
}
I would like to point out though, that you are going to run into problems with
this approach, because in general there is no way to properly separate
parameters that go to the inner and to the outer AE. Well, you could introduce
a prefix and only parameters having that prefix are passed to the inner AE, but
what if your InnerAE has another InnerInnerAE...?
The ConceptMapperAnnotator in the UIMA sandbox accepts the path of an
AnalysisEngineDescriptor for a tokenizer as a parameter and then instantiates
this, but it doesn't set any additional parameters. So when one sets up the
pipeline, one can create a AnalysisEngineDescription for the tokenizer,
serialize it as XML to a temporary file using the toXml() method and then pass
that file to the ConceptMapperAnnotator. In that way, the
ConceptMapperAnnotator does not have to know anything about how to pass on
parameters to the tokenizer and avoids any potential parameter name clashes.
At the moment, uimaFIT doesn't have explicit support for injecting
AnalysisEngineDescriptors directly as parameters. One could imagine something
like this:
createPrimitiveDescriptor(OuterAE.class,
OuterAE.PARAM_NAME, "outer",
OuterAE.PARAM_INNER_AE,
createPrimitiveDescriptor(InnerAE.class,
PARAM_NAME, "inner");
We do something like that already for external resources. I think it would make
sense to add it for analysis engines as well. In that example above, you
can also see the that there could easily be a parameter name clash between the
parameters of the inner and outer AE. Philip liked to work around that by
prepending the full class name to each parameter name, but that approach fails
if OuterAE and InnerAE are actually two components of the same class with
different configurations, e.g. some generic filtering AE.
As long as uimaFIT doesn't support engine injection, I'd suggest you work with
a temporary descriptor file that you generate with uimaFIT and pass to your
OuterAE.
- use AnalysisEngineFactory.createPrimitiveDescription(...) to create the
descriptor for your inner AE
- call
AnalysisEngineDescription.resolveImports(UIMAFramework.newDefaultResourceManager())
once on the descriptor to resolve it
- persist the generated descriptor to a temporary file using
AnalysisEngineDescription.toXML()
- pass the path to that file as InnerAEDescriptorPath to OuterAE
File.createTempFile() and File.deleteOnExit() are very helpful here.
-- Richard
--
-------------------------------------------------------------------
Richard Eckart de Castilho
Technical Lead
Ubiquitous Knowledge Processing Lab (UKP-TUD)
FB 20 Computer Science Department
Technische Universität Darmstadt
Hochschulstr. 10, D-64289 Darmstadt, Germany
phone [+49] (0)6151 16-7477, fax -5455, room S2/02/B117
[email protected]
www.ukp.tu-darmstadt.de
Web Research at TU Darmstadt (WeRC) www.werc.tu-darmstadt.de
-------------------------------------------------------------------