Best way imageJ to open an ImagePlus from OMERO using Bioformats

@Joost_Willemse1 Yes, thank you, you are completely right about the default group. Our scripts, such as https://github.com/ome/training-scripts/blob/master/practical/groovy/open_image_after_download.groovy will not open an image from non-default group. We will follow-up on this and deliver a better answer soon, with some more concrete suggestion about how to manage the group context.

All the best
Petr

OME Team

Hi @Joost_Willemse1 ,

I’m not an expert, but this how I’ve handled group changes in Omero. This assumes you’ve logged in created the gateway.

Once you have the security ctx and in the imageID I open it with browse.getImage(ctx, image_id).

Cheers,

Chris

user=gateway.getLoggedInUser()				

	
# create a browse Facility service 
from omero.gateway.facility import BrowseFacility
browse = gateway.getFacility(BrowseFacility)

# get the list of groups
groups = user.getGroups()

# some boring code here to select one of the groups
# .....  snip ..
group = groups[ iselected ]

# create a security context for this group (changes from default)
from omero.gateway import SecurityContext
ctx = SecurityContext( group.getId() )

# get a list of projects and screens
# I had to treat the default group different, not sure why exactly
params = ParametersI()		
if( groups[igroup].getName()=='default'):
	projects=browse.getHierarchy(ctx, ProjectData, user.getId())
	screens =browse.getHierarchy(ctx, ScreenData, user.getId())
else:
	projects=browse.getHierarchy(ctx,ProjectData,[],params)		
	screens =browse.getHierarchy(ctx,ScreenData, [],params)	

# boring code to select a project
# ... snip ...
project = projects[iproject]
datasets = projects.getDatasets()

# boring code to select a dataset
# .. snip ...
dataset = datasets[idataset]
images = browse.getImagesForDatasets(ctx,[Long(datasets[i_data].getId())]) 

Nevermind, issue still not solved, though i thought so for a sec

Hi @Joost_Willemse1,

I’ve adapted one of the solution from higher up in the thread. I’m sure this the wrong way to go about it as

  • this is a very manual process that belongs in a proper library
  • it is in hacked together Jython
  • it doesn’t get the calibration, LUTs or image metadata yet
  • it is very much old-school imageJ,1 rather than the new hotness of SciJava, imglib, IJ2, Abstract Service Provider etc

But it is best solution I’ve found so far. My wish list is to be able to:

  • Limit the range of X,Y,T,C,Z, resolution pyramid or fields of view. We have some 50GB image files so any approach that downloads the raw image file is out of the question
  • Doesn’t open the image. I’d rather just get the ImagePlus object or whatever it’s called in IJ2.
  • Read/write metadata in OMERO like key-values pairs and tables
  • Access all the groups the user is a member of.

Hope it helps. Let me know if you’d me to put it up on GitHub.

Cheers,

Chris


def open_omero_image(gateway, ctx, image_id ):
	from omero.gateway.facility import BrowseFacility
	browse = gateway.getFacility(BrowseFacility)
    
	image = browse.getImage(ctx, image_id)	
	pixels = image.getDefaultPixels()
	size_z = pixels.getSizeZ()
	size_t = pixels.getSizeT()
	size_c = pixels.getSizeC()
	size_x = pixels.getSizeX()
	size_y = pixels.getSizeY()

	
	pixtype = pixels.getPixelType()
	from loci.formats import FormatTools
	pixels_type = FormatTools.pixelTypeFromString(pixtype)
	bpp = FormatTools.getBytesPerPixel(pixels_type)

	is_signed = FormatTools.isSigned(pixels_type)
	is_float = FormatTools.isFloatingPoint(pixels_type)
	is_little = False
	interleave = False

	# setup the pixelStore
	store = gateway.getPixelsStore(ctx)
	pixels_id = pixels.getId()
	store.setPixelsId(pixels_id, False)

	from ij import IJ
	imp   = IJ.createHyperStack("tmp",size_x,size_y,size_c,size_z,size_t,bpp*8)
	stack = imp.getImageStack()
	

	from loci.formats import ImageTools
	from loci.common import DataTools
	from ij.process import ByteProcessor, ShortProcessor, FloatProcessor
	from java.lang import Short
	
	for t in range(size_t):
		for z in range(size_z):
			for c in range(size_c):
				
				n = imp.getStackIndex(c+1,z+1,t+1)
				print(t,z,c,n)
				plane = store.getPlane(z, c, t)
				ImageTools.splitChannels(plane, 0, 1, bpp, False, interleave)
				pixels = DataTools.makeDataArray(plane, bpp, is_float, is_little)	
				
				ip = stack.getProcessor(n)
				ip.setPixels(pixels)
				stack.setProcessor(ip,n)
				
	imp.setStack(stack)
	store.close()

	imp.setOpenAsHyperStack(True)
	from ij import IJ
	imp.setDisplayMode(IJ.COMPOSITE)

	return imp

Ok, after some more fiddling i really solved it now.

The trick is to connect via a gateway,
read out in which group the image is located,
Then reconnect with changed credentials (new groupId)
and then the images load like you want to

public void getDatasetImages() {
        Gateway gateway = null;
        try {
			LoginCredentials credentials = new LoginCredentials(Username,Password,HOST,PORT);
        	SimpleLogger simpleLogger = new SimpleLogger();
       		gateway = new Gateway(simpleLogger);
        	gateway.connect(credentials);
        	ExperimenterData ed = gateway.getLoggedInUser();
        	List<GroupData> grda= ed.getGroups();
        	
        	//This is the way to get via browsefacility, can be opened with 
        	 //* 
        	BrowseFacility browser = gateway.getFacility(BrowseFacility.class);
        	Iterator<GroupData> gidit=grda.iterator();
        	int counter =0;
        	ImageData id =null;
        	IJ.log("ngroups "+grda.size()); 
        	while (gidit.hasNext() && id==null){
	        	try {
	        		SecurityContext ctx = new SecurityContext(grda.get(counter).getGroupId());
	        		id = browser.getImage(ctx, imageId);
	        		credentials.setGroupID(ctx.getGroupID());
	        		gateway.connect(credentials);
	        	} catch (Exception e){
	        		//IJ.showMessage("Image not found in group " +grda.get(counter).getGroupId());
	        	}
	        	counter++;
        	}
        	if (id==null) {
        		IJ.showMessage("Image not found");
        		return;
        	}
        	ImageJ ij = new ImageJ();
        	Context context = ij.getContext();
        	OMEROService dos = context.service(OMEROService.class);
        	OMEROLocation ol = new OMEROLocation(HOST,PORT,Username,Password);
        	OMEROSession os = dos.createSession(ol);	
			client cl = os.getClient();
            Dataset d = dos.downloadImage(cl,imageId);
            ImgPlus implu=d.getImgPlus();
           	ImagePlus imp = ImageJFunctions.wrap(implu,"My desired imageplus");
           	imp.show();
        } catch (Exception e) {
        	IJ.log(e.getMessage());
        	StackTraceElement[] t = e.getStackTrace();
        	for (int i=0;i<t.length;i++){
        		IJ.log(t[i].toString());
        	}
            IJ.showMessage("An error occurred while loading the image.");
        } finally {
            if (gateway != null) gateway.disconnect();
        }
    }
1 Like

Hi Joost

As mentioned (and tested) you can change the context using the OMERO java gateway
You cannot do that using imagej-omero.
Glad you managed to find a workaround. This is not ideal but at least you could move forward.

Cheers
Jmarie

Hi @ctrueden,

OMERO through the update site

When I enable the OMERO 5.4 site from the update section I can see the libraries.

But it breaks the connection to OMERO. Attempts to connect result in the following:

    reason = "IceSSL: handshake error"
	at IceInternal.AsyncResultI.__wait(AsyncResultI.java:276)
	at Ice.ObjectPrxHelperBase.end_ice_isA(ObjectPrxHelperBase.java:310)
	at Ice.ObjectPrxHelperBase.ice_isA(ObjectPrxHelperBase.java:92)
	at Ice.ObjectPrxHelperBase.ice_isA(ObjectPrxHelperBase.java:69)
	at Ice.ObjectPrxHelperBase.checkedCastImpl(ObjectPrxHelperBase.java:2810)
	at Ice.ObjectPrxHelperBase.checkedCastImpl(ObjectPrxHelperBase.java:2770)
	at Glacier2.RouterPrxHelper.checkedCast(RouterPrxHelper.java:1787)
	at omero.client.getRouter(client.java:802)
	at omero.client.createSession(client.java:723)
	at net.imagej.omero.DefaultOMEROSession.<init>(DefaultOMEROSession.java:114)
	at net.imagej.omero.DefaultOMEROSession.<init>(DefaultOMEROSession.java:85)
	at net.imagej.omero.DefaultOMEROService.createSession(DefaultOMEROService.java:890)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Del

This happens for the IJ2 approach and for other approaches listed above (which I’ll call IJ1). The error for the IJ1 approach is similar:

    reason = "IceSSL: handshake error"
	at IceInternal.AsyncResultI.__wait(AsyncResultI.java:276)
	at Ice.ObjectPrxHelperBase.end_ice_isA(ObjectPrxHelperBase.java:310)
	at Ice.ObjectPrxHelperBase.ice_isA(ObjectPrxHelperBase.java:92)
	at Ice.ObjectPrxHelperBase.ice_isA(ObjectPrxHelperBase.java:69)
	at Ice.ObjectPrxHelperBase.checkedCastImpl(ObjectPrxHelperBase.java:2810)
	at Ice.ObjectPrxHelperBase.checkedCastImpl(ObjectPrxHelperBase.java:2770)
	at Glacier2.RouterPrxHelper.checkedCast(RouterPrxHelper.java:1787)
	at omero.client.getRouter(client.java:802)
	at omero.client.createSession(client.java:723)
	at omero.gateway.Gateway.createSession(Gateway.java:1054)
	at omero.gateway.Gateway.connect(Gateway.java:259)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)

I have the omero-ij plugin manually installed from the download section on the OME page - our OMERO version is 5.4.9-ice36-b101. So I tried all the combinations

OMERO 5.4 update OMERO manual IJ2 method IJ1 method
:black_circle: :x: IceSSL :x: IceSSL
:black_circle: :x: no Service :white_check_mark:
:black_circle: :black_circle: :x: IceSSL :x: IceSSL
  • Does the OMERO 5.4 instal through update site clash with a manually installed OMERO plugin?

Script parameters

Beyond simple scripts, I’ve not had much success with script parameters. When I refactor and call functions from modules / libraries the script parameter magic doesn’t work. Is this right?

Anyway, my I’d like the option to explicitly do what the script parameter magic is doing. Is there a place the code can see what the script parameters are doing?

Cheers,

Chris

Hi Chris

For OMERO 5.4 it should not clash.
We certainly had to make changes in newer version of OMERO (5.5. and 5.6) to work.

Have you tried to modify the system property jdk.tls.disabledAlgorithms
and remove the anon from the list
something like that

property = "jdk.tls.disabledAlgorithms"
value = Security.getProperty(property)
if (!(value == null || value.trim().isEmpty())) {
	algorithms = new ArrayList();
	isChanged = false;
	for (algorithm in value.split(",")) {
		algorithm = algorithm.trim();
		if (algorithm.isEmpty()) {
					/* ignore */
		} else if ("anon".equals(algorithm.toLowerCase())) {
			isChanged = true;
		} else {
			algorithms.add(algorithm);
		}
	}
	if (isChanged) {
		needsComma = false;
		newValue = new StringBuilder();
		for (algorithm in algorithms) {
			if (needsComma) {
				newValue.append(", ");
			} else {
				needsComma = true;
			}
			newValue.append(algorithm);
		}
		Security.setProperty(property, newValue.toString());
	}
}```
and see if it solved the issue

Cheers

Jmarie
1 Like

If you have script functions you want to use in library fashion, make the functions accept the needed services as arguments. And then pass them from your top-level scripts. And the top-level scripts can use script parameters to receive the from the framework.

Here is a hack to obtain the SciJava Context object currently in use, and then ask for the associated OMEROService from there:

Context ctx = (Context) IJ.runPlugIn("org.scijava.Context", "");
OMEROService omeroService = ctx.service(OMEROService.class);

This will work when executing code from within ImageJ/Fiji, when imagej-legacy is on the classpath.

This code will not work if:

  • You run from outside ImageJ—e.g. using the jython command line tool.
  • You run ImageJ without image-legacy on the classpath.
  • You instantiate a net.imagej.ImageJ gateway without including the LegacyService.
  • You instantiate multiple SciJava contexts.

But in the common case of running Fiji as a desktop application, or from the CLI, it should do the trick. But in that case, script parameters will also work from the top-level script. So the hack is not really necessary…

Thank you for posting that! Very helpful to understand what you tried.

I believe it is OK, based on a recent thread here:

However, I am not sure what, if anything, the OME team has uploaded to those OMERO-5.x update sites, as of this writing. Their primary purpose was to ship the ImageJ-OMERO extension, but then in the thread linked above, we were discussing also shipping the OMERO.insight-ij plugin as well. It would be awesome if the OME team could provide more details by expanding the stub page at:

We have not updated anything yet to the OMERO 5.x
After @ctrueden created it, we encountered an ssl issue (fixed) and focused on 5.6 upgrade.
We should now be able to push a version of OMERO.insight-ij plugin compatible with OMERO 5.5 and 5.6 server
The ImageJ-OMERO extension will also have to be updated.
I will hopefully have time next week to look into that

Cheers
Jmarie

A post was split to a new topic: Updating ImageJ-OMERO for OMERO 5.5 and 5.6

A post was split to a new topic: Loading images with imagej-omero

A post was split to a new topic: How to get all ImageIDs for a dataset via imagej-omero

For those awaiting the new ImageJ-OMERO: you can follow this issue:

I’ll be out for the next four weeks, but will try to complete it upon my return in October.

2 Likes

A post was split to a new topic: Imagej-omero isn’t working with scifio 0.41.0