-
Notifications
You must be signed in to change notification settings - Fork 39
Expand file tree
/
Copy pathapi_query.py
More file actions
151 lines (127 loc) · 5.12 KB
/
api_query.py
File metadata and controls
151 lines (127 loc) · 5.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (C) 2016 University of Dundee & Open Microscopy Environment.
# All rights reserved.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""Helper functions for views that handle object trees."""
from omero.rtypes import unwrap, wrap, rlong
from omero.sys import ParametersI
from . import api_settings
from .api_marshal import marshal_objects
from copy import deepcopy
MAX_LIMIT = max(1, api_settings.API_MAX_LIMIT)
DEFAULT_LIMIT = max(1, api_settings.API_LIMIT)
def get_wellsample_indices(conn, plate_id=None, plateacquisition_id=None):
"""
Return min and max WellSample index for a Plate OR PlateAcquisition
@param conn: BlitzGateway
@param plate_id: Plate ID
@param plateacquisition_id: PlateAcquisition ID
@return A dict of parent_id: child_count
"""
ctx = deepcopy(conn.SERVICE_OPTS)
ctx.setOmeroGroup(-1)
params = ParametersI()
query = (
"select minIndex(ws), maxIndex(ws) from Well well " "join well.wellSamples ws"
)
if plate_id is not None:
query += " where well.plate.id=:plate_id "
params.add("plate_id", rlong(plate_id))
elif plateacquisition_id is not None:
query += " where ws.plateAcquisition.id=:plateacquisition_id"
params.add("plateacquisition_id", rlong(plateacquisition_id))
result = conn.getQueryService().projection(query, params, ctx)
result = [r for r in unwrap(result)[0] if r is not None]
return result
def get_child_counts(conn, link_class, parent_ids):
"""
Count child links for the specified parent_ids.
@param conn: BlitzGateway
@param link_class: Type of link, e.g. 'ProjectDatasetLink'
@param parent_ids: List of Parent IDs
@return A dict of parent_id: child_count
"""
counts = {}
if len(parent_ids) == 0:
return counts
ctx = deepcopy(conn.SERVICE_OPTS)
ctx.setOmeroGroup(-1)
params = ParametersI()
params.add("ids", wrap([rlong(id) for id in parent_ids]))
query = (
"select chl.parent.id, count(chl.id) from %s chl"
" where chl.parent.id in (:ids) group by chl.parent.id" % link_class
)
result = conn.getQueryService().projection(query, params, ctx)
for d in result:
counts[d[0].val] = unwrap(d[1])
return counts
def validate_opts(opts):
"""Check that opts dict has valid 'limit' and 'offset'."""
if opts is None:
opts = {}
if opts.get("limit") is None or opts.get("limit") < 0:
opts["limit"] = DEFAULT_LIMIT
opts["limit"] = min(opts["limit"], MAX_LIMIT)
if opts.get("offset") is None or opts.get("offset") < 0:
opts["offset"] = 0
return opts
def query_objects(conn, object_type, group=None, opts=None, normalize=False):
"""
Base query method, handles different object_types.
Builds a query and adds common
parameters and filters such as by owner or group.
@param conn: BlitzGateway
@param object_type: Type to query, e.g. Project
@param group: Filter query by ExperimenterGroup ID
@param opts: Options dict for conn.buildQuery()
@param normalize: If true, marshal groups and experimenters separately
"""
opts = validate_opts(opts)
# buildQuery is used by conn.getObjects()
query, params, wrapper = conn.buildQuery(object_type, opts=opts)
# Set the desired group context
ctx = deepcopy(conn.SERVICE_OPTS)
if group is None:
group = -1
ctx.setOmeroGroup(group)
qs = conn.getQueryService()
objects = []
extras = {}
if opts["limit"] == 0:
result = []
else:
result = qs.findAllByQuery(query, params, ctx)
for obj in result:
objects.append(obj)
# Optionally get child counts...
if opts and opts.get("child_count") and wrapper.LINK_CLASS:
obj_ids = [r.id.val for r in result]
counts = get_child_counts(conn, wrapper.LINK_CLASS, obj_ids)
for obj_id in obj_ids:
count = counts[obj_id] if obj_id in counts else 0
extras[obj_id] = {"omero:childCount": count}
# Query the count() of objects & add to 'meta' dict
count_query, params = conn.buildCountQuery(object_type, opts=opts)
result = qs.projection(count_query, params, ctx)
meta = {}
meta["offset"] = opts["offset"]
meta["limit"] = opts["limit"]
meta["maxLimit"] = MAX_LIMIT
meta["totalCount"] = result[0][0].val
marshalled = marshal_objects(objects, extras=extras, normalize=normalize)
marshalled["meta"] = meta
return marshalled