//
// OmeroReader.java
//
/*
OME database I/O package for communicating with OME and OMERO servers.
Copyright (C) 2005-@year@ Melissa Linkert, Curtis Rueden and Philip Huettl.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package loci.ome.io;
import Glacier2.CannotCreateSessionException;
import Glacier2.PermissionDeniedException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import loci.common.DateTools;
import loci.common.RandomAccessInputStream;
import loci.formats.FormatException;
import loci.formats.FormatReader;
import loci.formats.FormatTools;
import loci.formats.MetadataTools;
import loci.formats.meta.MetadataStore;
import loci.formats.tools.ImageInfo;
import ome.xml.model.primitives.PositiveFloat;
import ome.xml.model.primitives.PositiveInteger;
import omero.RDouble;
import omero.RInt;
import omero.RString;
import omero.RTime;
import omero.ServerError;
import omero.api.GatewayPrx;
import omero.api.IAdminPrx;
import omero.api.IQueryPrx;
import omero.api.RawPixelsStorePrx;
import omero.api.ServiceFactoryPrx;
import omero.model.Channel;
import omero.model.Experimenter;
import omero.model.ExperimenterGroup;
import omero.model.ExperimenterGroupI;
import omero.model.Image;
import omero.model.IObject;
import omero.model.LogicalChannel;
import omero.model.Pixels;
import omero.sys.EventContext;
import omero.sys.ParametersI;
/**
* Implementation of {@link loci.formats.IFormatReader}
* for use in export from an OMERO Beta 4.2.x database.
*
* <dl><dt><b>Source code:</b></dt>
* <dd><a href="http://trac.openmicroscopy.org.uk/ome/browser/bioformats.git/components/ome-io/src/loci/ome/io/OmeroReader.java">Trac</a>,
* <a href="http://git.openmicroscopy.org/?p=bioformats.git;a=blob;f=components/ome-io/src/loci/ome/io/OmeroReader.java;hb=HEAD">Gitweb</a></dd></dl>
*/
public class OmeroReader extends FormatReader {
// -- Constants --
public static final int DEFAULT_PORT = 4064;
// -- Fields --
private String server;
private String username;
private String password;
private int thePort = DEFAULT_PORT;
private String sessionID;
private String group;
private Long groupID = null;
private boolean encrypted = true;
private omero.client client;
private RawPixelsStorePrx store;
private Image img;
private Pixels pix;
// -- Constructors --
public OmeroReader() {
super("OMERO", "*");
}
// -- OmeroReader methods --
public void setServer(String server) {
this.server = server;
}
public void setPort(int port) {
thePort = port;
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
public void setSessionID(String sessionID) {
this.sessionID = sessionID;
}
public void setEncrypted(boolean encrypted) {
this.encrypted = encrypted;
}
public void setGroupName(String group) {
this.group = group;
}
public void setGroupID(Long groupID) {
this.groupID = groupID;
}
// -- IFormatReader methods --
@Override
public boolean isThisType(String name, boolean open) {
return name.startsWith("omero:");
}
@Override
public byte[] openBytes(int no, byte[] buf, int x, int y, int w, int h)
throws FormatException, IOException
{
FormatTools.assertId(currentId, true, 1);
FormatTools.checkPlaneNumber(this, no);
FormatTools.checkBufferSize(this, buf.length, w, h);
final int[] zct = FormatTools.getZCTCoords(this, no);
final byte[] plane;
try {
plane = store.getPlane(zct[0], zct[1], zct[2]);
}
catch (ServerError e) {
throw new FormatException(e);
}
RandomAccessInputStream s = new RandomAccessInputStream(plane);
readPlane(s, x, y, w, h, buf);
s.close();
return buf;
}
@Override
public void close(boolean fileOnly) throws IOException {
super.close(fileOnly);
if (!fileOnly && client != null) {
client.closeSession();
}
}
@Override
protected void initFile(String id) throws FormatException, IOException {
LOGGER.debug("OmeroReader.initFile({})", id);
super.initFile(id);
if (!id.startsWith("omero:")) {
throw new IllegalArgumentException("Not an OMERO id: " + id);
}
// parse credentials from id string
LOGGER.info("Parsing credentials");
String address = server, user = username, pass = password;
int port = thePort;
long iid = -1;
final String[] tokens = id.substring(6).split("\n");
for (String token : tokens) {
final int equals = token.indexOf("=");
if (equals < 0) continue;
final String key = token.substring(0, equals);
final String val = token.substring(equals + 1);
if (key.equals("server")) address = val;
else if (key.equals("user")) user = val;
else if (key.equals("pass")) pass = val;
else if (key.equals("port")) {
try {
port = Integer.parseInt(val);
}
catch (NumberFormatException exc) { }
}
else if (key.equals("session")) {
sessionID = val;
}
else if (key.equals("groupName")) {
group = val;
}
else if (key.equals("groupID")) {
groupID = new Long(val);
}
else if (key.equals("iid")) {
try {
iid = Long.parseLong(val);
}
catch (NumberFormatException exc) { }
}
}
if (address == null) {
throw new FormatException("Invalid server address");
}
if (user == null && sessionID == null) {
throw new FormatException("Invalid username");
}
if (pass == null && sessionID == null) {
throw new FormatException("Invalid password");
}
if (iid < 0) {
throw new FormatException("Invalid image ID");
}
try {
// authenticate with OMERO server
LOGGER.info("Logging in");
client = new omero.client(address, port);
ServiceFactoryPrx serviceFactory = null;
if (user != null && pass != null) {
serviceFactory = client.createSession(user, pass);
}
else {
serviceFactory = client.createSession(sessionID, sessionID);
}
if (!encrypted) {
client = client.createClient(false);
serviceFactory = client.getSession();
}
if (group != null || groupID != null) {
IAdminPrx iAdmin = serviceFactory.getAdminService();
IQueryPrx iQuery = serviceFactory.getQueryService();
EventContext eventContext = iAdmin.getEventContext();
ExperimenterGroup defaultGroup =
iAdmin.getDefaultGroup(eventContext.userId);
if (!defaultGroup.getName().getValue().equals(group) &&
!new Long(defaultGroup.getId().getValue()).equals(groupID))
{
Experimenter exp = iAdmin.getExperimenter(eventContext.userId);
ParametersI p = new ParametersI();
p.addId(eventContext.userId);
List<IObject> groupList = iQuery.findAllByQuery(
"select distinct g from ExperimenterGroup as g " +
"join fetch g.groupExperimenterMap as map " +
"join fetch map.parent e " +
"left outer join fetch map.child u " +
"left outer join fetch u.groupExperimenterMap m2 " +
"left outer join fetch m2.parent p " +
"where g.id in " +
" (select m.parent from GroupExperimenterMap m " +
" where m.child.id = :id )", p);
Iterator<IObject> i = groupList.iterator();
ExperimenterGroup g = null;
boolean in = false;
while (i.hasNext()) {
g = (ExperimenterGroup) i.next();
if (g.getName().getValue().equals(group) ||
new Long(g.getId().getValue()).equals(groupID))
{
in = true;
groupID = g.getId().getValue();
break;
}
}
if (in) {
iAdmin.setDefaultGroup(exp, iAdmin.getGroup(groupID));
serviceFactory.setSecurityContext(
new ExperimenterGroupI(groupID, false));
}
}
}
// get raw pixels store and pixels
store = serviceFactory.createRawPixelsStore();
final GatewayPrx gateway = serviceFactory.createGateway();
img = gateway.getImage(iid);
if (img == null) {
throw new FormatException("Could not find Image with ID=" + iid +
" in group '" + group + "'.");
}
long pixelsId = img.getPixels(0).getId().getValue();
store.setPixelsId(pixelsId, false);
pix = gateway.getPixels(pixelsId);
final int sizeX = pix.getSizeX().getValue();
final int sizeY = pix.getSizeY().getValue();
final int sizeZ = pix.getSizeZ().getValue();
final int sizeC = pix.getSizeC().getValue();
final int sizeT = pix.getSizeT().getValue();
final String pixelType = pix.getPixelsType().getValue().getValue();
// populate metadata
LOGGER.info("Populating metadata");
core[0].sizeX = sizeX;
core[0].sizeY = sizeY;
core[0].sizeZ = sizeZ;
core[0].sizeC = sizeC;
core[0].sizeT = sizeT;
core[0].rgb = false;
core[0].littleEndian = false;
core[0].dimensionOrder = "XYZCT";
core[0].imageCount = sizeZ * sizeC * sizeT;
core[0].pixelType = FormatTools.pixelTypeFromString(pixelType);
RDouble x = pix.getPhysicalSizeX();
Double px = x == null ? null : x.getValue();
RDouble y = pix.getPhysicalSizeY();
Double py = y == null ? null : y.getValue();
RDouble z = pix.getPhysicalSizeZ();
Double pz = z == null ? null : z.getValue();
RDouble t = pix.getTimeIncrement();
Double time = t == null ? null : t.getValue();
RString imageName = img.getName();
String name = imageName == null ? null : imageName.getValue();
if (name != null) {
currentId = name;
}
else {
currentId = "Image ID " + iid;
}
RString imgDescription = img.getDescription();
String description =
imgDescription == null ? null : imgDescription.getValue();
RTime date = img.getAcquisitionDate();
MetadataStore store = getMetadataStore();
MetadataTools.populatePixels(store, this);
store.setImageName(name, 0);
store.setImageDescription(description, 0);
if (date != null) {
store.setImageAcquiredDate(DateTools.convertDate(date.getValue(),
(int) DateTools.UNIX_EPOCH), 0);
}
if (px != null && px > 0) {
store.setPixelsPhysicalSizeX(new PositiveFloat(px), 0);
}
if (py != null && py > 0) {
store.setPixelsPhysicalSizeY(new PositiveFloat(py), 0);
}
if (pz != null && pz > 0) {
store.setPixelsPhysicalSizeZ(new PositiveFloat(pz), 0);
}
if (time != null) {
store.setPixelsTimeIncrement(time, 0);
}
List<Channel> channels = pix.copyChannels();
for (int c=0; c<channels.size(); c++) {
LogicalChannel channel = channels.get(c).getLogicalChannel();
RInt emWave = channel.getEmissionWave();
RInt exWave = channel.getExcitationWave();
RDouble pinholeSize = channel.getPinHoleSize();
RString cname = channel.getName();
Integer emission = emWave == null ? null : emWave.getValue();
Integer excitation = exWave == null ? null : exWave.getValue();
String channelName = cname == null ? null : cname.getValue();
Double pinhole = pinholeSize == null ? null : pinholeSize.getValue();
if (channelName != null) {
store.setChannelName(channelName, 0, c);
}
if (pinhole != null) {
store.setChannelPinholeSize(pinhole, 0, c);
}
if (emission != null && emission > 0) {
store.setChannelEmissionWavelength(
new PositiveInteger(emission), 0, c);
}
if (excitation != null && excitation > 0) {
store.setChannelExcitationWavelength(
new PositiveInteger(excitation), 0, c);
}
}
}
catch (CannotCreateSessionException e) {
throw new FormatException(e);
}
catch (PermissionDeniedException e) {
throw new FormatException(e);
}
catch (ServerError e) {
throw new FormatException(e);
}
}
/** A simple command line tool for downloading images from OMERO. */
public static void main(String[] args) throws Exception {
// parse OMERO credentials
BufferedReader con = new BufferedReader(new InputStreamReader(System.in));
System.out.print("Server? ");
final String server = con.readLine();
System.out.printf("Port [%d]? ", DEFAULT_PORT);
final String portString = con.readLine();
final int port = portString.equals("") ? DEFAULT_PORT :
Integer.parseInt(portString);
System.out.print("Username? ");
final String user = con.readLine();
System.out.print("Password? ");
final String pass = new String(con.readLine());
System.out.print("Group? ");
final String group = con.readLine();
System.out.print("Image ID? ");
final int imageId = Integer.parseInt(con.readLine());
System.out.print("\n\n");
// construct the OMERO reader
final OmeroReader omeroReader = new OmeroReader();
omeroReader.setUsername(user);
omeroReader.setPassword(pass);
omeroReader.setServer(server);
omeroReader.setPort(port);
omeroReader.setGroupName(group);
final String id = "omero:iid=" + imageId;
try {
omeroReader.setId(id);
}
catch (Exception e) {
omeroReader.close();
throw e;
}
omeroReader.close();
// delegate the heavy lifting to Bio-Formats ImageInfo utility
final ImageInfo imageInfo = new ImageInfo();
imageInfo.setReader(omeroReader); // override default image reader
String[] readArgs = new String[args.length + 1];
System.arraycopy(args, 0, readArgs, 0, args.length);
readArgs[args.length] = id;
if (!imageInfo.testRead(readArgs)) {
omeroReader.close();
System.exit(1);
}
}
}