-
Notifications
You must be signed in to change notification settings - Fork 101
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Metadata plugin pixelsize #5696
Conversation
for pixel in pixels: | ||
if args.x: | ||
pixSize = pixel.getPhysicalSizeX() | ||
if not pixSize: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to avoid copy/paste of similar code, you should introduce a method to the set the physical size
elif md.get_type() == "Image": | ||
q = """SELECT pix FROM Pixels pix WHERE pix.image.id=:id""" | ||
else: | ||
raise Exception("Not implemented for type %s" % md.get_type()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is fine but just to mention that another option is http://downloads.openmicroscopy.org/latest/omero5.4/api/slice2html/omero/cmd/FindChildren.html#FindChildren to find their IDs with typesOfChildren = ['Pixels']
and stopBefore = ['Roi']
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we have a python example somewhere which uses FindChildren
? Can't get my head around how to use that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
from omero.callbacks import CmdCallbackI
from omero.cmd import FindChildren
from omero.gateway import BlitzGateway
conn = BlitzGateway(stuff) # I suggest user-2 on eel
conn.connect()
req = FindChildren(targetObjects={'Project': [1]},
typesOfChildren=['Pixels'], stopBefore=['Roi'])
prx = conn.c.sf.submit(req)
print CmdCallbackI(conn.c, prx).loop(500, 500)
conn._closeSession()
and see many IDs of Pixels that are in Project 1.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! That works. But I think I leave the the hql query for now, because it loads the Pixel objects directly. Otherwise I'd have to get the ids first with FindChildren
and then load the Pixel objects from the id list.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Btw, that example would be nice to have on https://docs.openmicroscopy.org/omero/5.4.4/developers/Python.html :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Leaving someone else to record or migrate the Python example.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if not pixSize: | ||
pixSize = omero.model.LengthI(args.z, units[args.unit]) | ||
pixel.setPhysicalSizeZ(pixSize) | ||
else: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are these else
worthwhile or simpler just to always do the first clause? (Can instantiate the LengthI
outside the loop so the pixels share it?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Always create a new LengthI
object? Is the old one automatically removed from the database then?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, definitely. They are structs
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They don't exist in the database as first-class objects.
pixSize.setValue(args.z) | ||
pixSize.setUnit(units[args.unit]) | ||
|
||
client.getSession().getUpdateService().saveAndReturnObject(pixel) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could instead save many in bulk with saveArray
outside the loop.
|
||
units = { | ||
'nm': UnitsLength.NANOMETER, | ||
'um': UnitsLength.MICROMETER, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ought we also allow 'μm'?
Not sure |
md = self._load(args) | ||
client, conn = self._clientconn(args) | ||
|
||
units = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This lookup can be achieved via:
In [34]: omero.model.LengthI.SYMBOLS.keys()[omero.model.LengthI.SYMBOLS.values().index("mm")]
Out[34]: 'MILLIMETER'
so that no hard-coding is needed. You'd have to special case um
, though, regardless and unicode is going to be challenging from the terminal.
pixelsize.add_argument( | ||
"--z", type=float, default=None, help="Physical pixel size Z") | ||
pixelsize.add_argument( | ||
"--unit", default="um", help="Unit (e.g. nm, um, mm, ...) " |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the sizes need different units, the suggestion would be to call the plugin multiple times?
def pixelsize(self, args): | ||
"Set physical pixel size" | ||
md = self._load(args) | ||
client, conn = self._clientconn(args) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be worth doing this after validating the inputs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few minor comments added. In general, working with units and the related enums is tricky at best. Just trying to write a snippet for this PR, I already noticed 2-3 helper methods that should be created. But that's for down the road.
Long-term I think we should support 1 or 2 forms of all enum values for a given unit:
- MILLIMETER
- NANOMETER
- etc
and/or
- mm
- nm
- etc.
As long as we're happy to formalize that later and continue to support any extra helpers introduced in this PR (like um
) then no objections to not having complete support here.
If there are any concerns over the "one-unit-fits-all" issue, a next step after this PR might be to use the (yet another) helper suggested in https://trello.com/c/Z2NAGjBQ/379-cli-support-enums-for-objpy such that:
--x=1mm
would be a valid argument.
I'd prefer only using the enum names like |
53df243
to
39407c2
Compare
I'll leave x, y, z parameter as value only parameter for now. A unit can be specified with |
This has the same issue as addressed in ome/omero-cli-render#6 in that a non-owner thinks that the change has taken place but silently fails:
|
That means I'd need to set the context explicitly |
Exactly. |
params = omero.sys.ParametersI() | ||
params.addId(md.get_id()) | ||
pixels = client.getSession().getQueryService()\ | ||
pixels = client.getSession().getQueryService(ctx)\ | ||
.findAllByQuery(q, params) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the ctx
needs to be passed to the findAllByQuery
. On eel I'm getting the same behavior of no change. Likely if not pixels:
should also call self.ctx.die
or at least self.ctx.err
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Argh, of course, thanks @joshmoore .
.findAllByQuery(q, params) | ||
|
||
for pixel in pixels: | ||
if args.x: | ||
pixel.setPhysicalSizeX(omero.model.LengthI(args.x, unit)) | ||
pixel.setPhysicalSizeX(omero.model.LengthI(args.x, unit), ctx) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These don't hurt, but also have no effect.
Doh. Unfortunately, this leads to:
i.e. ctx needed on
|
Bit lost now... When I pass the
What is that supposed to mean? |
The server is failing to figure how what group you intended to save to, perhaps as a result of |
Ha, yes, |
@@ -622,7 +621,9 @@ def pixelsize(self, args): | |||
if args.z: | |||
pixel.setPhysicalSizeZ(omero.model.LengthI(args.z, unit)) | |||
|
|||
client.getSession().getUpdateService(ctx).saveCollection(pixels) | |||
groupId = pixels[0].getDetails().getGroup().getId().getValue() | |||
ctx = {'omero.group': str(groupId)} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
conn.SERVICE_OPTS.setOmeroGroup(str(groupId)) is another option
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For some reason that doesn't work. If I set conn.SERVICE_OPTS.setOmeroGroup(str(groupId))
instead of using the ctx
, I'll get a ome.conditions.SecurityViolation
when running the command as non-owner of the image.
Same further up: pixels = conn.getQueryService().findAllByQuery(q, params, ctx)
works, but when setting conn.SERVICE_OPTS
instead of using the ctx
, it doesn't.
Merging for 5.4.6-rc2. Considering this is still a DEV plugin, we might consider a round of refactoring before going full production. |
What this PR does
Adds a
pixelsize
command to the metadata plugin, which allows setting a custom physical pixel size for an Image (or whole Dataset, Project, etc.)Testing this PR
Set a custom pixel size:
./omero metadata pixelsize --x 5 --y 6 --z 7 --unit nanometer Dataset:123
Doesn't output anything, so use Insight or Web to check if it was successful.
Related reading
IDR/idr0042-nirschl-wsideeplearning#1
/cc @sbesson