Skip to content
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

imgData JSON with no stateful services #536

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion omeroweb/webclient/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@

from omeroweb.version import omeroweb_buildyear as build_year
from omeroweb.version import omeroweb_version as omero_version
from omeroweb.webgateway.util import get_rendering_def

import omero
import omero.scripts
Expand Down Expand Up @@ -1803,7 +1804,8 @@ def load_metadata_preview(request, c_type, c_id, conn=None, share_id=None, **kwa

allRdefs = manager.image.getAllRenderingDefs()
rdefs = {}
rdefId = manager.image.getRenderingDefId()
rdef = get_rendering_def(manager.image)
rdefId = rdef["id"] if rdef is not None else None
# remove duplicates per user
for r in allRdefs:
ownerId = r["owner"]["id"]
Expand Down
135 changes: 125 additions & 10 deletions omeroweb/webgateway/marshal.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,17 @@
import logging
import traceback

from omero.model.enums import PixelsTypeint8, PixelsTypeuint8, PixelsTypeint16
from omero.model.enums import PixelsTypeuint16, PixelsTypeint32
from omero.model.enums import PixelsTypeuint32, PixelsTypefloat
from omero.model.enums import PixelsTypedouble

from omero.gateway import ChannelWrapper
from omero.rtypes import unwrap
from omero_marshal import get_encoder

from .util import get_rendering_def

logger = logging.getLogger(__name__)

# OMERO.insight point list regular expression
Expand All @@ -36,6 +44,32 @@
OME_MODEL_POINT_LIST_RE = re.compile(r"([\d.]+),([\d.]+)")


def getChannelsNoRe(image):
"""
Returns a list of Channels.

This differs from image.getChannels(noRE=True) in that we load statsInfo
here which is used by channel.getWindowMin() and channel.getWindowMax()

:return: Channels
:rtype: List of :class:`ChannelWrapper`
"""

conn = image._conn
pid = image.getPixelsId()
params = omero.sys.ParametersI()
params.addId(pid)
query = """select p from Pixels p join fetch p.channels as c
join fetch c.logicalChannel as lc
left outer join fetch c.statsInfo
where p.id=:id"""
pixels = conn.getQueryService().findByQuery(query, params, conn.SERVICE_OPTS)
return [
ChannelWrapper(conn, c, idx=n, img=image)
for n, c in enumerate(pixels.iterateChannels())
]


def eventContextMarshal(event_context):
"""
Marshals the omero::sys::EventContext as a dict.
Expand Down Expand Up @@ -72,6 +106,80 @@ def eventContextMarshal(event_context):
return ctx


def getPixelRange(image):
minVals = {
PixelsTypeint8: -128,
PixelsTypeuint8: 0,
PixelsTypeint16: -32768,
PixelsTypeuint16: 0,
PixelsTypeint32: -2147483648,
PixelsTypeuint32: 0,
PixelsTypefloat: -2147483648,
PixelsTypedouble: -2147483648,
}
maxVals = {
PixelsTypeint8: 127,
PixelsTypeuint8: 255,
PixelsTypeint16: 32767,
PixelsTypeuint16: 65535,
PixelsTypeint32: 2147483647,
PixelsTypeuint32: 4294967295,
PixelsTypefloat: 2147483647,
PixelsTypedouble: 2147483647,
}
pixtype = image.getPrimaryPixels().getPixelsType().getValue()
return [minVals[pixtype], maxVals[pixtype]]


def getWindowMin(channel):
si = channel._obj.getStatsInfo()
if si is None:
return None
return si.getGlobalMin().val


def getWindowMax(channel):
si = channel._obj.getStatsInfo()
if si is None:
return None
return si.getGlobalMax().val


def rdefMarshal(rdef, image, pixel_range):

channels = []

for rdef_ch, channel in zip(rdef["c"], getChannelsNoRe(image)):

chan = {
"emissionWave": channel.getEmissionWave(),
"label": channel.getLabel(),
"color": rdef_ch["color"],
# 'reverseIntensity' is deprecated. Use 'inverted'
"inverted": rdef_ch["inverted"],
"reverseIntensity": rdef_ch["inverted"],
"family": rdef_ch["family"],
"coefficient": rdef_ch["coefficient"],
"active": rdef_ch["active"],
}

window_min = getWindowMin(channel)
window_max = getWindowMax(channel)

chan["window"] = {
"min": pixel_range[0] if window_min is None else window_min,
"max": pixel_range[1] if window_max is None else window_max,
"start": rdef_ch["start"],
"end": rdef_ch["end"],
}

lut = channel.getLut()
if lut and len(lut) > 0:
chan["lut"] = lut
channels.append(chan)
return channels


def channelMarshal(channel):
"""
return a dict with all there is to know about a channel
Expand Down Expand Up @@ -113,6 +221,7 @@ def imageMarshal(image, key=None, request=None):
@return: Dict
"""

# projection / invertAxis etc from annotation
image.loadRenderOptions()
pr = image.getProject()
ds = None
Expand Down Expand Up @@ -164,11 +273,9 @@ def imageMarshal(image, key=None, request=None):
"canLink": image.canLink(),
},
}
reOK = False
try:
reOK = image._prepareRenderingEngine()
if not reOK:
logger.debug("Failed to prepare Rendering Engine for imageMarshal")
return rv
except omero.ConcurrencyException as ce:
backOff = ce.backOff
rv = {"ConcurrencyException": {"backOff": backOff}}
Expand All @@ -179,8 +286,10 @@ def imageMarshal(image, key=None, request=None):
return rv # Return what we have already, in case it's useful

# big images
levels = image._re.getResolutionLevels()
tiles = levels > 1
tiles = False
if reOK:
levels = image._re.getResolutionLevels()
tiles = levels > 1
rv["tiles"] = tiles
if tiles:
width, height = image._re.getTileSize()
Expand Down Expand Up @@ -239,15 +348,20 @@ def pixel_size_in_microns(method):
rv["init_zoom"] = init_zoom
if nominalMagnification is not None:
rv.update({"nominalMagnification": nominalMagnification})

rdef = get_rendering_def(image, rv)
if not rdef:
return rv

try:
rv["pixel_range"] = image.getPixelRange()
rv["channels"] = [channelMarshal(x) for x in image.getChannels()]
rv["pixel_range"] = getPixelRange(image)
rv["channels"] = rdefMarshal(rdef, image, rv["pixel_range"])
rv["split_channel"] = image.splitChannelDims()
rv["rdefs"] = {
"model": (image.isGreyscaleRenderingModel() and "greyscale" or "color"),
"model": (rdef["model"] == "greyscale" and "greyscale" or "color"),
"projection": image.getProjection(),
"defaultZ": image._re.getDefaultZ(),
"defaultT": image._re.getDefaultT(),
"defaultZ": rdef["z"],
"defaultT": rdef["t"],
"invertAxis": image.isInvertedAxis(),
}
except TypeError:
Expand All @@ -264,6 +378,7 @@ def pixel_size_in_microns(method):
"invertAxis": image.isInvertedAxis(),
}
except AttributeError:
# Why do we do raise just for this exception?!
rv = None
raise
if key is not None and rv is not None:
Expand Down
38 changes: 38 additions & 0 deletions omeroweb/webgateway/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
import shutil
import logging

import omero
import traceback

logger = logging.getLogger(__name__)

LUTS_IN_PNG = [
Expand Down Expand Up @@ -233,3 +236,38 @@ def points_string_to_XY_list(string):
x, y = xy.split(",")
xyList.append((float(x.strip()), float(y.strip())))
return xyList


def load_re(image, rsp_dict=None):
rsp_dict = {} if rsp_dict is None else rsp_dict
reOK = False
try:
reOK = image._prepareRenderingEngine()
if not reOK:
rsp_dict["Error"] = "Failed to prepare Rendering Engine for imageMarshal"
logger.debug("Failed to prepare Rendering Engine for imageMarshal")
except omero.ConcurrencyException as ce:
backOff = ce.backOff
rsp_dict["ConcurrencyException"] = {"backOff": backOff}
except Exception as ex: # Handle everything else.
rsp_dict["Exception"] = ex.message
logger.error(traceback.format_exc())
return reOK


def get_rendering_def(image, rsp_dict=None):
# rsp_dict allows errors to be added
# Try to get user's rendering def
exp_id = image._conn.getUserId()
rdefs = image.getAllRenderingDefs(exp_id)
if len(rdefs) == 0:
# try to create our own rendering settings
if load_re(image, rsp_dict):
rdefs = image.getAllRenderingDefs(exp_id)
# otherwise use owners
if len(rdefs) == 0:
owner_id = image.getDetails().getOwner().id
if owner_id != exp_id:
rdefs = image.getAllRenderingDefs(owner_id)

return rdefs[0] if len(rdefs) > 0 else None
Loading