Writing Python plugin

I am writing a Python SNAP plugin (https://github.com/DHI-GRAS/sen-et-snap) and I run into a couple of questions for which I couldn’t find answers online. Any help on those would be greatly appreciated.

  1. Can an operator have multiple target products and if yes then how to specify this?
  2. I am running SNAP through IntelliJ and all the print statements output to the IntelliJ terminal. How can I display messages in SNAP GUI (e.g. in the operator dialog) instead? This could be to indicate progress, advise on input parameters, report errors, etc.
  3. My operators are available through the specified SNAP menu (in my case Optical) but I cannot see them when creating a graph. How can I specify that an operator should be available in the graph dialog?
  4. How can I find out from snappy how many processors and how much memory are assigned to SNAP?
  5. How can I create a File/Folder parameter?
  6. How can I specify which source product a Band parameter refers to? Currently it always reads the bands from the first source product.
  7. Which exception should I use in case the user sets wrong parameters or input data is wrong? I would like a warning dialog to be displayed and the user given the possibility to select different parameters and inputs.
  8. How to set autoWriteDisabled? I tried to set it in -info.xml but it didn’t seem to work. How exactly does it affect computeTileStack and computeTile methods?

Thank you and regards

Dear SNAP developers,
Would anyone be able to assist with the above questions now that SNAP 7 is out?

Hello @radosuav ,
For beginning, I will try to answer what I know.

Q1. There is only one targetProductFile parameter (read-only). It is a File corresponding to the target product that will be loaded in SNAP after the tool execution.

Q2. There are 2 elements available (progressPattern, errorPattern), under <operator>. E.g.
<progressPattern>.*: (\d{1,3})%(?:.+)</progressPattern>

Q3. When creating a graph, search the external operator under Add -> Tools (not under Optical)

Q5. By setting its dataType to “java.io.File”

Q7. There are already basic validations done (with popup dialogs displayed), depending on the configuration of a parameter:

  • not empty value [notEmpty]
  • required parameter [notNull]
  • value of a specified data type [dataType]
  • regex validations for [progressPattern] and [errorPattern]
  • value within value set [valueSet])

Q8. It’s autoWriteSupressed, e.g.:

I am supposing you already saw the help page inside SNAP:

Also, you can install an existing external plugin in SNAP (from Tools -> Plugins -> Available Plugins), and then try to export it in order to see exactly how it’s made (Tools -> Manage External Tools -> select an operator -> click on Edit -> Export as module :

Best regards,

Hi Oana,
Thank you for the useful tips! Unfortunately not everything seems to be working.

Q2. If I put any of those elements under <operator> I get “Unexpected Exception: Could not initialize class org.esa.snap.python.gpf.PyOperatorSpi” when starting SNAP and cannot open the operator.

Q3. I cannot find my operators under Add -> Tools. Is it because operatorClass is org.esa.snap.python.gpf.PyOperator and not org.esa.snap.core.gpf.operators.tooladapter.ToolAdapterOp? Is there a way to add org.esa.snap.python.gpf.PyOperator to graphs?

Q5. java.ioFile works fine but if I use $USERPROFILE in the I get an “Unexpected Exception”. However this is not a critical issue for me.

Q8. <autoWriteSuppressed>false</autoWriteSuppressed> works (i.e. I do not get an exception when starting SNAP) but in the operator dialog there is still Target Product area on the I/O tab. Is there a way to remove the Target Product selection from this tab? Alternatively, can I somehow limit the output format of the Target Products (e.g. just to NetCDF).

Thank you!

Hello Rado,
You are right, there are several differences for python.
Do you have access to the following guide:
If not, you can find attached the PDF export of this page.SNAP-HowtowriteaprocessorinPython-190819-1518.pdf (75.4 KB)
Here you will also find how to make the plugin visible in graph builder (by adding a org.esa.snap.python.gpf.PyOperatorSpi in META-INF/services).
Best regards,

Hi Oana,

Thank you for the links. I have access to the guide but still was not sure what is the purpose of org.esa.snap.python.gpf.PyOperatorSpi. However, I have the the directory and file structure as described in the guide, including org.esa.snap.python.gpf.PyOperatorSpi and still the operators do not appear in the GPF graph builder. Does the content of PyOperatorSpi look correct?

There is no mention of <progressPattern>, <errorPattern> or <autoWriteSuppressed> in the Python guide. Does this mean that those parameters do not work with Python processors?

Best regards

Hi Rado,
PyOperator uses DefaultOperatorDescriptor, which contains less fields than ToolAdapterOperatorDescriptor.
However, among the 3 fields you mentioned, autoWriteSuppressed is available in both types of descriptors (so it’s available for PyOperator)
Regarding your org.esa.snap.python.gpf.PyOperatorSpi file, it looks OK…

Best regards,

Hi Oana,
Does this mean that there is no way to display progress and errors to the users, in a similar mechanism to <progressPattern>, <errorPattern>? And what does <autoWriteSuppressed> do? I do not see any difference when this property is set to False or True in the behavior of the operator? Finally, would you know where I could look for a reason for why the operators do not appear in the graph builder even though PyOperatorSpi is fine? Is there any log where a relevant error could be found?
Thank you!

Hello Rado,
I build the nbm for your plugin, I installed it in SNAP, there was no error in the log.
I see the operators in SNAP menu. Also, they are available in gpt (open a cmd window and type “gpt -h”), but not exaclty under the names declared in org.esa.snap.python.gpf.PyOperatorSpi.

So, even if they are not available in Graph Builder (for which I asked further details to Marco), you can use them inside a graph and execute the graph in gpt.
Have you tried it already?
Best regards,

Hi Oana,
Thank you for testing this! I did not try looking for the operators in the command line interface of GPT since I did not find them in the in the GUI. I will do some testing through the command line but still hope that there is a way to make them appear in the GUI.

Hi Rado,
Maybe @obarrilero or @marpet can shed some light on whether/how external python operators can appear in Graph Builder.
Best regards,

Yes, I can. It is a known issue of the GraphBuilder.
So, for the time being they don’t show up in the GraphBuilder.

Thanks for the clarification @marpet. Would you or @obarrilero have any tips regarding other issues listed at the top of this thread?

I just checked which questions were not yet answered.

Progress reporting is currently not supported, maybe there is some default progress indicator, but I’m not sure. Validation messages are shown automatically to the user.
The parameters Oana mentioned do only work if you use the standard tools adapter, but nor if you only implement a python operator.

Load the class java.lang.Runtime via jpy.get_type()
and then call:
runtime = Runtime.getRuntime()
total = runtime.totalMemory()
free = runtime.freeMemory()
max = runtime.maxMemory()
numProc = runtime.availableProcessors()

See also: https://docs.oracle.com/javase/8/docs/api/java/lang/Runtime.html

This is currently not possible. But you can set a value set of names, from which the user can select from.

As Oana already said, some validation is already done. If you want to throw your own exception you can throw a RuntimeError.

If you like to look at an example. Check this repository: https://github.com/senbox-org/snap-rut

Now, I go on holiday. See you in three weeks :beach_umbrella:

Hi again,

In the end we decided to switch to ToolAdapterOp approach. This is mainly because in PyOperator there seems to be no way to report progress to the user (as confirmed by @marpet) and this is critical functionality.

I am wandering now how to set target product in ToolAdapterOp. All the adapters in https://github.com/senbox-org/s2tbx/tree/master/s2tbx-sta-adapters are setting the output as one of the parameters. I tried the following in descriptor.xml but still there is no output in the I/O Parametrs tab of the operator dialog:

Is there an example or instructions somewhere on which tags to use?


@oana_hogoiu, @marpet, @obarrilero could you please assist me with the question from the previous post?

In the meantime I got one more question. Using the <rasterDataNodeClass>org.esa.snap.core.datamodel.Band</rasterDataNodeClass> tag for a parameter does not link it to any source products of the operator. When used with a Python operator it would link the parameter to the first source product. Is there a way to automatically generate a drop down list of available bands in ToolAdapterOp?


Hello Rado,
Regarding the output parameter, the only way to do it is using a parameter having its name “targetProductFile”.
This is a default parameter:

Also, in ToolAdapterConstants you can see a constant with this value, which is after used in finding the output parameter (by its name).

As for the second question, from the code that I see inside ParameterDescriptorFactory (lines 195-208), it should detect the bands of the first source product and fill the value set for that parameter with the list of bands. You can try it with org.esa.snap.core.datamodel.Band.class (I see it used like this in the annotated operators)

Best regards,

Hi Oana,
Thank you for the tip. Indeed naming a parameter as targetProductFile and setting <isHandlingOutputName> to false results in Target Product appearing on the I/O Parameters tab. But it also raises other issues.

The output parameter also appears in the Processing Parameters tab. So where should it be set and how do the two outputs relate? Target Product is always set to be saved in temp directory and in DIM format (is there a way to change this dynamically) while in the parameters tab I can control both the output path and the file format. Is there documentation which explains the behavior?

Related to the previous question regarding <rasterDataNodeClass>, do I have to specify the source product explicitly? I noticed that while previously (in Python Operator) I could write something like
in ToolAdapterOp this has to be written as
So I am wondering if there is a similar change in syntax for raster data node.


Hi again,
Just a bit more information on setting rasterDataNodeClass.

When I set it to org.esa.snap.core.datamodel.Band.class, the following error is reported when SNAP is starting the and operator dialog does not load:

When I set it to org.esa.snap.core.datamodel.Band, the operator dialog loads but there is no connection between the source products and the band parameter (i.e. the drop down list is always empty).


Hello Rado,
Using rasterDataNodeClass, the value set is dynamically filled.
If you want to set fixed values in the xml descriptor, you can specify the values as in your example (string array of values).
The handling of the output parameter should be done in an “after/post” velocity template.
Regarding the error “No such field MemoryTemplate.file” maybe you have an error in your template? Are you using this object in your template? (there is no such field indeed…)

Best regards,