# OMERO.scripts user guide

OMERO.blitz provides a service to run scripts on the server. The scripts are then passed on to a grid of processors called OMERO.grid that executes the script and returns the result to the server which in turn passes the result onto the caller. All scripts are of the form:

    # import the omero package and the omero.scripts package.
    import omero, omero.scripts as scripts

    '''
    This method creates the client script object, with name SCRIPTNAME and SCRIPTDESCRIPTION.
    The script then supplies a number of variables that are both inputs and outputs to the
    script. The types allowed are defined in the script package, with the qualifier after the
    variable of in, out or inout depending on whether the variable if for input, output or input
    and output.
    '''
    client = scripts.client("SCRIPTNAME", "SCRIPTDESCRIPTION",
             scripts.TYPE("VARIABLENAME").[in()|out()|inout()], …)

    # All variables are stored in a map accessed by getInput and setOutput via the client object.
    VARIABLENAME = client.getInput("VARIABLENAME");
    client.setOutput("VARIABLENAME", value);

This is a guide to getting started with the scripting service, without going into the ‘behind the scenes’ details. More technical details can be found on the OMERO.scripts advanced topics page. In addition to this guide, you may find the following pages useful for more information on using the OMERO Python API: Working with OMERO, OMERO Python language bindings.

## Sample scripts

Below are two sample scripts. You can find the core scripts that are distributed with the OMERO.server under the scripts repository or download them from OMERO.insight (from the bottom-left of any run-script dialog), or use the GitHub repositories forked from ome/omero-user-scripts to find scripts written by other users.

### Ping script

This script echoes the input parameters as outputs.

    import omero, omero.scripts as scripts
    client = scripts.client("ping.py", "simple ping script",
                            scripts.Long("a"), scripts.String("b"))

    keys = client.getInputKeys()
    print("Keys found:")
    print(keys)
    for key in keys:
          client.setOutput(key, client.getInput(key))

### Accessing an Image and Channels on the server

This example shows usage of the Python Blitz Gateway to access an Image, using its ID. We then list the Channel names and the script returns them as outputs.

    import omero, omero.scripts as scripts
    from omero.gateway import BlitzGateway
    from omero.rtypes import wrap

    # Define the script name & description, and a single 'required' parameter
    client = scripts.client("Get_Channels.py", "Get channel names for an image",
                            scripts.Long("imageId", optional=False))

    # get the Image Id from the parameters.
    imageId = client.getInput("imageId", unwrap=True)   # unwrap the rtype

    # Use the Python Blitz Gateway for convenience
    conn = BlitzGateway(client_obj=client)

    # get the Image, print its name
    image = conn.getObject("Image", imageId)
    print(image.getName())

    # Print each channel 'label' (Name or Excitation wavelength)
    for i, ch in enumerate(image.getChannels()):
        print(ch.getLabel())
        # Return as output. Key is string, value is rtype
        client.setOutput("Channel%s" % i, wrap(str(ch.getLabel())))

    # Cleanup
    client.closeSession()

### Dynamic arguments

In general, script parameters are processed on server startup and cached for later use. If you have a script which should recalculate its arguments on each invocation, use the NSDYNAMIC namespace:

    # A list of datasets will be dynamically generated and used to populate the
    # script parameters every time the script is called

    import omero
    import omero.gateway
    from omero import scripts
    from omero.rtypes import rstring

    def get_params():
        try:
            client = omero.client()
            client.createSession()
            conn = omero.gateway.BlitzGateway(client_obj=client)
            conn.SERVICE_OPTS.setOmeroGroup(-1)
            objparams = [rstring('Dataset:%d %s' % (d.id, d.getName()))
                         for d in conn.getObjects('Dataset')]
            if not objparams:
                objparams = [rstring('<No objects found>')]
            return objparams
        except Exception as e:
            return ['Exception: %s' % e]
        finally:
            client.closeSession()

    def runScript():
        """
        The main entry point of the script
        """

        objparams = get_params()

        client = scripts.client(
            'Example Dynamic Test', 'Example script using dynamic parameters',

            scripts.String(
                'Dataset', optional=False, grouping='1',
                description='Select a dataset', values=objparams),

            namespaces=[omero.constants.namespaces.NSDYNAMIC],
        )

        try:
            scriptParams = client.getInputs(unwrap=True)
            message = 'Params: %s\n' % scriptParams
            print(message)
            client.setOutput('Message', rstring(str(message)))

        finally:
            client.closeSession()

    if __name__ == '__main__':
        runScript()

`Example_Dynamic_Script.py`

## Script writing as ‘Admin’

The basic steps in a script-writing workflow are:

- Write a script using your favorite text editor, save locally

- Use command line (or OMERO.insight) to upload the script to server

- Use command line (or OMERO.insight or web clients) to run the script on the server (results will be displayed)

- Edit the script and replace it on the server and run again, etc.

Working with scripts is far more straightforward if you have admin access to your OMERO.server installation - this is the preferred workflow. It is possible to work with scripts as a regular user (see OMERO.scripts advanced topics) but the software you would be required to install means it is easier to install a server on your local machine so you have admin rights.

It is assumed that scripts written by a server admin are “trusted” to run on the server without causing any disruption or security risks. Once uploaded these scripts are available to all regular users of the server alongside the official scripts included in each OMERO release.

### Download / Edit script

The easiest way to get started is to take an existing script and edit it for your needs. An example created for the purpose of this tutorial can be found at Edit_Descriptions.py. You should organize your scripts on your local machine in a way that makes sense to users, since your local file paths will be mimicked on the server and used to organize script menus in the clients (see screen-shot above).

    # Save the script to a suitable location. The tutorial will use this location:
    # Desktop/scripts/demo_tutorial/Edit_Descriptions.py

The action of this script (editing Image descriptions) is trivial but it demonstrates a number of features that you may find useful, including conventions for inputs and outputs to improve interaction with the clients(as discussed on the Guidelines for writing OMERO.scripts).

The script is well-documented and should get you started. A few points to note:

If you are using the ‘Blitz Gateway’ then you can get a connection wrapper like this:

    from omero.gateway import BlitzGateway

    conn = BlitzGateway(client_obj=client)
    # now you can do e.g. conn.getObject("Image", imageId) etc.

Alternatively, if you are working directly with the OMERO services, you can get a service factory like this:

    session = client.getSession()
    # now you can do e.g. session.getQueryService() etc.

### More example scripts

Several official scripts are included in the release of OMERO and can be found under the lib/scripts/omero/ directory of the server package. Any script can also be download from the clients (bottom-left of the run-script dialog).

Warning

If you wish to edit the official scripts that are part of the OMERO release, you should be prepared to apply the same changes to future releases of these scripts from OMERO. If you think that your changes should be included as part of future released scripts, please let us know.

### Upload script

You can use the command line, OMERO.insight or the server file system to upload scripts. The `script` command line tool is discussed in more detail below.

Upload the script we saved earlier, specifying it as ‘official’ (trusted to run on the server processor). You will need to log in the first time you use the omero script command. The new script ID will be printed out:

    $ cd Desktop/scripts/
    $ omero script upload demo_tutorial/Edit_Descriptions.py --official
    Previously logged in to localhost:4064 as root
    Server: [localhost]          # hit 'enter' to accept default login details
    Username: [root]
    Password:
    Created session 09fcf689-cc85-409d-91ac-f9865dbfd650 (root@localhost:4064). Idle timeout: 10.0 min. Current group: system
    Uploaded official script as original file #301

You can add, remove and edit scripts directly in the OMERO_HOME/lib/scripts/omero/ folder. Any changes made here will be detected by OMERO. Official scripts are uniquely identified on the OMERO server by their ‘path’ and ‘name’.

Any folders in the script path are created on the server under /lib/scripts/ e.g. the above example will be stored at /lib/scripts/examples/Edit_Descriptions.py

The ID of the script is printed after upload and can also be determined by listing scripts (see below).

### Run script

You can run the script from OMERO.insight or OMERO.web by browsing the scripts (see screen-shot above). A UI will be generated from the chosen script and the currently selected images or datasets will be populated if the script supports this (see Guidelines for writing OMERO.scripts).

Or launch the script from the command line, specifying the script ID. You will be asked to provide input for any non-optional parameters that do not have default values specified. Any stdout and stderr will be displayed as well as any outputs that the script has returned.

    $ omero script launch 301  # script ID
    Using session 1202acc0-4424-4fa2-84fe-7c9e069d3563 (root@localhost:4064). Idle timeout: 10.0 min. Current group: system
    Enter value for "IDs": 1201
    Job 1464 ready
    Waiting....
    Callback received: FINISHED

        *** start stdout ***
        * {'IDs': [1201L], 'Data_Type': 'Dataset'}
        * Processing Images from Dataset: LSM - .mdb
        * Editing images with this description:
        * No description specified
        *
        *    Editing image ID: 15651 Name: sample files.mdb [XY-ch-02]
        *    Editing image ID: 15652 Name: sample files.mdb [XY-ch-03]
        *    Editing image ID: 15653 Name: sample files.mdb [XY-ch]
        *    Editing image ID: 15654 Name: sample files.mdb [XYT]
        *    Editing image ID: 15655 Name: sample files.mdb [XYZ-ch-20x]
        *    Editing image ID: 15656 Name: sample files.mdb [XYZ-ch-zoom]
        *    Editing image ID: 15658 Name: sample files.mdb [XYZ-ch0]
        *    Editing image ID: 15657 Name: sample files.mdb [XYZ-ch]
        *
        *** end stdout ***

        *** out parameters ***
        * Message=8 Images edited
        ***  done ***

Parameter values can also be specified in the command.

    # simply specify the required parameters that don't have defaults
    $ omero script launch 301 IDs=1201

    # can also specify additional parameters
    $ omero script launch 301 Data_Type='Image' IDs=15652,15653 New_Description="Adding description from script to Image"

### Edit and replace

Edit the script and upload it to replace the previous copy, specifying the ID of the file to replace.

    $ omero script replace 301 examples/Edit_Descriptions.py

Finally, you can upload and run your scripts from OMERO.insight.

### Other script commands

Start by printing help for the script command:

    $ omero script -h
    usage: omero script
           [-h] <subcommand> ...

    Support for launching, uploading and otherwise managing OMERO.scripts

    Optional Arguments:
      In addition to any higher level options

      -h, --help          show this help message and exit

    Subcommands:
      Use omero script <subcommand> -h for more information.

      <subcommand>
        demo              Runs a short demo of the scripting system
        list              List files for user or group
        cat               Prints a script to standard out
        edit              Opens a script in $EDITOR and saves it back to the server
        params            Print the parameters for a given script
        launch            Launch a script with parameters
        disable           Makes script non-executable by setting the mimetype
        enable            Makes a script executable (sets mimetype to text/x-python)
        jobs              List current jobs for user or group
        serve             Start a usermode processor for scripts
        upload            Upload a script
        replace           Replace an existing script with a new value
        run               Run a script with the OMERO libraries loaded and current login

To list scripts on the server:

    $ omero script list
    Using session 09fcf689-cc85-409d-91ac-f9865dbfd650 (root@localhost:4064). Idle timeout: 10.0 min. Current group: system
     id  | Official scripts
    -----+---------------------------------------------
     202 | /omero/export_scripts/Batch_Image_Export.py
     203 | /omero/export_scripts/Make_Movie.py
     204 | /omero/figure_scripts/Movie_Figure.py
     205 | /omero/figure_scripts/Movie_ROI_Figure.py
     206 | /omero/figure_scripts/ROI_Split_Figure.py
     207 | /omero/figure_scripts/Split_View_Figure.py
     208 | /omero/figure_scripts/Thumbnail_Figure.py
     8   | /omero/import_scripts/Populate_ROI.py
     209 | /omero/util_scripts/Channel_Offsets.py
     210 | /omero/util_scripts/Combine_Images.py
     211 | /omero/util_scripts/Images_From_ROIs.py
    (14 rows)

If you want to know the parameters for a particular script you can use the params command. This prints out the details of the script, including the inputs.

    $ omero script params 301
    Using session 1202acc0-4424-4fa2-84fe-7c9e069d3563 (root@localhost:4064). Idle timeout: 10.0 min. Current group: system

    id:  301
    name:  Edit_Descriptions.py
    version:
    authors:
    institutions:
    description:  Edits the descriptions of multiple Images,
    either specified via Image IDs or by the Dataset IDs.
    namespaces:
    stdout:  text/plain
    stderr:  text/plain
    inputs:
      New_Description - The new description to set for each Image in the Dataset
        Optional: True
        Type: ::omero::RString
        Min:
        Max:
        Values:
      IDs - List of Dataset IDs or Image IDs
        Optional: False
        Type: ::omero::RList
        Subtype: ::omero::RLong
        Min:
        Max:
        Values:
      Data_Type - The data you want to work with.
        Optional: False
        Type: ::omero::RString
        Min:
        Max:
        Values: Dataset, Image
    outputs:

## Debugging scripts

The stderr and stdout from running a script should always be returned to you, either when running scripts from the command line, via the clients or using the scripts API. This should allow you to debug any problems you have.

You can also look at the output from the script in the OriginalFile directory, commonly stored in /OMERO/File/. The script file when executed is uploaded as a new OriginalFile, and the standard error, standard out are saved as the next two OriginalFiles after that. These files can be opened in a text editor to examine contents.