From 68ad7bc6ad2eabea874614db539bbf9895ce5002 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 1 Nov 2023 16:09:58 +0100 Subject: [PATCH 01/15] api_annotations send inherited annotations under 'inherited' --- omeroweb/webclient/views.py | 84 +++++++++++++++++++++++++++++-------- 1 file changed, 67 insertions(+), 17 deletions(-) diff --git a/omeroweb/webclient/views.py b/omeroweb/webclient/views.py index 560f721731..ee64c7a6da 100755 --- a/omeroweb/webclient/views.py +++ b/omeroweb/webclient/views.py @@ -35,6 +35,7 @@ import re import sys import warnings +from collections import defaultdict from past.builtins import unicode from future.utils import bytes_to_native_str from django.utils.html import escape @@ -193,6 +194,24 @@ def validate_redirect_url(url): return url +def get_parentIds_recursive(obj): + """ + Goes recursively through the object parents list. + Returns a dictionary containing a list of parents Id + per type. + """ + d = defaultdict(set) + if obj.OMERO_CLASS == "WellSample": + id_ = int(obj.getPlateAcquisition().getId()) + d["PlateAcquisition"].add(id_) + else: + d[obj.OMERO_CLASS].add(int(obj.getId())) + for parent in obj.listParents(): + for k, v in get_parentIds_recursive(parent).items(): + d[k].update(v) + return d + + ############################################################################## # custom index page @@ -1341,35 +1360,66 @@ def api_tags_and_tagged_list_DELETE(request, conn=None, **kwargs): @login_required() def api_annotations(request, conn=None, **kwargs): r = request.GET - image_ids = get_list(request, "image") - dataset_ids = get_list(request, "dataset") - project_ids = get_list(request, "project") - screen_ids = get_list(request, "screen") - plate_ids = get_list(request, "plate") - run_ids = get_list(request, "acquisition") - well_ids = get_list(request, "well") page = get_long_or_default(request, "page", 1) limit = get_long_or_default(request, "limit", ANNOTATIONS_LIMIT) - ann_type = r.get("type", None) ns = r.get("ns", None) - anns, exps = tree.marshal_annotations( + to_query = defaultdict(set) + inheritors = defaultdict(lambda: defaultdict(list)) + requested = defaultdict(list) + for type_ in ("Image", "Dataset", "Project", + "Well", "Acquisition", "Plate", "Screen"): + if type_ == "Acquisition": + type_ = "PlateAcquisition" + + for id_ in get_list(request, type_.lower()): + id_ = int(id_) + requested[type_].append(id_) + + obj = conn.getObject(type_, id_) + obj_descr = {"id": id_, + "class": type_+"I", + "name": obj.getName()} + if type_ == "Well": + del obj_descr["name"] + + for k, v in get_parentIds_recursive(obj).items(): + to_query[k].update(v) + if k != type_: # Skip current object + for parent in v: + inheritors[k][parent].append(obj_descr) + + all_anns, exps = tree.marshal_annotations( conn, - project_ids=project_ids, - dataset_ids=dataset_ids, - image_ids=image_ids, - screen_ids=screen_ids, - plate_ids=plate_ids, - run_ids=run_ids, - well_ids=well_ids, + project_ids=to_query["Project"], + dataset_ids=to_query["Dataset"], + image_ids=to_query["Image"], + screen_ids=to_query["Screen"], + plate_ids=to_query["Plate"], + run_ids=to_query["PlateAcquisition"], + well_ids=to_query["Well"], ann_type=ann_type, ns=ns, page=page, limit=limit, ) - return JsonResponse({"annotations": anns, "experimenters": exps}) + anns = [] + inherited_anns = {"annotations": [], "inheritors": {}} + for ann in all_anns: + p = ann["link"]["parent"] + pclass, pid = p["class"][:-1], p["id"] + if pid in requested[pclass]: + anns.append(ann) + inheritor_l = inheritors[pclass][pid] + if len(inheritor_l) > 0: + inherited_anns["annotations"].append(ann) + inherited_anns["inheritors"][int(ann["id"])] = inheritor_l + + return JsonResponse({"annotations": anns, + "inherited": inherited_anns, + "experimenters": exps}) @login_required() From b9abd951fa366a173abb0cccc9cae3f21785d298 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 1 Nov 2023 18:00:04 +0100 Subject: [PATCH 02/15] display of inherited mapann in main viewer --- .../ome.right_panel_mapanns_pane.js | 43 ++++++++++++++++--- .../annotations/mapanns_underscore.html | 9 +++- 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/omeroweb/webclient/static/webclient/javascript/ome.right_panel_mapanns_pane.js b/omeroweb/webclient/static/webclient/javascript/ome.right_panel_mapanns_pane.js index 2ab23ea62d..fb2da3e2fc 100644 --- a/omeroweb/webclient/static/webclient/javascript/ome.right_panel_mapanns_pane.js +++ b/omeroweb/webclient/static/webclient/javascript/ome.right_panel_mapanns_pane.js @@ -132,17 +132,31 @@ var MapAnnsPane = function MapAnnsPane($element, opts) { }, {}); } - // Populate experimenters within anns - var anns = data.annotations.map(function(ann){ + var populate_experimenter = function(ann) { if (data.experimenters.length > 0) { ann.owner = experimenters[ann.owner.id]; } if (ann.link && ann.link.owner) { ann.link.owner = experimenters[ann.link.owner.id]; // AddedBy IDs for filtering - ann.addedBy = [ann.link.owner.id]; + ann.addedBy = [ann.link.owner.id]; } return ann; + }; + + // Populate experimenters within anns + var anns = data.annotations.map(populate_experimenter); + + + var inh_anns = []; + data.inherited.annotations.forEach(function(ann) { + ann = populate_experimenter(ann); + for(j = 0; j < data.inherited.inheritors[ann["id"]].length; j++){ + // Unpacking the parent annoations for each image + let clone_ann = { ...ann }; + //clone_ann.link.parent.class = clone_ann.link.parent.class.substring(0, class_.length - 1); + inh_anns.push(clone_ann); + } }); // Sort map anns into 3 lists... @@ -160,10 +174,22 @@ var MapAnnsPane = function MapAnnsPane($element, opts) { } }); + var inh_client_map_annotations = []; + var inh_map_annotations = []; + inh_anns.forEach(function(ann){ + if (isClientMapAnn(ann)) { + inh_client_map_annotations.push(ann); + } else { + inh_map_annotations.push(ann); + } + }); + if (batchAnn) { my_client_map_annotations = groupDuplicateAnns(my_client_map_annotations); client_map_annotations = groupDuplicateAnns(client_map_annotations); map_annotations = groupDuplicateAnns(map_annotations); + inh_client_map_annotations = groupDuplicateAnns(inh_client_map_annotations); + inh_map_annotations = groupDuplicateAnns(inh_map_annotations); } // Update html... @@ -178,11 +204,16 @@ var MapAnnsPane = function MapAnnsPane($element, opts) { } // In batch_annotate view, we show which object each map is linked to var showParent = batchAnn; - html = html + mapAnnsTempl({'anns': my_client_map_annotations, 'objCount': objects.length, + html = html + mapAnnsTempl({'anns': inh_client_map_annotations, 'isInherited': true, 'showTableHead': showHead, 'showNs': false, 'clientMapAnn': true, 'showParent': showParent}); - html = html + mapAnnsTempl({'anns': client_map_annotations, + html = html + mapAnnsTempl({'anns': inh_map_annotations, 'isInherited': true, + 'showTableHead': false, 'showNs': true, 'clientMapAnn': false, 'showParent': showParent}); + html = html + mapAnnsTempl({'anns': my_client_map_annotations, 'objCount': objects.length, + 'showTableHead': showHead, 'showNs': false, 'clientMapAnn': true, 'showParent': showParent, + 'isInherited': false}); + html = html + mapAnnsTempl({'anns': client_map_annotations, 'isInherited': false, 'showTableHead': false, 'showNs': false, 'clientMapAnn': true, 'showParent': showParent}); - html = html + mapAnnsTempl({'anns': map_annotations, + html = html + mapAnnsTempl({'anns': map_annotations, 'isInherited': false, 'showTableHead': false, 'showNs': true, 'clientMapAnn': false, 'showParent': showParent}); $mapAnnContainer.html(html); diff --git a/omeroweb/webclient/templates/webclient/annotations/mapanns_underscore.html b/omeroweb/webclient/templates/webclient/annotations/mapanns_underscore.html index fc28427993..df67efe5e5 100644 --- a/omeroweb/webclient/templates/webclient/annotations/mapanns_underscore.html +++ b/omeroweb/webclient/templates/webclient/annotations/mapanns_underscore.html @@ -7,9 +7,16 @@ data-added-by="<%= WEBCLIENT.USER.id %>" <% } %> class="keyValueTable - <% if (!ann.id || (ann.permissions.canEdit && clientMapAnn)){ %> editableKeyValueTable <% } %> + <% if (!ann.id || (ann.permissions.canEdit && clientMapAnn && !isInherited)){ %> editableKeyValueTable <% } %> "> + <% if (isInherited) { %> + + + <%- (ann.link.parent.class.substring(0, ann.link.parent.class.length - 1) + ":" + ann.link.parent.id + ":" + ann.link.parent.name).slice(0, 50) %> + + + <% } %> <% if (showNs && ann.ns) { %> From 1c11ac40f1c4614ec8a74a9ee7c377c1a766d48f Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 1 Nov 2023 17:36:51 +0000 Subject: [PATCH 03/15] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- omeroweb/webclient/views.py | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/omeroweb/webclient/views.py b/omeroweb/webclient/views.py index ee64c7a6da..4abb701c3a 100755 --- a/omeroweb/webclient/views.py +++ b/omeroweb/webclient/views.py @@ -1368,8 +1368,15 @@ def api_annotations(request, conn=None, **kwargs): to_query = defaultdict(set) inheritors = defaultdict(lambda: defaultdict(list)) requested = defaultdict(list) - for type_ in ("Image", "Dataset", "Project", - "Well", "Acquisition", "Plate", "Screen"): + for type_ in ( + "Image", + "Dataset", + "Project", + "Well", + "Acquisition", + "Plate", + "Screen", + ): if type_ == "Acquisition": type_ = "PlateAcquisition" @@ -1378,9 +1385,7 @@ def api_annotations(request, conn=None, **kwargs): requested[type_].append(id_) obj = conn.getObject(type_, id_) - obj_descr = {"id": id_, - "class": type_+"I", - "name": obj.getName()} + obj_descr = {"id": id_, "class": type_ + "I", "name": obj.getName()} if type_ == "Well": del obj_descr["name"] @@ -1417,9 +1422,9 @@ def api_annotations(request, conn=None, **kwargs): inherited_anns["annotations"].append(ann) inherited_anns["inheritors"][int(ann["id"])] = inheritor_l - return JsonResponse({"annotations": anns, - "inherited": inherited_anns, - "experimenters": exps}) + return JsonResponse( + {"annotations": anns, "inherited": inherited_anns, "experimenters": exps} + ) @login_required() From 9b6f81df8f3064296070a8f17bc29ebfffd0a7fe Mon Sep 17 00:00:00 2001 From: Tom-TBT Date: Sat, 4 Nov 2023 09:32:09 +0100 Subject: [PATCH 04/15] added parents=true for api_annotations --- .../ome.right_panel_mapanns_pane.js | 2 +- omeroweb/webclient/views.py | 33 ++++++++++++------- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/omeroweb/webclient/static/webclient/javascript/ome.right_panel_mapanns_pane.js b/omeroweb/webclient/static/webclient/javascript/ome.right_panel_mapanns_pane.js index fb2da3e2fc..c84c40b49c 100644 --- a/omeroweb/webclient/static/webclient/javascript/ome.right_panel_mapanns_pane.js +++ b/omeroweb/webclient/static/webclient/javascript/ome.right_panel_mapanns_pane.js @@ -104,7 +104,7 @@ var MapAnnsPane = function MapAnnsPane($element, opts) { } // convert objects to json data - ajaxdata = {"type": "map"}; + ajaxdata = {"type": "map", "parents": true}; for (var i=0; i < objects.length; i++) { var o = objects[i].split(/-(.+)/); if (typeof ajaxdata[o[0]] !== 'undefined') { diff --git a/omeroweb/webclient/views.py b/omeroweb/webclient/views.py index 4abb701c3a..cc751aed28 100755 --- a/omeroweb/webclient/views.py +++ b/omeroweb/webclient/views.py @@ -199,13 +199,15 @@ def get_parentIds_recursive(obj): Goes recursively through the object parents list. Returns a dictionary containing a list of parents Id per type. + params: + - obj: if not in exisiting_d, add and iterate on parents """ d = defaultdict(set) if obj.OMERO_CLASS == "WellSample": - id_ = int(obj.getPlateAcquisition().getId()) - d["PlateAcquisition"].add(id_) - else: - d[obj.OMERO_CLASS].add(int(obj.getId())) + d["PlateAcquisition"].add(int(obj.getPlateAcquisition().getId())) + obj = obj.getParent() # Jump right away to the Well + d[obj.OMERO_CLASS].add(int(obj.getId())) + for parent in obj.listParents(): for k, v in get_parentIds_recursive(parent).items(): d[k].update(v) @@ -1364,6 +1366,7 @@ def api_annotations(request, conn=None, **kwargs): limit = get_long_or_default(request, "limit", ANNOTATIONS_LIMIT) ann_type = r.get("type", None) ns = r.get("ns", None) + with_parents = r.get("parents", False) to_query = defaultdict(set) inheritors = defaultdict(lambda: defaultdict(list)) @@ -1385,15 +1388,17 @@ def api_annotations(request, conn=None, **kwargs): requested[type_].append(id_) obj = conn.getObject(type_, id_) - obj_descr = {"id": id_, "class": type_ + "I", "name": obj.getName()} - if type_ == "Well": - del obj_descr["name"] + if not with_parents: + to_query[type_].add(id_) + continue + + details = {"id": id_, "class": type_ + "I"} for k, v in get_parentIds_recursive(obj).items(): to_query[k].update(v) if k != type_: # Skip current object for parent in v: - inheritors[k][parent].append(obj_descr) + inheritors[k][parent].append(details) all_anns, exps = tree.marshal_annotations( conn, @@ -1409,9 +1414,13 @@ def api_annotations(request, conn=None, **kwargs): page=page, limit=limit, ) + if not with_parents: + return JsonResponse( + {"annotations": all_anns, "experimenters": exps} + ) anns = [] - inherited_anns = {"annotations": [], "inheritors": {}} + inh_anns = {"annotations": [], "inheritors": {}} for ann in all_anns: p = ann["link"]["parent"] pclass, pid = p["class"][:-1], p["id"] @@ -1419,11 +1428,11 @@ def api_annotations(request, conn=None, **kwargs): anns.append(ann) inheritor_l = inheritors[pclass][pid] if len(inheritor_l) > 0: - inherited_anns["annotations"].append(ann) - inherited_anns["inheritors"][int(ann["id"])] = inheritor_l + inh_anns["annotations"].append(ann) + inh_anns["inheritors"][int(ann["id"])] = inheritor_l return JsonResponse( - {"annotations": anns, "inherited": inherited_anns, "experimenters": exps} + {"annotations": anns, "inherited": inh_anns, "experimenters": exps} ) From 106c4ab13939eada0424eb7b2e2c41d47b47d485 Mon Sep 17 00:00:00 2001 From: Tom-TBT Date: Sat, 4 Nov 2023 10:45:19 +0100 Subject: [PATCH 05/15] changed inheritor response --- .../ome.right_panel_mapanns_pane.js | 7 ++++-- omeroweb/webclient/views.py | 23 ++++++++++--------- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/omeroweb/webclient/static/webclient/javascript/ome.right_panel_mapanns_pane.js b/omeroweb/webclient/static/webclient/javascript/ome.right_panel_mapanns_pane.js index c84c40b49c..c76ee12277 100644 --- a/omeroweb/webclient/static/webclient/javascript/ome.right_panel_mapanns_pane.js +++ b/omeroweb/webclient/static/webclient/javascript/ome.right_panel_mapanns_pane.js @@ -104,7 +104,7 @@ var MapAnnsPane = function MapAnnsPane($element, opts) { } // convert objects to json data - ajaxdata = {"type": "map", "parents": true}; + ajaxdata = {"type": "map", "parents": "yes"}; for (var i=0; i < objects.length; i++) { var o = objects[i].split(/-(.+)/); if (typeof ajaxdata[o[0]] !== 'undefined') { @@ -151,7 +151,10 @@ var MapAnnsPane = function MapAnnsPane($element, opts) { var inh_anns = []; data.inherited.annotations.forEach(function(ann) { ann = populate_experimenter(ann); - for(j = 0; j < data.inherited.inheritors[ann["id"]].length; j++){ + let class_ = ann.link.parent.class; + let id_ = '' + ann.link.parent.id; + children = data.inherited.inheritors[class_][id_]; + for(j = 0; j < children.length; j++){ // Unpacking the parent annoations for each image let clone_ann = { ...ann }; //clone_ann.link.parent.class = clone_ann.link.parent.class.substring(0, class_.length - 1); diff --git a/omeroweb/webclient/views.py b/omeroweb/webclient/views.py index cc751aed28..03bcb62382 100755 --- a/omeroweb/webclient/views.py +++ b/omeroweb/webclient/views.py @@ -1366,7 +1366,8 @@ def api_annotations(request, conn=None, **kwargs): limit = get_long_or_default(request, "limit", ANNOTATIONS_LIMIT) ann_type = r.get("type", None) ns = r.get("ns", None) - with_parents = r.get("parents", False) + with_parents = r.get("parents", "no") + with_parents = with_parents == "yes" to_query = defaultdict(set) inheritors = defaultdict(lambda: defaultdict(list)) @@ -1394,11 +1395,11 @@ def api_annotations(request, conn=None, **kwargs): details = {"id": id_, "class": type_ + "I"} - for k, v in get_parentIds_recursive(obj).items(): - to_query[k].update(v) - if k != type_: # Skip current object - for parent in v: - inheritors[k][parent].append(details) + for p_type, p_ids in get_parentIds_recursive(obj).items(): + to_query[p_type].update(p_ids) + if p_type != type_: # Skip current object + for p_id in p_ids: + inheritors[p_type][p_id].append(details) all_anns, exps = tree.marshal_annotations( conn, @@ -1420,16 +1421,16 @@ def api_annotations(request, conn=None, **kwargs): ) anns = [] - inh_anns = {"annotations": [], "inheritors": {}} + inh_anns = {"annotations": [], "inheritors": defaultdict(dict)} for ann in all_anns: p = ann["link"]["parent"] - pclass, pid = p["class"][:-1], p["id"] - if pid in requested[pclass]: + pclass, pid = p["class"], p["id"] + if pid in requested[pclass[:-1]]: anns.append(ann) - inheritor_l = inheritors[pclass][pid] + inheritor_l = inheritors[pclass[:-1]][pid] if len(inheritor_l) > 0: inh_anns["annotations"].append(ann) - inh_anns["inheritors"][int(ann["id"])] = inheritor_l + inh_anns["inheritors"][pclass][pid] = inheritor_l return JsonResponse( {"annotations": anns, "inherited": inh_anns, "experimenters": exps} From 271e46ba384bc57765b1cbf55b5abcba5fd60689 Mon Sep 17 00:00:00 2001 From: Tom-TBT Date: Sat, 4 Nov 2023 13:11:57 +0100 Subject: [PATCH 06/15] rework UI and moved inherited under current object mapann --- .../ome.right_panel_mapanns_pane.js | 50 ++++++++----------- .../annotations/mapanns_underscore.html | 27 +++++++--- omeroweb/webclient/views.py | 4 +- 3 files changed, 42 insertions(+), 39 deletions(-) diff --git a/omeroweb/webclient/static/webclient/javascript/ome.right_panel_mapanns_pane.js b/omeroweb/webclient/static/webclient/javascript/ome.right_panel_mapanns_pane.js index c76ee12277..46d5f69366 100644 --- a/omeroweb/webclient/static/webclient/javascript/ome.right_panel_mapanns_pane.js +++ b/omeroweb/webclient/static/webclient/javascript/ome.right_panel_mapanns_pane.js @@ -147,20 +147,24 @@ var MapAnnsPane = function MapAnnsPane($element, opts) { // Populate experimenters within anns var anns = data.annotations.map(populate_experimenter); - - var inh_anns = []; - data.inherited.annotations.forEach(function(ann) { - ann = populate_experimenter(ann); - let class_ = ann.link.parent.class; - let id_ = '' + ann.link.parent.id; - children = data.inherited.inheritors[class_][id_]; - for(j = 0; j < children.length; j++){ - // Unpacking the parent annoations for each image - let clone_ann = { ...ann }; - //clone_ann.link.parent.class = clone_ann.link.parent.class.substring(0, class_.length - 1); - inh_anns.push(clone_ann); - } - }); + var inh_map_annotations = []; + if (data.hasOwnProperty("inherited")){ + data.inherited.annotations.forEach(function(ann) { + ann = populate_experimenter(ann); + let class_ = ann.link.parent.class; + let id_ = '' + ann.link.parent.id; + children = data.inherited.inheritors[class_][id_]; + class_ = children[0].class; + ann.childClass = class_.substring(0, class_.length - 1); + ann.childNames = []; + if (children[0].hasOwnProperty("name")){ + for(j = 0; j < children.length; j++){ + ann.childNames.push(children[j].name); + } + } + inh_map_annotations.push(ann); + }); + } // Sort map anns into 3 lists... var client_map_annotations = []; @@ -177,22 +181,10 @@ var MapAnnsPane = function MapAnnsPane($element, opts) { } }); - var inh_client_map_annotations = []; - var inh_map_annotations = []; - inh_anns.forEach(function(ann){ - if (isClientMapAnn(ann)) { - inh_client_map_annotations.push(ann); - } else { - inh_map_annotations.push(ann); - } - }); - if (batchAnn) { my_client_map_annotations = groupDuplicateAnns(my_client_map_annotations); client_map_annotations = groupDuplicateAnns(client_map_annotations); map_annotations = groupDuplicateAnns(map_annotations); - inh_client_map_annotations = groupDuplicateAnns(inh_client_map_annotations); - inh_map_annotations = groupDuplicateAnns(inh_map_annotations); } // Update html... @@ -207,10 +199,6 @@ var MapAnnsPane = function MapAnnsPane($element, opts) { } // In batch_annotate view, we show which object each map is linked to var showParent = batchAnn; - html = html + mapAnnsTempl({'anns': inh_client_map_annotations, 'isInherited': true, - 'showTableHead': showHead, 'showNs': false, 'clientMapAnn': true, 'showParent': showParent}); - html = html + mapAnnsTempl({'anns': inh_map_annotations, 'isInherited': true, - 'showTableHead': false, 'showNs': true, 'clientMapAnn': false, 'showParent': showParent}); html = html + mapAnnsTempl({'anns': my_client_map_annotations, 'objCount': objects.length, 'showTableHead': showHead, 'showNs': false, 'clientMapAnn': true, 'showParent': showParent, 'isInherited': false}); @@ -218,6 +206,8 @@ var MapAnnsPane = function MapAnnsPane($element, opts) { 'showTableHead': false, 'showNs': false, 'clientMapAnn': true, 'showParent': showParent}); html = html + mapAnnsTempl({'anns': map_annotations, 'isInherited': false, 'showTableHead': false, 'showNs': true, 'clientMapAnn': false, 'showParent': showParent}); + html = html + mapAnnsTempl({'anns': inh_map_annotations, 'isInherited': true, + 'showTableHead': false, 'showNs': true, 'clientMapAnn': false, 'showParent': showParent}); $mapAnnContainer.html(html); // re-use the ajaxdata to set Object IDS data on the parent container diff --git a/omeroweb/webclient/templates/webclient/annotations/mapanns_underscore.html b/omeroweb/webclient/templates/webclient/annotations/mapanns_underscore.html index df67efe5e5..3999bd5562 100644 --- a/omeroweb/webclient/templates/webclient/annotations/mapanns_underscore.html +++ b/omeroweb/webclient/templates/webclient/annotations/mapanns_underscore.html @@ -10,14 +10,7 @@ <% if (!ann.id || (ann.permissions.canEdit && clientMapAnn && !isInherited)){ %> editableKeyValueTable <% } %> "> - <% if (isInherited) { %> - - - <%- (ann.link.parent.class.substring(0, ann.link.parent.class.length - 1) + ":" + ann.link.parent.id + ":" + ann.link.parent.name).slice(0, 50) %> - - - <% } %> - <% if (showNs && ann.ns) { %> + <% if (showNs && ann.ns && !isInherited) { %> <%- ann.ns.slice(0, 50) %> @@ -27,6 +20,9 @@ <% if (ann.id) { %> + <% if (isInherited) { %> + Added on <%- ann.link.parent.class.substring(0, ann.link.parent.class.length - 1) %> <%- ann.link.parent.name.slice(0, 30) %> + <% } else { %> Added by: <%- ann.owner.firstName %> <%- ann.owner.lastName %> <% if (showParent && ann.link.parent.name){ %>
@@ -37,8 +33,14 @@ <% } %> <%- ann.parentNames ? (ann.parentNames.length + " objects") : ann.link.parent.name %> <% } %> + <% } %> <% } else if (objCount && objCount > 1) { %> Add annotations to <%- objCount %> objects diff --git a/omeroweb/webclient/views.py b/omeroweb/webclient/views.py index 03bcb62382..b7b3bfc869 100755 --- a/omeroweb/webclient/views.py +++ b/omeroweb/webclient/views.py @@ -1393,7 +1393,9 @@ def api_annotations(request, conn=None, **kwargs): to_query[type_].add(id_) continue - details = {"id": id_, "class": type_ + "I"} + details = {"id": id_, "class": type_ + "I", "name": obj.getName()} + if type_ in ["Well", "PlateAcquisition"]: + del details["name"] for p_type, p_ids in get_parentIds_recursive(obj).items(): to_query[p_type].update(p_ids) From 3fe0a123f94ae7e1d5a7b700d26b9ce2421d2c99 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 4 Nov 2023 12:12:17 +0000 Subject: [PATCH 07/15] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- omeroweb/webclient/views.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/omeroweb/webclient/views.py b/omeroweb/webclient/views.py index b7b3bfc869..5392c949a2 100755 --- a/omeroweb/webclient/views.py +++ b/omeroweb/webclient/views.py @@ -1418,9 +1418,7 @@ def api_annotations(request, conn=None, **kwargs): limit=limit, ) if not with_parents: - return JsonResponse( - {"annotations": all_anns, "experimenters": exps} - ) + return JsonResponse({"annotations": all_anns, "experimenters": exps}) anns = [] inh_anns = {"annotations": [], "inheritors": defaultdict(dict)} From 65962aeede6eb6b9483a6b6d5f3965ff8d64773a Mon Sep 17 00:00:00 2001 From: Tom-TBT Date: Thu, 16 Nov 2023 16:27:34 +0100 Subject: [PATCH 08/15] modified api_annotations parents parameter names --- .../ome.right_panel_mapanns_pane.js | 8 ++++---- omeroweb/webclient/views.py | 20 +++++++++---------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/omeroweb/webclient/static/webclient/javascript/ome.right_panel_mapanns_pane.js b/omeroweb/webclient/static/webclient/javascript/ome.right_panel_mapanns_pane.js index 46d5f69366..8fca4b09a1 100644 --- a/omeroweb/webclient/static/webclient/javascript/ome.right_panel_mapanns_pane.js +++ b/omeroweb/webclient/static/webclient/javascript/ome.right_panel_mapanns_pane.js @@ -104,7 +104,7 @@ var MapAnnsPane = function MapAnnsPane($element, opts) { } // convert objects to json data - ajaxdata = {"type": "map", "parents": "yes"}; + ajaxdata = {"type": "map", "parents": "true"}; for (var i=0; i < objects.length; i++) { var o = objects[i].split(/-(.+)/); if (typeof ajaxdata[o[0]] !== 'undefined') { @@ -148,12 +148,12 @@ var MapAnnsPane = function MapAnnsPane($element, opts) { var anns = data.annotations.map(populate_experimenter); var inh_map_annotations = []; - if (data.hasOwnProperty("inherited")){ - data.inherited.annotations.forEach(function(ann) { + if (data.hasOwnProperty("parents")){ + data.parents.annotations.forEach(function(ann) { ann = populate_experimenter(ann); let class_ = ann.link.parent.class; let id_ = '' + ann.link.parent.id; - children = data.inherited.inheritors[class_][id_]; + children = data.parents.lineage[class_][id_]; class_ = children[0].class; ann.childClass = class_.substring(0, class_.length - 1); ann.childNames = []; diff --git a/omeroweb/webclient/views.py b/omeroweb/webclient/views.py index 5392c949a2..86bdc6f813 100755 --- a/omeroweb/webclient/views.py +++ b/omeroweb/webclient/views.py @@ -1366,11 +1366,11 @@ def api_annotations(request, conn=None, **kwargs): limit = get_long_or_default(request, "limit", ANNOTATIONS_LIMIT) ann_type = r.get("type", None) ns = r.get("ns", None) - with_parents = r.get("parents", "no") - with_parents = with_parents == "yes" + with_parents = r.get("parents", "false") + with_parents = with_parents == "true" to_query = defaultdict(set) - inheritors = defaultdict(lambda: defaultdict(list)) + lineage_d = defaultdict(lambda: defaultdict(list)) requested = defaultdict(list) for type_ in ( "Image", @@ -1401,7 +1401,7 @@ def api_annotations(request, conn=None, **kwargs): to_query[p_type].update(p_ids) if p_type != type_: # Skip current object for p_id in p_ids: - inheritors[p_type][p_id].append(details) + lineage_d[p_type][p_id].append(details) all_anns, exps = tree.marshal_annotations( conn, @@ -1421,19 +1421,19 @@ def api_annotations(request, conn=None, **kwargs): return JsonResponse({"annotations": all_anns, "experimenters": exps}) anns = [] - inh_anns = {"annotations": [], "inheritors": defaultdict(dict)} + parent_anns = {"annotations": [], "lineage": defaultdict(dict)} for ann in all_anns: p = ann["link"]["parent"] pclass, pid = p["class"], p["id"] if pid in requested[pclass[:-1]]: anns.append(ann) - inheritor_l = inheritors[pclass[:-1]][pid] - if len(inheritor_l) > 0: - inh_anns["annotations"].append(ann) - inh_anns["inheritors"][pclass][pid] = inheritor_l + lineage_l = lineage_d[pclass[:-1]][pid] + if len(lineage_l) > 0: + parent_anns["annotations"].append(ann) + parent_anns["lineage"][pclass][pid] = lineage_l return JsonResponse( - {"annotations": anns, "inherited": inh_anns, "experimenters": exps} + {"annotations": anns, "parents": parent_anns, "experimenters": exps} ) From d6e3c467aa6af5749ebbf1132631ba16134c0179 Mon Sep 17 00:00:00 2001 From: Tom-TBT Date: Thu, 16 Nov 2023 18:58:16 +0100 Subject: [PATCH 09/15] replaced lineage build with HQL --- omeroweb/webclient/tree.py | 111 ++++++++++++++++++++++++++++++++++++ omeroweb/webclient/views.py | 63 ++++++++++---------- 2 files changed, 140 insertions(+), 34 deletions(-) diff --git a/omeroweb/webclient/tree.py b/omeroweb/webclient/tree.py index 643dafaa69..654436e1be 100644 --- a/omeroweb/webclient/tree.py +++ b/omeroweb/webclient/tree.py @@ -24,6 +24,7 @@ import pytz import omero from builtins import bytes +from collections import defaultdict from omero.rtypes import rlong, unwrap, wrap from django.conf import settings @@ -2074,3 +2075,113 @@ def marshal_annotations( experimenters.sort(key=lambda x: x["id"]) return annotations, experimenters + + +def marshal_lineage(conn, + project_ids=None, + dataset_ids=None, + image_ids=None, + screen_ids=None, + plate_ids=None, + run_ids=None, + well_ids=None): + + def add_refs(ref_, dataset=None, project=None, well=None, + run=None, plate=None, screen=None): + def _add_refs(obj_type, obj_id): + if obj_id: + all_obj_ids[obj_type].add(obj_id) + lineage_d[obj_type][obj_id].append(ref_) + _add_refs("DatasetI", dataset) + _add_refs("ProjectI", project) + _add_refs("PlateAcquisitionI", run) + _add_refs("WellI", well) + _add_refs("PlateI", plate) + _add_refs("ScreenI", screen) + + def parse_hql_id(hql_ids): + return ("" if x is None else x.getValue() for x in hql_ids) + + requested = { + "ImageI": image_ids, + "DatasetI": dataset_ids, + "ProjectI": project_ids, + "PlateAcquisitionI": run_ids, + "WellI": well_ids, + "PlateI": plate_ids, + "ScreenI": screen_ids, + } + + child_ref_d = defaultdict(dict) # Children references dict + lineage_d, all_obj_ids = {}, {} # Result dictionnaries + for obj_type in ["ImageI", "DatasetI", "ProjectI", "PlateI", + "PlateAcquisitionI", "WellI", "ScreenI"]: + lineage_d[obj_type] = defaultdict(list) + all_obj_ids[obj_type] = set(requested[obj_type]) + + if len(requested[obj_type]) > 0: + for o in conn.getObjects(obj_type[:-1], requested[obj_type]): + details = {"id": o.getId(), + "class": obj_type} + if obj_type not in ["PlateAcquisitionI", "WellI"]: + details["name"] = o.getName() + child_ref_d[obj_type][details["id"]] = details + + service_opts = conn.SERVICE_OPTS.copy() + qs = conn.getQueryService() + hql_image = ("select img.id, dset.id, pdl.parent.id, smp.well.id," + " smp.plateAcquisition.id, plt.id, spl.parent.id" + " from Image img" + " left outer join img.datasetLinks dil" + " left outer join dil.parent dset" + " left outer join img.wellSamples smp" + " left outer join dset.projectLinks pdl" + " left outer join smp.well.plate plt" + " left outer join plt.screenLinks spl" + " where img.id in (:ids)") + + hql_wellrun = ("select child_o.id, plt.id, pdl.parent.id" + " from {} child_o" + " join child_o.plate plt" + " left outer join plt.screenLinks pdl" + " where child_o.id in (:ids)") + + hql_dsetplate = ("select child_o.id, opl.parent.id FROM {} child_o" + " left outer join child_o.{}Links opl " + " where child_o.id in (:ids)") + + if len(requested["ImageI"]) > 0: + params = omero.sys.ParametersI() + params.addIds(requested["ImageI"]) + for (im, ds, pr, + wl, rn, pl, sc) in map(parse_hql_id, + qs.projection(hql_image, + params, service_opts)): + ref_ = child_ref_d["ImageI"][im] + add_refs(ref_, ds, pr, wl, rn, pl, sc) + + for _type in ["WellI", "PlateAcquisitionI"]: + if len(requested[_type]) > 0: + params = omero.sys.ParametersI() + params.addIds(requested[_type]) + for ob, pl, sc in map(parse_hql_id, + qs.projection(hql_wellrun.format(_type[:-1]), + params, service_opts)): + ref_ = child_ref_d[_type][ob] + add_refs(ref_, plate=pl, screen=sc) + + for _type, parent_type in zip(["PlateI", "DatasetI"], + ["screen", "project"]): + if len(requested[_type]) > 0: + params = omero.sys.ParametersI() + params.addIds(requested[_type]) + for ob, p in map(parse_hql_id, + qs.projection(hql_dsetplate.format(_type[:-1], + parent_type), + params, service_opts)): + ref_ = child_ref_d[_type][ob] + if _type == "PlateI": + add_refs(ref_, screen=p) + else: + add_refs(ref_, project=p) + return lineage_d, all_obj_ids diff --git a/omeroweb/webclient/views.py b/omeroweb/webclient/views.py index 86bdc6f813..cfd0e60f5f 100755 --- a/omeroweb/webclient/views.py +++ b/omeroweb/webclient/views.py @@ -1366,12 +1366,9 @@ def api_annotations(request, conn=None, **kwargs): limit = get_long_or_default(request, "limit", ANNOTATIONS_LIMIT) ann_type = r.get("type", None) ns = r.get("ns", None) - with_parents = r.get("parents", "false") - with_parents = with_parents == "true" + with_parents = r.get("parents", "false") == "true" to_query = defaultdict(set) - lineage_d = defaultdict(lambda: defaultdict(list)) - requested = defaultdict(list) for type_ in ( "Image", "Dataset", @@ -1381,37 +1378,34 @@ def api_annotations(request, conn=None, **kwargs): "Plate", "Screen", ): + ids = get_list(request, type_.lower()) if type_ == "Acquisition": type_ = "PlateAcquisition" + # Important to cast to int to match marshal_lineage output + to_query[f"{type_}I"] = list(map(int, ids)) - for id_ in get_list(request, type_.lower()): - id_ = int(id_) - requested[type_].append(id_) - - obj = conn.getObject(type_, id_) - if not with_parents: - to_query[type_].add(id_) - continue - - details = {"id": id_, "class": type_ + "I", "name": obj.getName()} - if type_ in ["Well", "PlateAcquisition"]: - del details["name"] - - for p_type, p_ids in get_parentIds_recursive(obj).items(): - to_query[p_type].update(p_ids) - if p_type != type_: # Skip current object - for p_id in p_ids: - lineage_d[p_type][p_id].append(details) + if with_parents: + requested = to_query.copy() + lineage_d, to_query = tree.marshal_lineage( + conn, + project_ids=to_query["ProjectI"], + dataset_ids=to_query["DatasetI"], + image_ids=to_query["ImageI"], + screen_ids=to_query["ScreenI"], + plate_ids=to_query["PlateI"], + run_ids=to_query["PlateAcquisitionI"], + well_ids=to_query["WellI"], + ) all_anns, exps = tree.marshal_annotations( conn, - project_ids=to_query["Project"], - dataset_ids=to_query["Dataset"], - image_ids=to_query["Image"], - screen_ids=to_query["Screen"], - plate_ids=to_query["Plate"], - run_ids=to_query["PlateAcquisition"], - well_ids=to_query["Well"], + project_ids=to_query["ProjectI"], + dataset_ids=to_query["DatasetI"], + image_ids=to_query["ImageI"], + screen_ids=to_query["ScreenI"], + plate_ids=to_query["PlateI"], + run_ids=to_query["PlateAcquisitionI"], + well_ids=to_query["WellI"], ann_type=ann_type, ns=ns, page=page, @@ -1425,12 +1419,13 @@ def api_annotations(request, conn=None, **kwargs): for ann in all_anns: p = ann["link"]["parent"] pclass, pid = p["class"], p["id"] - if pid in requested[pclass[:-1]]: + if pid in requested[pclass]: anns.append(ann) - lineage_l = lineage_d[pclass[:-1]][pid] - if len(lineage_l) > 0: - parent_anns["annotations"].append(ann) - parent_anns["lineage"][pclass][pid] = lineage_l + if pclass != "ImageI": + lineage = lineage_d[pclass][pid] + if len(lineage) > 0: + parent_anns["annotations"].append(ann) + parent_anns["lineage"][pclass][pid] = lineage return JsonResponse( {"annotations": anns, "parents": parent_anns, "experimenters": exps} From a97f4d8f3ac14063dfb4ad14dd65e82126fe000f Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 16 Nov 2023 17:58:43 +0000 Subject: [PATCH 10/15] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- omeroweb/webclient/tree.py | 112 +++++++++++++++++++++---------------- 1 file changed, 64 insertions(+), 48 deletions(-) diff --git a/omeroweb/webclient/tree.py b/omeroweb/webclient/tree.py index 654436e1be..5a5157ef6d 100644 --- a/omeroweb/webclient/tree.py +++ b/omeroweb/webclient/tree.py @@ -2077,21 +2077,24 @@ def marshal_annotations( return annotations, experimenters -def marshal_lineage(conn, - project_ids=None, - dataset_ids=None, - image_ids=None, - screen_ids=None, - plate_ids=None, - run_ids=None, - well_ids=None): - - def add_refs(ref_, dataset=None, project=None, well=None, - run=None, plate=None, screen=None): +def marshal_lineage( + conn, + project_ids=None, + dataset_ids=None, + image_ids=None, + screen_ids=None, + plate_ids=None, + run_ids=None, + well_ids=None, +): + def add_refs( + ref_, dataset=None, project=None, well=None, run=None, plate=None, screen=None + ): def _add_refs(obj_type, obj_id): if obj_id: all_obj_ids[obj_type].add(obj_id) lineage_d[obj_type][obj_id].append(ref_) + _add_refs("DatasetI", dataset) _add_refs("ProjectI", project) _add_refs("PlateAcquisitionI", run) @@ -2114,49 +2117,60 @@ def parse_hql_id(hql_ids): child_ref_d = defaultdict(dict) # Children references dict lineage_d, all_obj_ids = {}, {} # Result dictionnaries - for obj_type in ["ImageI", "DatasetI", "ProjectI", "PlateI", - "PlateAcquisitionI", "WellI", "ScreenI"]: + for obj_type in [ + "ImageI", + "DatasetI", + "ProjectI", + "PlateI", + "PlateAcquisitionI", + "WellI", + "ScreenI", + ]: lineage_d[obj_type] = defaultdict(list) all_obj_ids[obj_type] = set(requested[obj_type]) if len(requested[obj_type]) > 0: for o in conn.getObjects(obj_type[:-1], requested[obj_type]): - details = {"id": o.getId(), - "class": obj_type} + details = {"id": o.getId(), "class": obj_type} if obj_type not in ["PlateAcquisitionI", "WellI"]: details["name"] = o.getName() child_ref_d[obj_type][details["id"]] = details service_opts = conn.SERVICE_OPTS.copy() qs = conn.getQueryService() - hql_image = ("select img.id, dset.id, pdl.parent.id, smp.well.id," - " smp.plateAcquisition.id, plt.id, spl.parent.id" - " from Image img" - " left outer join img.datasetLinks dil" - " left outer join dil.parent dset" - " left outer join img.wellSamples smp" - " left outer join dset.projectLinks pdl" - " left outer join smp.well.plate plt" - " left outer join plt.screenLinks spl" - " where img.id in (:ids)") - - hql_wellrun = ("select child_o.id, plt.id, pdl.parent.id" - " from {} child_o" - " join child_o.plate plt" - " left outer join plt.screenLinks pdl" - " where child_o.id in (:ids)") - - hql_dsetplate = ("select child_o.id, opl.parent.id FROM {} child_o" - " left outer join child_o.{}Links opl " - " where child_o.id in (:ids)") + hql_image = ( + "select img.id, dset.id, pdl.parent.id, smp.well.id," + " smp.plateAcquisition.id, plt.id, spl.parent.id" + " from Image img" + " left outer join img.datasetLinks dil" + " left outer join dil.parent dset" + " left outer join img.wellSamples smp" + " left outer join dset.projectLinks pdl" + " left outer join smp.well.plate plt" + " left outer join plt.screenLinks spl" + " where img.id in (:ids)" + ) + + hql_wellrun = ( + "select child_o.id, plt.id, pdl.parent.id" + " from {} child_o" + " join child_o.plate plt" + " left outer join plt.screenLinks pdl" + " where child_o.id in (:ids)" + ) + + hql_dsetplate = ( + "select child_o.id, opl.parent.id FROM {} child_o" + " left outer join child_o.{}Links opl " + " where child_o.id in (:ids)" + ) if len(requested["ImageI"]) > 0: params = omero.sys.ParametersI() params.addIds(requested["ImageI"]) - for (im, ds, pr, - wl, rn, pl, sc) in map(parse_hql_id, - qs.projection(hql_image, - params, service_opts)): + for im, ds, pr, wl, rn, pl, sc in map( + parse_hql_id, qs.projection(hql_image, params, service_opts) + ): ref_ = child_ref_d["ImageI"][im] add_refs(ref_, ds, pr, wl, rn, pl, sc) @@ -2164,21 +2178,23 @@ def parse_hql_id(hql_ids): if len(requested[_type]) > 0: params = omero.sys.ParametersI() params.addIds(requested[_type]) - for ob, pl, sc in map(parse_hql_id, - qs.projection(hql_wellrun.format(_type[:-1]), - params, service_opts)): + for ob, pl, sc in map( + parse_hql_id, + qs.projection(hql_wellrun.format(_type[:-1]), params, service_opts), + ): ref_ = child_ref_d[_type][ob] add_refs(ref_, plate=pl, screen=sc) - for _type, parent_type in zip(["PlateI", "DatasetI"], - ["screen", "project"]): + for _type, parent_type in zip(["PlateI", "DatasetI"], ["screen", "project"]): if len(requested[_type]) > 0: params = omero.sys.ParametersI() params.addIds(requested[_type]) - for ob, p in map(parse_hql_id, - qs.projection(hql_dsetplate.format(_type[:-1], - parent_type), - params, service_opts)): + for ob, p in map( + parse_hql_id, + qs.projection( + hql_dsetplate.format(_type[:-1], parent_type), params, service_opts + ), + ): ref_ = child_ref_d[_type][ob] if _type == "PlateI": add_refs(ref_, screen=p) From deb15bc81524ea11011e3e6fd3a511d822814972 Mon Sep 17 00:00:00 2001 From: Tom Boissonnet Date: Fri, 17 Nov 2023 19:00:17 +0100 Subject: [PATCH 11/15] Remove obsolete get_parentIds_recursive --- omeroweb/webclient/views.py | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/omeroweb/webclient/views.py b/omeroweb/webclient/views.py index cfd0e60f5f..66df4f078a 100755 --- a/omeroweb/webclient/views.py +++ b/omeroweb/webclient/views.py @@ -194,26 +194,6 @@ def validate_redirect_url(url): return url -def get_parentIds_recursive(obj): - """ - Goes recursively through the object parents list. - Returns a dictionary containing a list of parents Id - per type. - params: - - obj: if not in exisiting_d, add and iterate on parents - """ - d = defaultdict(set) - if obj.OMERO_CLASS == "WellSample": - d["PlateAcquisition"].add(int(obj.getPlateAcquisition().getId())) - obj = obj.getParent() # Jump right away to the Well - d[obj.OMERO_CLASS].add(int(obj.getId())) - - for parent in obj.listParents(): - for k, v in get_parentIds_recursive(parent).items(): - d[k].update(v) - return d - - ############################################################################## # custom index page From ccfeb7513d285c68280968d93aab1778605722e6 Mon Sep 17 00:00:00 2001 From: Tom-TBT Date: Mon, 4 Dec 2023 22:11:12 +0100 Subject: [PATCH 12/15] Marshal Run and Well name for annotation parents --- omeroweb/webclient/tree.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/omeroweb/webclient/tree.py b/omeroweb/webclient/tree.py index 5a5157ef6d..aaeb2f70ef 100644 --- a/omeroweb/webclient/tree.py +++ b/omeroweb/webclient/tree.py @@ -30,8 +30,7 @@ from django.conf import settings from datetime import datetime from copy import deepcopy -from omero.gateway import _letterGridLabel - +from omero.gateway import _letterGridLabel, _PlateWrapper logger = logging.getLogger(__name__) @@ -1908,8 +1907,17 @@ def _marshal_annotation(conn, annotation, link=None): "id": link.parent.id.val, "class": link.parent.__class__.__name__, } - if hasattr(link.parent, "name"): + if hasattr(link.parent, "name") and link.parent.name: ann["link"]["parent"]["name"] = unwrap(link.parent.name) + elif type(link.parent) is omero.model.PlateAcquisitionI: + # Name is optional for PlateAcquisition + ann["link"]["parent"]["name"] = f"Run {link.parent.id._val}" + elif type(link.parent) is omero.model.WellI: + # Well name constructed from plate + plate = _PlateWrapper(conn, link.parent.plate) + row = plate.getRowLabels()[link.parent.row._val] + col = plate.getColumnLabels()[link.parent.column._val] + ann["link"]["parent"]["name"] = f"{row}{col}" linkCreation = link.details.creationEvent._time ann["link"]["date"] = _marshal_date(unwrap(linkCreation)) p = link.details.permissions @@ -2053,11 +2061,12 @@ def marshal_annotations( left outer join fetch oal.child as ch left outer join fetch oal.parent as pa join fetch ch.details.creationEvent - join fetch ch.details.owner + join fetch ch.details.owner %s left outer join fetch ch.file as file where %s order by ch.ns """ % ( dtype, + "join fetch pa.plate" if dtype == "Well" else "", " and ".join(where_clause), ) From 3e38491a37855b8328d2790bfe221d4855861871 Mon Sep 17 00:00:00 2001 From: Tom-TBT Date: Thu, 7 Dec 2023 21:58:58 +0100 Subject: [PATCH 13/15] inherited annotation tooltips fix --- .../annotations/mapanns_underscore.html | 26 +++++++++---------- omeroweb/webclient/tree.py | 9 +++++-- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/omeroweb/webclient/templates/webclient/annotations/mapanns_underscore.html b/omeroweb/webclient/templates/webclient/annotations/mapanns_underscore.html index 3999bd5562..e16228a76d 100644 --- a/omeroweb/webclient/templates/webclient/annotations/mapanns_underscore.html +++ b/omeroweb/webclient/templates/webclient/annotations/mapanns_underscore.html @@ -37,16 +37,18 @@ <% } else if (objCount && objCount > 1) { %> diff --git a/omeroweb/webclient/tree.py b/omeroweb/webclient/tree.py index aaeb2f70ef..26f2de7e15 100644 --- a/omeroweb/webclient/tree.py +++ b/omeroweb/webclient/tree.py @@ -2141,8 +2141,13 @@ def parse_hql_id(hql_ids): if len(requested[obj_type]) > 0: for o in conn.getObjects(obj_type[:-1], requested[obj_type]): details = {"id": o.getId(), "class": obj_type} - if obj_type not in ["PlateAcquisitionI", "WellI"]: - details["name"] = o.getName() + if obj_type == "WellI": + name = o.getWellPos() + else: + name = o.getName() + if (obj_type == "PlateAcquisitionI" and name is None): + name = f"Run {o.getId()}" + details["name"] = name child_ref_d[obj_type][details["id"]] = details service_opts = conn.SERVICE_OPTS.copy() From fa713315ec50a8a1adc84bfd29fa47399ec39764 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 7 Dec 2023 21:00:17 +0000 Subject: [PATCH 14/15] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- omeroweb/webclient/tree.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omeroweb/webclient/tree.py b/omeroweb/webclient/tree.py index 26f2de7e15..8f6827acd4 100644 --- a/omeroweb/webclient/tree.py +++ b/omeroweb/webclient/tree.py @@ -2145,7 +2145,7 @@ def parse_hql_id(hql_ids): name = o.getWellPos() else: name = o.getName() - if (obj_type == "PlateAcquisitionI" and name is None): + if obj_type == "PlateAcquisitionI" and name is None: name = f"Run {o.getId()}" details["name"] = name child_ref_d[obj_type][details["id"]] = details From 231b2d01ca9164e5f67f5f71893fe1042ee318cf Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 15 Dec 2023 12:28:45 +0100 Subject: [PATCH 15/15] remove excess from inherited mapann tooltip --- .../annotations/mapanns_underscore.html | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/omeroweb/webclient/templates/webclient/annotations/mapanns_underscore.html b/omeroweb/webclient/templates/webclient/annotations/mapanns_underscore.html index e16228a76d..71f809b7aa 100644 --- a/omeroweb/webclient/templates/webclient/annotations/mapanns_underscore.html +++ b/omeroweb/webclient/templates/webclient/annotations/mapanns_underscore.html @@ -36,13 +36,6 @@ <% } %>