Skip to content
Merged
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
14 changes: 11 additions & 3 deletions components/tools/OmeroWeb/omeroweb/webgateway/marshal.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,20 @@ def imageMarshal (image, key=None):
image.loadRenderOptions()
pr = image.getProject()
ds = None
wellsample = None
well = None
try:
# Replicating the functionality of the deprecated
# ImageWrapper.getDataset() with shares in mind.
# -- Tue Sep 6 10:48:47 BST 2011 (See #6660)
parents = image.listParents()
if parents is not None and len(parents) == 1 \
and parents[0].OMERO_CLASS == 'Dataset':
ds = parents[0]
if parents is not None and len(parents) == 1:
if parents[0].OMERO_CLASS == 'Dataset':
ds = parents[0]
elif parents[0].OMERO_CLASS == 'WellSample':
wellsample = parents[0]
if wellsample.well is not None:
well = wellsample.well
except omero.SecurityViolation, e:
# We're in a share so the Image's parent Dataset cannot be loaded
# or some other permissions related issue has tripped us up.
Expand All @@ -90,6 +96,8 @@ def imageMarshal (image, key=None):
'datasetName': ds and ds.name or 'Multiple',
'datasetId': ds and ds.id or '',
'datasetDescription': ds and ds.description or '',
'wellSampleId': wellsample and wellsample.id or '',
'wellId': well and well.id.val or '',
'imageTimestamp': time.mktime(image.getDate().timetuple()),
'imageId': image.id,},
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,35 @@
$('#wblitz-image-pub').html(tmp.projectName);
$('#wblitz-image-pubid').html(tmp.projectId);
$('#wblitz-image-timestamp').html(tmp.imageTimestamp);

$("#bulk-annotations").hide();
$("#bulk-annotations").next().hide();
if (tmp.wellId) {
// Load bulk annotations for plate
var onAnnotations = function(result) {
if (result.data && result.data.rows) {
var table = $("#bulk-annotations").show().next().show().children("table");
table.find("tr").remove();
for (var col in result.data.columns) {
var label = result.data.columns[col];
var value = '';
for (var row in result.data.rows) {
value += result.data.rows[row][col] + '<br />';
}
var row = $('<tr><td class="title"></td><td></td></tr>');
row.addClass(col % 2 == 1 ? 'odd' : 'even');
$('td:first-child', row).html(label + ":&nbsp;");
$('td:last-child', row).html(value);
table.append(row);
}
}
};
$.getJSON('{% url webgateway_object_table_query 'Plate.wells' 999 %}'.replace('999', tmp.wellId) +
'?query=Well-' + tmp.wellId +
'&callback=?',
onAnnotations);
}

{% block xtra_metadata %}{% endblock %}

/*$('#wblitz-shortname').attr('title', tmp.imageName).html(gs_text_trim(tmp.imageName, 15, true));*/
Expand Down Expand Up @@ -947,6 +976,13 @@ <h3 class="can-collapse"> Dimensions </h3>
</tr>
</table>
</div>

<h3 class="can-collapse" id="bulk-annotations" style="display: none;">Bulk Annotations</h3>
<div style="display: none;">
<table cellspacing="0">
</table>
</div>

<!--<h3 class="can-collapse defclose"> Legend </h3>
<div id="wblitz-image-description"><span id="wblitz-image-description-content"></span></div>-->
</div>
Expand Down
25 changes: 23 additions & 2 deletions components/tools/OmeroWeb/omeroweb/webgateway/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,23 @@
Returns a main prefix
"""

annotations = url(r'^annotations/(?P<objtype>[\w.]+)/(?P<objid>\d+)/$', 'webgateway.views.annotations', name="webgateway_annotations")
"""
Retrieve annotations for object specified by object type and identifier,
optionally traversing object model graph.
"""

table_query = url(r'^table/(?P<fileid>\d+)/query/$', 'webgateway.views.table_query', name="webgateway_table_query")
"""
Query a table specified by fileid
"""

object_table_query = url(r'^table/(?P<objtype>[\w.]+)/(?P<objid>\d+)/query/$', 'webgateway.views.object_table_query', name="webgateway_object_table_query")
"""
Query bulk annotations table attached to an object specified by
object type and identifier, optionally traversing object model graph.
"""

render_image = (r'^render_image/(?P<iid>[^/]+)/(?:(?P<z>[^/]+)/)?(?:(?P<t>[^/]+)/)?$', 'webgateway.views.render_image')
"""
Returns a jpeg of the OMERO image. See L{views.render_image}. Rendering settings can be specified
Expand Down Expand Up @@ -196,7 +213,7 @@
- key: Optional key of selected attributes to return. E.g. meta, pixel_range, rdefs, split_channel, size etc
"""

wellData_json = (r'^wellData/(?P<wid>[^/]+)/$', 'webgateway.views.wellData_json')
wellData_json = url(r'^wellData/(?P<wid>[^/]+)/$', 'webgateway.views.wellData_json', name='webgateway_wellData_json')
"""
json method: returns details of specified Well. See L{views.wellData_json}.
- webgateway/wellData/<wid>/ params are:
Expand Down Expand Up @@ -304,7 +321,11 @@
copy_image_rdef_json,
# switch user
webgateway_su,

# bulk annotations
annotations,
table_query,
object_table_query,

# Debug stuff

)
Expand Down
157 changes: 156 additions & 1 deletion components/tools/OmeroWeb/omeroweb/webgateway/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,17 @@

import omero
import omero.clients
from django.http import HttpResponse, HttpResponseServerError, HttpResponseRedirect, Http404
from django.http import HttpResponse, HttpResponseServerError, HttpResponseRedirect, Http404, HttpResponseNotFound
from django.utils import simplejson
from django.utils.encoding import smart_str
from django.utils.http import urlquote
from django.views.decorators.http import require_POST
from django.core import template_loader
from django.core.urlresolvers import reverse
from django.conf import settings
from django.template import RequestContext as Context
from omero.rtypes import rlong, unwrap
from omero.constants.namespaces import NSBULKANNOTATIONS
from marshal import imageMarshal, shapeMarshal

try:
Expand Down Expand Up @@ -1679,3 +1681,156 @@ def su (request, user, conn=None, **kwargs):
conn.revertGroupForSession()
conn.seppuku()
return True


def _annotations(request, objtype, objid, conn=None, **kwargs):
"""
Retrieve annotations for object specified by object type and identifier,
optionally traversing object model graph.
Returns dictionary containing annotations in NSBULKANNOTATIONS namespace
if successful, error information otherwise

Example: /annotations/Plate/1/
retrieves annotations for plate with identifier 1
Example: /annotations/Plate.wells/1/
retrieves annotations for plate that contains well with
identifier 1

@param request: http request.
@param objtype: Type of target object, or type of target object followed
by a slash-separated list of properties to resolve
@param objid: Identifier of target object, or identifier of object
reached by resolving given properties
@param conn: L{omero.gateway.BlitzGateway}
@param **kwargs: unused
@return: A dictionary with key 'error' with an error message or
with key 'data' containing an array of dictionaries
with keys 'id' and 'file' of the retrieved annotations
"""
q = conn.getQueryService()
# If more than one objtype is specified, use all in query to
# traverse object model graph
# Example: /annotations/Plate/wells/1/
# retrieves annotations from Plate that contains Well 1
objtype = objtype.split('.')

query = "select obj0 from %s obj0\n" % objtype[0]
for i, t in enumerate(objtype[1:]):
query += "join fetch obj%d.%s obj%d\n" % (i, t, i+1)
query += """
left outer join fetch obj0.annotationLinks links
left outer join fetch links.child
where obj%d.id=:id""" % (len(objtype) - 1)

try:
obj = q.findByQuery(query, omero.sys.ParametersI().addId(objid),
conn.createServiceOptsDict())
except omero.QueryException, ex:
return HttpResponseNotFound('%s cannot be queried' % objtype)

if not obj:
return HttpResponseNotFound('%s with id %s not found' % (objtype, objid))

return dict(data=[
dict(id=annotation.id.val,
file=annotation.file.id.val)
for annotation in obj.linkedAnnotationList()
if unwrap(annotation.getNs()) == NSBULKANNOTATIONS
])

annotations = login_required()(jsonp(_annotations))


def _table_query(request, fileid, conn=None, **kwargs):
"""
Query a table specified by fileid
Returns a dictionary with query result if successful, error information
otherwise

@param request: http request; querystring must contain key 'query'
with query to be executed, or '*' to retrieve all rows.
If query is in the format word-number, e.g. "Well-7",
if will be run as (word==number), e.g. "(Well==7)".
This is supported to allow more readable query strings.
@param fileid: Numeric identifier of file containing the table
@param conn: L{omero.gateway.BlitzGateway}
@param **kwargs: unused
@return: A dictionary with key 'error' with an error message
or with key 'data' containing a dictionary with keys
'columns' (an array of column names) and 'rows'
(an array of rows, each an array of values)
"""
query = request.GET.get('query')
if not query:
return dict(error='Must specify query parameter, use * to retrieve all')

r = conn.getSharedResources()
t = r.openTable(omero.model.OriginalFileI(fileid),
conn.createServiceOptsDict())
if not t:
return dict(error="Table %s not found" % fileid)

cols = t.getHeaders()
rows = t.getNumberOfRows()

if query == '*':
hits = range(rows)
else:
match = re.match(r'^(\w+)-(\d+)', query)
if match:
query = '(%s==%s)' % (match.group(1), match.group(2))
try:
hits = t.getWhereList(query, None, 0, rows, 1)
except Exception, e:
return dict(error='Error executing query: %s' % query)

return dict(data=dict(
columns=[col.name for col in cols],
rows=[
[col.values[0] for col in t.read(range(len(cols)), hit, hit+1).columns]
for hit in hits
],
)
)

table_query = login_required()(jsonp(_table_query))


@login_required()
@jsonp
def object_table_query(request, objtype, objid, conn=None, **kwargs):
"""
Query bulk annotations table attached to an object specified by
object type and identifier, optionally traversing object model graph.
Returns a dictionary with query result if successful, error information
otherwise

Example: /table/Plate/1/query/?query=*
queries bulk annotations table for plate with identifier 1
Example: /table/Plate.wells/1/query/?query=*
queries bulk annotations table for plate that contains well with
identifier 1

@param request: http request.
@param objtype: Type of target object, or type of target object followed
by a slash-separated list of properties to resolve
@param objid: Identifier of target object, or identifier of object
reached by resolving given properties
@param conn: L{omero.gateway.BlitzGateway}
@param **kwargs: unused
@return: A dictionary with key 'error' with an error message
or with key 'data' containing a dictionary with keys
'columns' (an array of column names) and 'rows'
(an array of rows, each an array of values)
"""
a = _annotations(request, objtype, objid, conn, **kwargs)
if isinstance(a, HttpResponse) or a.has_key('error'):
return a

if len(a['data']) != 1:
return dict(error='Could not retrieve single bulk annotations table')

# multiple bulk annotations files could be attached, use the most recent
# one (= the one with the highest identifier)
fileId = max(annotation['file'] for annotation in a['data'])
return _table_query(request, fileId, conn, **kwargs)