forked from ome/omego
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathauto_import_directory.py
executable file
·324 lines (285 loc) · 11.3 KB
/
auto_import_directory.py
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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
#!/usr/bin/env python
import getopt
import sys
import omero
import omero.cli
import os
import path
from omero.gateway import BlitzGateway
from omero.rtypes import wrap
from omero.model import DatasetI, ProjectI, ScreenI
from omero.util.import_candidates import as_dictionary
# This script is essentially for use in a very controlled situation
# ie standard omero passwords for a test situation.
host = "localhost"
root_user = "root"
root_passw = "omero"
user_passw = "ome"
class AutoImporter:
def __init__(self):
self.known_users = {}
self.orphans = "orphans"
self.screens = "screens"
self.no_projs = "no_projects"
self.no_dats = "no_datasets"
def new_connection(self, user, passw, host):
conn = BlitzGateway(user, passw, host=host)
conn.connect()
return conn
def use_connection(self, cli, host):
sessionId = cli._event_context.sessionUuid
conn = BlitzGateway(host=host)
conn.connect(sUuid = sessionId)
return conn
def get_params(self, conn=None):
params = omero.sys.Parameters()
params.theFilter = omero.sys.Filter()
if conn is not None:
params.theFilter.ownerId = wrap(conn.getUser().getId())
return params
def create_containers(self, cli, project, dataset):
"""
Creates containers with names provided if they don't exist already.
Returns Dataset ID.
"""
conn = self.use_connection(cli, host)
params = self.get_params(conn)
d = None
dsId = None
if project is not None:
# We need to find or create a project
# This is not nice but we really shouldn't be dealing with large numbers of objects here
plist = list(conn.getObjects("Project", attributes={'name': project}, params=params))
if len(plist) == 0:
# Create project and dataset then link
p = self.create_project(conn, project)
d = self.create_dataset(conn, dataset)
dsId = d.id.val
self.link_dataset(conn, p.id.val, dsId)
else:
# Pick the first, it's as good as any
p = plist[0]
print "Using existing Project:", project
# Since Project already exists check children for dataset
for c in p.listChildren():
if c.getName() == dataset:
d = c
dsId = d.getId()
# No existing child dataset so create one and link
if d is None:
d = self.create_dataset(conn, dataset)
dsId = d.id.val
self.link_dataset(conn, p.getId(), dsId)
else:
print "Using existing Dataset:", dataset
else:
# There may be more than one dataset with the same name
# This is not nice but we really shouldn't be dealing with large numbers of objects here
dlist = list(conn.getObjects("Dataset", attributes={'name': dataset}, params=params))
if len(dlist) != 0:
# We want one without a parent, the first will do
for c in dlist:
if len(c.listParents()) == 0:
d = c
dsId = d.getId()
if d is None:
dsId = self.create_dataset(conn, dataset).id.val
else:
print "Using existing Dataset:", dataset
return dsId
def create_project(self, conn, project):
print "Creating new Project:", project
p = ProjectI()
p.name = wrap(project.encode('ascii','ignore'))
return conn.getUpdateService().saveAndReturnObject(p)
def create_dataset(self, conn, dataset):
print "Creating new Dataset:", dataset
d = DatasetI()
d.name = wrap(dataset.encode('ascii','ignore'))
return conn.getUpdateService().saveAndReturnObject(d)
def link_dataset(self, conn, prId, dsId):
print "Linking Project and Dataset..."
link = omero.model.ProjectDatasetLinkI()
link.parent = ProjectI(prId, False)
link.child = DatasetI(dsId, False)
conn.getUpdateService().saveObject(link)
def create_screen(self, cli, screen):
"""
Creates screen with name provided if it doesn't exist already.
Returns Screen ID.
"""
conn = self.use_connection(cli, host)
params = self.get_params(conn)
slist = list(conn.getObjects("Screen", attributes={'name': screen}, params=params))
if len(slist) == 0:
print "Creating Screen:", screen
s = ScreenI()
s.name = wrap(screen.encode('ascii','ignore'))
scrId = conn.getUpdateService().saveAndReturnObject(s).id.val
else:
scrId = slist[0].getId()
print "Using Screen:", screen
return scrId
def user_exists(self, user):
if user in self.known_users.keys():
print "User:", user,
return True
try:
try:
conn = self.new_connection(root_user, root_passw, host)
params = self.get_params()
u = conn.getObject("Experimenter", attributes={'omeName': user}, params=params)
except Exception, e:
print e
print "Error getting user - ignoring."
return False
if u is None:
print "User:", user, "does not exist - ignoring."
return False
else:
print "User:", user,
self.known_users[user] = []
return True
finally:
try:
conn.seppuku()
except:
pass
def group_exists(self, user, group):
if not self.user_exists(user):
return False
else:
if group in self.known_users[user]:
print "in Group:", group
return True
try:
try:
conn = self.new_connection(user, user_passw, host)
groups = conn.getGroupsMemberOf()
except Exception, e:
print e
return False
if group in [g.name for g in groups]:
print "in Group:", group
self.known_users[user].append(group)
return True
else:
print "is not in Group:", group, "- ignoring."
return False
finally:
try:
conn.seppuku()
except:
pass
def do_import(self, user, group, project, dataset, archive, filename=None):
cli = omero.cli.CLI()
cli.loadplugins()
cli.invoke(["login", "%s@localhost" % user, "-w", "ome", "-C"], strict=True)
cli.invoke(["sessions", "group", group], strict=True)
import_args = ["import"]
if archive:
import_args.extend(["-a"])
if project == self.screens:
if dataset != self.orphans:
targetId = self.create_screen(cli, dataset)
import_args.extend(["-r", str(targetId)])
output = "Importing plate(s) into Screen:" + dataset
else:
output = "Importing plate(s) as an orphan"
else:
if project == self.no_projs:
targetId = self.create_containers(cli, None, dataset)
import_args.extend(["-d", str(targetId)])
output = "Importing image(s) into Dataset:" + dataset
elif dataset == self.no_dats:
self.create_containers(cli, project, None)
targetId = None
elif project != self.orphans and dataset != self.orphans:
targetId = self.create_containers(cli, project, dataset)
import_args.extend(["-d", str(targetId)])
output = "Importing image(s) into Project/Dataset:" + project+"/"+dataset
else:
output = "Importing image(s) as orphan(s)"
if filename is not None:
print output,
try:
import_args.append(filename)
print " ...using import args", import_args
cli.invoke(import_args, strict=True)
except:
print "Import failed!"
else:
print "No import, just container creation."
def auto_import(self, basepath, paths, no_imports, archive):
for filepath in paths:
parts = filepath.strip().split(os.sep)
# Skip commented out users - only relevant for file
if "#" in parts:
continue
# Ignore relative directory paths that do not adhere to:
# user/group/project/dataset
# This guarantees a target but doesn't process more
# deeply nested directories and so avoids double imports.
if len(parts) != 4:
#print "Ignoring ", filepath # Not that useful in general.
continue
print "="*100
print "Processing ", filepath
# Users must exist and they must be in an already existing group.
user = parts[0]
group = parts[1]
if not self.group_exists(user, group):
continue
if no_imports:
filepath = None
else:
print "-"*100
print "Getting import canditates..."
# If separate imports or further logging are required could use import_candidates.
filepath = basepath.joinpath(filepath)
import_candidates = as_dictionary([filepath])
if len(import_candidates) == 0:
print "Nothing to import, path contains no import candidates."
# Create P/D or S anyway.
filepath = None
print "-"*100
# Finally we can import something creating containers as we go.
self.do_import(user, group, parts[2], parts[3], archive, filepath)
print "="*100
if __name__ == '__main__':
try:
opts, args = getopt.getopt(sys.argv[1:], "fna", ["file", "no_import", "archive"])
except getopt.GetoptError as err:
sys.exit(str(err))
source = args[0]
use_file = False
no_imports = False
archive = False
for o, a in opts:
if o in ("-f", "--file"):
use_file = True
elif o in ("-n", "--no_import"):
no_imports = True
elif o in ("-a", "--archive"):
archive = True
if use_file:
if not os.path.exists(source):
sys.exit('ERROR: File %s was not found!' % source)
no_imports = True
try:
f = open(source, "r")
filepaths = f.read()
f.close()
paths = [p for p in filepaths.split("\n")]
basepath = None
except:
sys.exit('ERROR: Problem accessing file %s' % source)
else:
if not os.path.exists(source):
sys.exit('ERROR: Directory %s was not found!' % source)
basepath = path.path(source).abspath()
paths = list(basepath.walkdirs())
for i in range(len(paths)):
paths[i] = str(basepath.relpathto(paths[i]))
ai = AutoImporter()
ai.auto_import(basepath, paths, no_imports, archive)