OMERO Matlab language bindings
==============================
See |DevelopingOmeroClients| and |OmeroModel|, for an introduction to
**Object**.
.. highlight:: matlab
Installing the OMERO.matlab toolbox
-----------------------------------
- Download the latest released version from the
:downloads:`download page <>` . For the latest build, go
:omerojob:`here `, and download the OMERO.matlab zip
file.
- Unzip the directory anywhere on your system.
- In Matlab, move to the newly unzipped directory and run ``loadOmero;``.
- The Matlab files are now on your path, and the necessary jars are on
your java classpath. You can change directories and still have access
to OMERO.
Once OMERO.matlab is installed, the typical workflow is:
#. :ref:`connection_init`
#. :ref:`connection_keepalive`
#. :ref:`unsecure_client` (optional)
#. Do some work (load objects, work with them, upload to the server…)
#. :ref:`connection_close`
#. :ref:`unload` (optional)
As a quickstart example, the following lines create a secure connection to a
server, read a series of images and close the connection.
::
client = loadOmero(servername, port);
session = client.createSession(user, password);
client.enableKeepAlive(60);
images = getImages(session, ids);
client.closeSession();
Configuring the OMERO.matlab connection
---------------------------------------
.. _connection_init:
Creating a connection
^^^^^^^^^^^^^^^^^^^^^
As described under |OmeroClients|, there are several ways to configure your
connection to an OMERO server. OMERO.matlab comes with a few conveniences for
making this work.
If you run ``client = loadOmero();`` (i.e. loadOmero with an output argument),
then OMERO.matlab will try to configure the
``omero.client`` object for you. First, it checks the :envvar:`ICE_CONFIG`
environment variable. If set, it will let the ``omero.client``
constructor initialize itself. Otherwise, it looks for the file
:file:`ice.config` in the current directory. The OMERO.matlab toolbox comes
with a default :file:`ice.config` file pointing at ``localhost``. To use this
configuration file, you should replace ``localhost`` by your server address.
Alternatively, you can pass the same parameters to ``loadOmero;`` that
you would pass to ``omero.client``::
>> omero_client_1 = loadOmero('localhost');
>> omero_client_2 = omero.client('localhost');
Or, if you want a session created directly, the following are
equivalent:
::
>> [client1, session1] = loadOmero('localhost');
>> client2 = loadOmero('localhost');
>> session2 = client2.createSession()
.. _connection_keepalive:
Keeping your session alive
^^^^^^^^^^^^^^^^^^^^^^^^^^
For executing any long running task, you will need a background thread
which keeps your session alive. If you are familiar with Matlab
``Timers`` you can use
:source:`omeroKeepAlive.m `
directly or modify it to your liking.
::
>> [c,s] = loadOmero;
>> t = omeroKeepAlive(c); % Create a 60-second timer and starts it
>> …
>> delete(t); % Disable the keep-alive
Alternatively, you can use the Java-based ``enableKeepAlive`` method,
but it is not configurable from within Matlab::
c.enableKeepAlive(60); % Call session.keepAlive() every 60 seconds
c.closeSession(); % Close session to end the keep-alive
.. _unsecure_client:
Creating an unencrypted session
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If you want to speed up the data transfer, you can create and use an
unencrypted session as::
unsecureClient = client.createClient(false);
sessionUnencrypted = unsecureClient.getSession();
.. _connection_close:
Closing your connection
^^^^^^^^^^^^^^^^^^^^^^^
When you are done with OMERO, it is critical that you close your connection to
save resources::
client.closeSession();
clear client1;
clear session1;
If you created an unencrypted session, you will need to close the unsecure
session as well::
client.closeSession();
unsecureClient.closeSession();
.. _unload:
Unloading OMERO
^^^^^^^^^^^^^^^
Then if you would like, you can unload OMERO as well::
unloadOmero();
You may see the following warning when unloading OMERO::
>> unloadOmero()
Warning: Objects of omero/client class exist - not clearing java
> In javaclasspath>doclear at 377
In javaclasspath>local_javapath at 194
In javaclasspath at 105
In javarmpath at 48
In unloadOmero at 75
===============================================================
While unloading OMERO, found java objects left in workspace.
Please remove with 'clear ' and then run 'unloadOmero'
again. Printing all objects...
===============================================================
Name Size Bytes Class Attributes
c 1x1 omero.client
Closing session(s) for 1 found client(s): c
This means that there is still an OMERO.matlab object in your workspace. If
not listed, use ``whos`` to find such objects, and ``clear`` to remove them.
After that, run ``unloadOmero()`` again::
>> clear c
>> unloadOmero()
.. warning::
You should also unload OMERO before installing a new version of
OMERO.matlab or calling ``loadOmero`` again.
If you need to create another session without unloading/loading OMERO
again, use the ``omero.client`` object directly::
>> [c,s] = loadOmero(arg1,arg2);
>> c = omero.client(arg3,arg4);
>> s = c.createSession();
Reading data
------------
The ``IContainer`` service provides methods to load the data management
hierarchy in OMERO -- projects, datasets… A list of examples follows
indicating how to load projects, datasets, screens…
- **Projects**
The projects owned by the user currently logged in can be retrieved using the
:source:`getProjects `
function::
projects = getProjects(session)
If the project identifiers are known, they can be specified as::
projects = getProjects(session, ids)
If the projects contain datasets, the datasets will automatically be loaded::
for j = 1 : numel(projects)
datasetsList = projects(j).linkedDatasetList;
for i = 0:datasetsList.size()-1,
d = datasetsList.get(i);
end
end
If the datasets contain images, the images will automatically be loaded::
imageList = projects(1).linkedDatasetList.get(0).linkedImageList;
To avoid loading the whole graph (projects, datasets, images), pass `false` as
a second optional argument. Only datasets will be loaded::
unloadedProjects = getProjects(session, ids, false)
- **Datasets**
The datasets owned by the user currently logged in can be retrieved using the
:source:`getDatasets `
function::
datasets = getDatasets(session)
If the dataset identifiers are known, they can be specified as::
datasets = getDatasets(session, ids)
If the datasets contain images, the images will automatically be loaded::
imageList = datasets(1).linkedImageList;
To avoid loading the images, pass `false` as a second optional argument::
unloadedDatasets = getDatasets(session, ids, false)
- **Images**
All the images owned by the user currently logged in can be retrieved using
the :source:`getImages `
function::
images = getImages(session)
If the image identifiers are known, they can be specified as::
images = getImages(session, ids)
All the images contained in a subset of datasets of known identifiers
``datasetsIds`` can be returned using::
datasetImages = getImages(session, 'dataset', datasetsIds)
All the images contained in all the datasets under a subset of projects of
known identifiers ``projectIds`` can be returned using::
projectImages = getImages(session, 'project', projectIds)
The ``Image``-``Pixels`` model implies you need to use the ``Pixels`` objects
to access valuable data about the ``Image``::
pixels = image.getPrimaryPixels();
sizeZ = pixels.getSizeZ().getValue(); % The number of z-sections.
sizeT = pixels.getSizeT().getValue(); % The number of timepoints.
sizeC = pixels.getSizeC().getValue(); % The number of channels.
sizeX = pixels.getSizeX().getValue(); % The number of pixels along the X-axis.
sizeY = pixels.getSizeY().getValue(); % The number of pixels along the Y-axis.
- **Screens**
The screens owned by the user currently logged in can be retrieved using the
:source:`getScreens `
function::
screens = getScreens(session)
If the screen identifiers are known, they can be specified as::
screens = getScreens(session, ids)
Note that the wells are not loaded. The plate objects can be accessed using::
for j = 1 : numel(screens),
platesList = screens(j).linkedPlateList;
for i = 0:platesList.size()-1,
plate = platesList.get(i);
plateAcquisitionList = plate.copyPlateAcquisitions();
for k = 0:plateAcquisitionList.size()-1,
pa = plateAcquisitionList.get(i);
end
end
- **Plates**
The plates owned by the user currently logged in can be retrieved using the
:source:`getPlates `
function::
plates = getPlates(session)
If the plate identifiers are known, they can be specified as::
plates = getPlates(session, ids)
- **Wells**
Given a plate identifier, the wells can be loaded using the ``findAllByQuery``
method::
wellList = session.getQueryService().findAllByQuery(
['select well from Well as well '...
'left outer join fetch well.plate as pt '...
'left outer join fetch well.wellSamples as ws '...
'left outer join fetch ws.plateAcquisition as pa '...
'left outer join fetch ws.image as img '...
'left outer join fetch img.pixels as pix '...
'left outer join fetch pix.pixelsType as pt '...
'where well.plate.id = ', num2str(plateId)], []);
for j = 0:wellList.size()-1,
well = wellList.get(j);
wellsSampleList = well.copyWellSamples();
well.getId().getValue()
for i = 0:wellsSampleList.size()-1,
ws = wellsSampleList.get(i);
ws.getId().getValue()
pa = ws.getPlateAcquisition();
end
end
Raw data access
---------------
You can retrieve data, plane by plane or retrieve a stack.
- **Plane**
The plane of an input image at coordinates (z, c, t) can be retrieved using
the :source:`getPlane `
function::
plane = getPlane(session, image, z, c, t);
Alternatively, the image identifier can be passed to the function::
plane = getPlane(session, imageID, z, c, t);
- **Tile**
The tile of an input image at coordinates (z, c, t) originated at (x, y) and
of dimensions (w, h) can be retrieved using the
:source:`getTile ` function::
tile = getTile(session, image, z, c, t, x, y, w, h);
Alternatively, the image identifier can be passed to the function::
tile = getTile(session, imageID, z, c, t, x, y, w, h);
- **Stack**
The stack of an input image at coordinates (c, t) can be retrieved using the
:source:`getStack ` function::
stack = getStack(session, image, c, t);
Alternatively, the image identifier can be passed to the function::
stack = getStack(session, imageID, c, t);
- **Hypercube**
This is useful when you need the ``Pixels`` intensity.
::
% Create the store to load the stack. No access via the gateway
store = session.createRawPixelsStore();
% Indicate the pixels set you are working on
store.setPixelsId(pixelsId, false);
% Offset values in each dimension XYZCT
offset = java.util.ArrayList;
offset.add(java.lang.Integer(0));
offset.add(java.lang.Integer(0));
offset.add(java.lang.Integer(0));
offset.add(java.lang.Integer(0));
offset.add(java.lang.Integer(0));
size = java.util.ArrayList;
size.add(java.lang.Integer(sizeX));
size.add(java.lang.Integer(sizeY));
size.add(java.lang.Integer(sizeZ));
size.add(java.lang.Integer(sizeC));
size.add(java.lang.Integer(sizeT));
% Indicate the step in each direction,
% step = 1, will return values at index 0, 1, 2.
% step = 2, values at index 0, 2, 4…
step = java.util.ArrayList;
step.add(java.lang.Integer(1));
step.add(java.lang.Integer(1));
step.add(java.lang.Integer(1));
step.add(java.lang.Integer(1));
step.add(java.lang.Integer(1));
% Retrieve the data
store.getHypercube(offset, size, step);
% Close the store
store.close();
Annotations
-----------
The following table lists all OMERO.matlab functions used to manipulate
annotations from OMERO:
.. list-table::
:header-rows: 1
:widths: 20, 20, 20, 20, 20
- *
* Tag
* File
* Comment
* XML
- * Get by identifier
* :source:`getTagAnnotations `
* :source:`getFileAnnotations `
* :source:`getCommentAnnotations `
* :source:`getXmlAnnotations `
- * Linked to images
* :source:`getImageTagAnnotations `
* :source:`getImageFileAnnotations `
* :source:`getImageCommentAnnotations `
* :source:`getImageXmlAnnotations `
- * Linked to datasets
* :source:`getDatasetTagAnnotations `
* :source:`getDatasetFileAnnotations `
* :source:`getDatasetCommentAnnotations `
* :source:`getDatasetXmlAnnotations `
- * Linked to projects
* :source:`getProjectTagAnnotations `
* :source:`getProjectFileAnnotations `
* :source:`getProjectCommentAnnotations `
* :source:`getProjectXmlAnnotations `
- * Linked to screens
* :source:`getScreenTagAnnotations `
* :source:`getScreenFileAnnotations `
* :source:`getScreenCommentAnnotations `
* :source:`getScreenXmlAnnotations `
- * Linked to plates
* :source:`getPlateTagAnnotations `
* :source:`getPlateFileAnnotations `
* :source:`getPlateCommentAnnotations `
* :source:`getPlateXmlAnnotations `
- * Write
* :source:`writeTagAnnotation `
* :source:`writeFileAnnotation `
* :source:`writeCommentAnnotation `
* :source:`writeXmlAnnotation `
- **Reading annotations**
If the identifier of the annotation of a given type is known, the annotation
can be retrieved from the server using the corresponding function, e.g. for
tags using the :source:`getTagAnnotations `
function::
tagAnnotations = getTagAnnotations(session, tagIds);
Alternatively, the annotations of a given type linked to a given object can be
retrieved using the corresponding function, e.g. to retrieve all tags linked
to images :source:`getImageTagAnnotations `
function::
tagAnnotations = getImageTagAnnotations(session, imageIds);
- **Reading file annotations**
The content of a file annotation can be downloaded to local disk using the
:source:`getFileAnnotationContent `
function. If the file annotation has been retrieved from the server as
``fileAnnotation``, then the content of its ``OriginalFile`` can be downloaded
under ``target_file`` using::
getFileAnnotationContent(session, fileAnnotation, target_file);
Alternatively, if only the identifier of the file annotation ``faId`` is
known::
getFileAnnotationContent(session, faId, target_file);
- **Writing annotations**
New annotations can be created using the corresponding ``write*Annotation``
function (see table above). Existing annotations can be linked to existing
objects on the server using the
:source:`linkAnnotation `
function.
For example, to create a new tag annotation ``tag_name`` and attach it to the
image ``image_id``::
tagAnnotation = writeTagAnnotation(session, tag_name);
link = linkAnnotation(session, tagAnnotation, 'Image', image_id);
To create a file annotations from the content of a ``local_file_path`` and
attach it to the image ``image_id``::
fileAnnotation = writeFileAnnotation(session, local_file_path);
link = linkAnnotation(session, fileAnnotation, 'Image', image_id);
For existing file annotations, it is possible to replace the content of the
original file without having to recreate a new file annotation using the
:source:`updateFileAnnotation ` function.
If the file annotation has been retrieved from the server as
``fileAnnotation``, then the content of its ``OriginalFile`` can be replaced
by the content of ``local_file_path`` using::
updateFileAnnotation(session, fileAnnotation, local_file_path);
Writing data
------------
- **Create a Dataset** and link it to an existing project.
::
dataset = omero.model.DatasetI;
dataset.setName(omero.rtypes.rstring(char('name dataset')));
dataset.setDescription(omero.rtypes.rstring(char('description dataset')));
% Link Dataset and Project
link = omero.model.ProjectDatasetLinkI;
link.setChild(dataset);
link.setParent(omero.model.ProjectI(projectId, false));
session.getUpdateService().saveAndReturnObject(link);
How to use OMERO tables
-----------------------
- **Create a table**. In the following example, a table is created with
2 columns.
::
name = char(java.util.UUID.randomUUID());
columns = javaArray('omero.grid.Column', 2)
columns(1) = omero.grid.LongColumn('Uid', 'testLong', []);
valuesString = javaArray('java.lang.String', 1);
columns(2) = omero.grid.StringColumn('MyStringColumn', '', 64, valuesString);
% Create a new table.
table = session.sharedResources().newTable(1, name);
% Initialize the table
table.initialize(columns);
% Add data to the table.
data = javaArray('omero.grid.Column', 2);
data(1) = omero.grid.LongColumn('Uid', 'test Long', [2]);
valuesString = javaArray('java.lang.String', 1);
valuesString(1) = java.lang.String('add');
data(2) = omero.grid.StringColumn('MyStringColumn', '', 64, valuesString);
table.addData(data);
file = table.getOriginalFile(); % if you need to interact with the table
- **Read the contents of the table**.
::
of = omero.model.OriginalFileI(file.getId(), false);
tablePrx = session.sharedResources().openTable(of);
% Read headers
headers = tablePrx.getHeaders();
for i=1:size(headers, 1),
headers(i).name; % name of the header
% Do something
end
% Depending on the size of table, you may only want to read some blocks.
cols = [0:size(headers, 1)-1]; % The number of columns you wish to read.
rows = [0:tablePrx.getNumberOfRows()-1]; % The number of rows you wish to read.
data = tablePrx.slice(cols, rows); % Read the data.
c = data.columns;
for i=1:size(c),
column = c(i);
% Do something
end
tablePrx.close(); % Important to close when done.
ROIs
----
To learn about the model see :model_doc:`developers/roi.html`. Note that
annotation can be linked to ROI.
- **Creating ROI**
This example creates a ROI with two shapes, a rectangle and an ellipse, and
attaches it to an image::
% First create a rectangular shape.
rectangle = createRectangle(0, 0, 10, 20);
% Indicate on which plane to attach the shape
setShapeCoordinates(rectangle, 0, 0, 0);
% First create an ellipse shape.
ellipse = createEllipse(0, 0, 10, 20);
% Indicate on which plane to attach the shape
setShapeCoordinates(ellipse, 0, 0, 0);
% Create the roi.
roi = omero.model.RoiI;
% Attach the shapes to the roi, several shapes can be added.
roi.addShape(rectangle);
roi.addShape(ellipse);
% Link the roi and the image
roi.setImage(omero.model.ImageI(imageId, false));
% Save
iUpdate = session.getUpdateService();
roi = iUpdate.saveAndReturnObject(roi);
% Check that the shape has been added.
numShapes = roi.sizeOfShapes;
for ns = 1:numShapes
shape = roi.getShape(ns-1);
end
.. seealso::
:sourcedir:`ROI utility functions `
OMERO.matlab functions for creating and managing Shape and ROI
objects.
- **Retrieving ROIs linked to an image**
::
service = session.getRoiService();
roiResult = service.findByImage(imageId, []);
rois = roiResult.rois;
n = rois.size;
shapeType = '';
for thisROI = 1:n
roi = rois.get(thisROI-1);
numShapes = roi.sizeOfShapes;
for ns = 1:numShapes
shape = roi.getShape(ns-1);
if (isa(shape, 'omero.model.Rect'))
rectangle = shape;
rectangle.getX().getValue()
elseif (isa(shape, 'omero.model.Ellipse'))
ellipse = shape;
ellipse.getCx().getValue()
elseif (isa(shape, 'omero.model.Point'))
point = shape;
point.getX().getValue();
elseif (isa(shape, 'omero.model.Line'))
line = shape;
line.getX1().getValue();
end
end
end
- **Removing a shape from ROI**
::
// Retrieve the roi linked to an image
service = session.getRoiService();
roiResult = service.findByImage(imageId, []);
n = rois.size;
for thisROI = 1:n
roi = rois.get(thisROI-1);
numShapes = roi.sizeOfShapes;
for ns = 1:numShapes
shape = roi.getShape(ns-1);
% Remove the shape
roi.removeShape(shape);
end
% Update the roi.
roi = iUpdate.saveAndReturnObject(roi);
end
Deleting data
-------------
It is possible to delete projects, datasets, images, ROIs… and
objects linked to them depending on the specified options (see
:doc:`/developers/Modules/Delete`). For example, images of known identifiers
can be deleted from the server using the
:source:`deleteImages `
function::
deleteImages(session, imageIds);
.. seealso::
:source:`deleteProjects `, :source:`deleteDatasets `, :source:`deleteScreens `, :source:`deletePlates `
Utility functions to delete objects
Rendering images
-----------------
The :source:`RenderImages.m ` example
script shows how to initialize the rendering engine and render an image.
Creating Image
--------------
The :source:`CreateImage.m ` example
script shows how to create an image in OMERO. A similar approach can be
applied when uploading an image. To upload individual planes onto the server,
the data must be converted into a byte (int8) array first.