uima-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Richard Eckart de Castilho <eck...@ukp.informatik.tu-darmstadt.de>
Subject Re: Calling an annotator from another annotator
Date Fri, 08 Jun 2012 07:43:22 GMT
Am 08.06.2012 um 08:56 schrieb <Armin.Wegner@bka.bund.de>:

> 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
eckart@ukp.informatik.tu-darmstadt.de 
www.ukp.tu-darmstadt.de 
Web Research at TU Darmstadt (WeRC) www.werc.tu-darmstadt.de
------------------------------------------------------------------- 







Mime
View raw message