OMERO Application Programming Interface

All interaction with the OMERO server takes place via several API services available from a ServiceFactory. A service factory is obtained from the client connection e.g. Python:

import omero.clients

client = omero.client("localhost")
session = client.createSession("username", "password")   # this is the service factory
adminService = session.getAdminService()                 # now we can get/create services
  • The Service factory API has methods for creating Stateless and Stateful services, see below.
    • Stateless services are obtained using “getXXX” methods e.g. getQueryService()
    • Stateful services are obtained using “createXXX” methods e.g. createRenderingEngine()
  • Services will provide access to omero.model.objects. You will then need the API for these objects, e.g. Dataset, Image, Pixels, etc.

Services list

The ome.api package in the common component defines the central “verbs” of the OMERO system. All external interactions with the system should happen with these verbs, or services. Each OMERO service belongs to a particular service level with each level calling only on services from lower levels.

Service Level 1 (direct database and Hibernate connections)

  • AdminService: src, API for working with Experimenters, Groups and the current Context (switching groups etc.).
  • ConfigService: src, API for getting and setting config parameters.
  • ContainerService: API for loading Project, Dataset, Image, Screen, Plate hierarchies.
  • LdapService: src, API for communicating with LDAP servers.
  • MetadataService: API for working with Annotation and retrieving acquisition metadata e.g. instrument.
  • PixelsService: API for pixels stats and creating Images with existing or new Pixels.
  • ProjectionService API for performing projections of Pixels sets.
  • QueryService: src, API for custom SQL-like queries.
  • RenderingSettingsService API for copying, pasting & resetting rendering settings.
  • RepositoryInfo API disk space stats.
  • RoiService API working with ROIs (now deprecated).
  • ScriptService API for uploading and launching Python scripts.
  • SessionService API for creating and working with OMERO sessions.
  • ShareService API (now deprecated).
  • TimelineService API for queries based on time.
  • TypesService API for Enumerations.
  • UpdateService: src, API for saving and editing omero.model objects.

Service Level 2

Stateful/Binary Services

  • RawFileStore: src, API for reading and writing files
  • RawPixelsStore: src, API for reading and writing pixels data
  • RenderingEngine: src, API for viewing images, see OMERO rendering engine for more details
  • ThumbnailStore: src, API for retrieving thumbnails
  • IScale for scaling rendered images

A complete list of service APIs can be found here and some examples of API usage in Python are provided. Java or C++ code can use the same API in a very similar manner.

Discussion

Reads and writes

IQuery and IUpdate are the basic building blocks for the rest of the (non-binary) API. IQuery is based on QuerySources and QueryParemeters which are explained under Using server queries internally. The goal of this design is to make wildly separate definitions of queries (templates, db-stored, Java code, C# code, …) runnable on the server.

IUpdate takes any graph composed of IObject objects and checks them for dirtiness. All changes to the graph are stored in the database if the user calling IUpdate has the proper permissions, otherwise an exception is thrown.

Dirty checks follow the Three Commandments:

  1. Any IObject-valued field with unloaded set to true is treated as a proxy and is reloaded from the database.
  2. Any collection-valued field with a null value is re-loaded from the database.
  3. Any collection-valued field with the FILTERED flag is assumed to be dirty and is loaded from the database, with the future option of examining the filtered collection for any new and updated values and applying them to the real collection. Deletions cannot happen this way since it would be unclear if the object was filtered or deleted.

Administration

The IAdmin interface defines all the actions necessary to administer the Server security and firewalls. It is explained further on the OMERO admin interface page.

Model Object Java

Certain operations, like those dealing with data management and viewing, happen more frequently than others e.g. defining microscopes. Those have been collected in the IContainer interface. IContainer simplifies a few very common queries, and there is a related package omero.gateway.model.\* for working with the returned graphs. OMERO.insight works almost exclusively with the IContainer interface mostly indirectly via the Java Gateway.

Examples

// Saving a simple change
Dataset d = iQuery.get(Dataset.class, 1L);
d.setName("test");
iUpdate.saveObject(d);

// Creating a new object
Dataset d = new Dataset();
d.setName("test"); // not-null fields must be filled in
iUpdate.saveObject(d);

// Retrieving a graph
Set<Dataset> ds = iQuery.findAllByQuery("from Dataset d left outer join d.images where d.name = 'test'", null);

Stateless versus stateful services

A stateless service has no client-noticeable lifecycle and all instances can be treated equally. A new stateful service, on the other hand, will be created for each client-side proxy, see the ServiceFactory.createXXX methods. Once obtained, a stateful service proxy can only be used by a single user. After task completion, the service should be closed i.e. proxy.close() to free up server resources.

How to write a service

A tutorial is available at How To create a service. See Build System for more information on how the annotated service will be deployed. In the case of OMERO.blitz, the service must be properly defined under components/blitz/resources.

OMERO annotations for validation

The server-side implementation of these interfaces makes use of Java annotations and an AOP interceptor to validate all method parameters. Calls to pojos.findContainerHierarchies are first caught by a method interceptor, which checks for annotations on the parameters and, if available, performs the necessary checks. The interceptor also makes proactive checks. For a range of parameter types such as Java Collections it requires that annotations exist and will refuse to proceed if not implemented.

An API call of the form:

pojos.findContainerHierarchies(Class, Set, Map)

is implemented as

pojos.findContainerHierarchies(@NotNull Class, @NotNull @Validate(Integer.class) Set, Map)