hrm_omero.transfer
Transfer related functions.
1"""Transfer related functions.""" 2 3import os 4import tempfile 5from io import BytesIO 6from pathlib import Path 7import stat 8 9from loguru import logger as log 10from PIL import Image 11 12from . import hrm 13from .decorators import connect_and_set_group 14from .omero import extract_image_id, add_annotation_keyvalue 15from .misc import printlog, changemodes 16 17 18@connect_and_set_group 19def from_omero(conn, omero_id, dest): 20 """Download the corresponding original file(s) from an image ID. 21 22 This only works for image IDs that were created with OMERO 5.0 or later as previous 23 versions don't have an "original file" linked to an image. 24 25 Note that files will be downloaded with their original name, which is not 26 necessarily the name shown by OMERO, e.g. if an image name was changed in OMERO. To 27 keep filesets consistent, we have to preserve the original names! 28 29 In addition to the original file(s), it also downloads a thumbnail of the requested 30 file from OMERO and puts it into the appropriate place so HRM will show it as a 31 preview until the user hits "re-generate preview". 32 33 Parameters 34 ---------- 35 conn : omero.gateway.BlitzGateway 36 The OMERO connection object. 37 omero_id : hrm_omero.misc.OmeroId 38 The ID of the OMERO image to be downloaded. 39 dest : str 40 The destination path. 41 42 Returns 43 ------- 44 bool 45 True in case the download was successful, False otherwise. 46 47 Raises 48 ------ 49 ValueError 50 Raised in case an object that is not of type `Image` was requested. 51 """ 52 log.trace(f"Downloading {omero_id.obj_type}:{omero_id.obj_id} to [{dest}]...") 53 54 # conn.setGroupForSession(-1) 55 conn.SERVICE_OPTS.setOmeroGroup(-1) # still working with OMERO-5.6.3 56 if omero_id.obj_type != "Image": 57 raise ValueError("Currently only the download of 'Image' objects is supported!") 58 59 # check if dest is a directory, rewrite it otherwise: 60 if not os.path.isdir(dest): 61 # FIXME: this should raise a ValueError as it's quite counter-intuitive that 62 # specifying a file *name* for the target doesn't have an effect on how the 63 # downloaded file will be called actually! 64 dest = os.path.dirname(dest) 65 from omero_model_OriginalFileI import OriginalFileI 66 67 # use image objects and getFileset() methods to determine original files, 68 # see the following OME forum thread for some more details: 69 # https://www.openmicroscopy.org/community/viewtopic.php?f=6&t=7563 70 target_obj = conn.getObject(omero_id.obj_type, omero_id.obj_id) 71 if not target_obj: 72 printlog("ERROR", f"ERROR: can't find image with ID [{omero_id.obj_id}]!") 73 return False 74 75 fset = target_obj.getFileset() 76 if not fset: # pragma: no cover 77 printlog("ERROR", f"ERROR: no original file(s) for [{omero_id.obj_id}] found!") 78 return False 79 80 # NOTE: the idea of offering to download the OME-TIFF from OMERO (i.e. the converted 81 # data) as an alternative has been discarded for the moment - see upstream HRM 82 # ticket #398 (http://hrm.svi.nl:8080/redmine/issues/398) 83 downloads = [] 84 # assemble a list of items to download 85 for fset_file in fset.listFiles(): 86 # for foo in dir(fset_file): 87 # log.error(foo) 88 file_name = fset_file.getName() 89 file_path = fset_file.getPath() 90 downloads.append((fset_file.getId(), os.path.join(file_path, file_name))) 91 92 # determine the common prefix, e.g. `hrm-test-02_3/2022-02/17/14-34-16.480/` 93 all_files = [x[1] for x in downloads] 94 strip = os.path.commonprefix(all_files).rindex("/") + 1 95 96 # strip the common prefix, check if any of the files already exist: 97 top_level = [] 98 for i, pair in enumerate(downloads): 99 rel_path = pair[1][strip:] 100 log.trace(f"relative path: {rel_path}") 101 top_level.append(rel_path.split("/")[0]) 102 abs_path = os.path.join(dest, rel_path) 103 downloads[i] = (pair[0], abs_path) 104 if os.path.exists(abs_path): 105 printlog("ERROR", f"ERROR: file '{abs_path}' already existing!") 106 return False 107 108 # now initiate the downloads for all original files: 109 for (file_id, tgt) in downloads: 110 try: 111 log.trace(f"Downloading original file [{file_id}] to [{tgt}]...") 112 os.makedirs(os.path.dirname(tgt), exist_ok=True) 113 conn.c.download(OriginalFileI(file_id), tgt) 114 except Exception as err: # pylint: disable-msg=broad-except 115 printlog("ERROR", f"ERROR: downloading {file_id} to '{tgt}' failed: {err}") 116 return False 117 printlog("SUCCESS", f"ID {file_id} downloaded as '{os.path.basename(tgt)}'") 118 119 changemodes(dest, top_level) 120 121 # NOTE: for filesets with a single file or e.g. ICS/IDS pairs it makes 122 # sense to use the target name of the first file to construct the name for 123 # the thumbnail, but it is unclear whether this is a universal approach: 124 fetch_thumbnail(conn, omero_id, downloads[0][1]) 125 return True 126 127 128def fetch_thumbnail(conn, omero_id, dest): 129 """Download the thumbnail of a given image from OMERO. 130 131 OMERO provides thumbnails for stored images, this function downloads the thumbnail 132 image and places it as preview in the corresponding HRM directory. 133 134 Parameters 135 ---------- 136 conn : omero.gateway.BlitzGateway 137 The OMERO connection object. 138 omero_id : hrm_omero.misc.OmeroId 139 The ID of the OMERO image to fetch the thumbnail for. 140 dest : str 141 The destination filename. 142 143 Returns 144 ------- 145 bool 146 True in case the download was successful, False otherwise. 147 """ 148 ##### WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING ##### 149 # 150 # do NOT decorate this function using `@connect_and_set_group`, see the 151 # explanation in the decorator definition for more details 152 # 153 ##### WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING ##### 154 log.info(f"Trying to fetch thumbnail for OMERO image [{omero_id.obj_id}]...") 155 log.trace(f"Requested target location: [{dest}].") 156 157 base_dir, fname = os.path.split(dest) 158 target_dir = Path(base_dir) / "hrm_previews" 159 target = Path(target_dir) / f"{fname}.preview_xy.jpg" 160 161 image_obj = conn.getObject("Image", omero_id.obj_id) 162 image_data = image_obj.getThumbnail() 163 log.trace(f"len(image_data)={len(image_data)}") 164 thumbnail = Image.open(BytesIO(image_data)) 165 try: 166 target_dir.mkdir(parents=True, exist_ok=True) 167 # TODO: consider using `misc.changemodes()` 168 # for an unkown reason using mode=(S_IRWXU | S_IRWXG) on the `mkdir()` call 169 # doesn't seem to work, so we have to add group-write in a second step: 170 target_dir.chmod(target_dir.stat().st_mode | stat.S_IWGRP) 171 thumbnail.save(target.as_posix(), format="jpeg") 172 printlog("SUCCESS", f"Thumbnail downloaded to '{target}'.") 173 target.chmod(target.stat().st_mode | stat.S_IWGRP) 174 log.success(f"Added group-write permissions to '{target}'.") 175 except Exception as err: # pylint: disable-msg=broad-except 176 printlog("ERROR", f"ERROR downloading thumbnail to '{target}': {err}") 177 return False 178 179 return True 180 181 182@connect_and_set_group 183def to_omero(conn, omero_id, image_file, omero_logfile="", _fetch_zip_only=False): 184 """Upload an image into a specific dataset in OMERO. 185 186 In case we know from the suffix that a given format is not supported by OMERO, the 187 upload will not be initiated at all (e.g. for SVI-HDF5, having the suffix '.h5'). 188 189 The import itself is done by instantiating the CLI class, assembling the required 190 arguments, and finally running `cli.invoke()`. This eventually triggers the 191 `importer()` method defined in [OMERO's Python bindings][1]. 192 193 [1]: https://github.com/ome/omero-py/blob/master/src/omero/plugins/import.py 194 195 Parameters 196 ---------- 197 conn : omero.gateway.BlitzGateway 198 The OMERO connection object. 199 omero_id : hrm_omero.misc.OmeroId 200 The ID of the target dataset in OMERO. 201 image_file : str 202 The local image file including the full path. 203 omero_logfile : str, optional 204 The prefix of files to be used to capture OMERO's `import` call stderr messages. 205 If the parameter is non-empty the `--debug ALL` option will be added to the 206 `omero` call with the output being placed in the specified file. If the 207 parameter is omitted or empty, debug messages will be disabled. 208 _fetch_zip_only : bool, optional 209 Replaces all parameters to the import call by `--advanced-help`, which is 210 **intended for INTERNAL TESTING ONLY**. No actual import will be attempted! 211 212 Returns 213 ------- 214 bool 215 True in case of success, False otherwise. 216 217 Raises 218 ------ 219 TypeError 220 Raised in case `image_file` is in a format that is not supported by OMERO. 221 ValueError 222 Raised in case `omero_id` is not pointing to a dataset. 223 """ 224 225 # TODO: revisit this, as e.g. BDV .h5 files are supported for now! 226 if image_file.lower().endswith((".h5", ".hdf5")): 227 msg = f"ERROR importing [{image_file}]: HDF5 format not supported by OMERO!" 228 printlog("ERROR", msg) 229 raise TypeError(msg) 230 231 if omero_id.obj_type != "Dataset": 232 msg = "Currently only the upload to 'Dataset' objects is supported!" 233 printlog("ERROR", msg) 234 raise ValueError(msg) 235 236 # we have to create the annotations *before* we actually upload the image 237 # data itself and link them to the image during the upload - the other way 238 # round is not possible right now as the CLI wrapper (see below) doesn't 239 # expose the ID of the newly created object in OMERO (confirmed by J-M and 240 # Sebastien on the 2015 OME Meeting): 241 #### namespace = "deconvolved.hrm" 242 #### mime = 'text/plain' 243 #### annotations = [] 244 #### # TODO: the list of suffixes should not be hardcoded here! 245 #### for suffix in ['.hgsb', '.log.txt', '.parameters.txt']: 246 #### if not os.path.exists(basename + suffix): 247 #### continue 248 #### ann = conn.createFileAnnfromLocalFile( 249 #### basename + suffix, mimetype=mime, ns=namespace, desc=None) 250 #### annotations.append(ann.getId()) 251 252 # currently there is no direct "Python way" to import data into OMERO, so we have to 253 # use the CLI wrapper for this... 254 # TODO: check the more recent code mentioned by the OME developers in the forum 255 # thread: https://forum.image.sc/t/automated-uploader-to-omero-in-python/38290 256 # https://gitlab.com/openmicroscopy/incubator/omero-python-importer/-/blob/master/import.py) 257 # and also see https://pypi.org/project/omero-upload/ 258 from omero.cli import CLI 259 260 cli = CLI() 261 cli.loadplugins() 262 cli.set_client(conn.c) 263 import_args = ["import"] 264 265 # disable upgrade checks (https://forum.image.sc/t/unable-to-use-cli-importer/26424) 266 import_args.extend(["--skip", "upgrade"]) 267 268 if omero_logfile: 269 log.warning(f"Messages (stderr) from import will go to [{omero_logfile}].") 270 import_args.extend(["--debug", "ALL"]) 271 import_args.extend(["--errs", omero_logfile]) 272 273 import_args.extend(["-d", omero_id.obj_id]) 274 275 # capture stdout and request YAML format to parse the output later on: 276 tempdir = tempfile.TemporaryDirectory(prefix="hrm-omero__") 277 cap_stdout = f"{tempdir.name}/omero-import-stdout" 278 log.debug(f"Capturing stdout of the 'omero' call into [{cap_stdout}]...") 279 import_args.extend(["--file", cap_stdout]) 280 import_args.extend(["--output", "yaml"]) 281 282 #### for ann_id in annotations: 283 #### import_args.extend(['--annotation_link', str(ann_id)]) 284 import_args.append(image_file) 285 if _fetch_zip_only: 286 # calling 'import --advanced-help' will trigger the download of OMERO.java.zip 287 # in case it is not yet present (the extract_image_id() call will then fail, 288 # resulting in the whole function returning "False") 289 printlog("WARNING", "As '_fetch_zip_only' is set NO IMPORT WILL BE ATTEMPTED!") 290 import_args = ["import", "--advanced-help"] 291 log.debug(f"import_args: {import_args}") 292 try: 293 cli.invoke(import_args, strict=True) 294 imported_id = extract_image_id(cap_stdout) 295 log.success(f"Imported OMERO image ID: {imported_id}") 296 except PermissionError as err: 297 printlog("ERROR", err) 298 omero_userdir = os.environ.get("OMERO_USERDIR", "<not-set>") 299 printlog("ERROR", f"Current OMERO_USERDIR value: {omero_userdir}") 300 printlog( 301 "ERROR", 302 ( 303 "Please make sure to read the documentation about the 'OMERO_USERDIR' " 304 "environment variable and also check if the file to be imported has " 305 "appropriate permissions!" 306 ), 307 ) 308 return False 309 except Exception as err: # pylint: disable-msg=broad-except 310 printlog("ERROR", f"ERROR: uploading '{image_file}' to {omero_id} failed!") 311 printlog("ERROR", f"OMERO error message: >>>{err}<<<") 312 printlog("WARNING", f"import_args: {import_args}") 313 return False 314 finally: 315 tempdir.cleanup() 316 317 target_id = f"G:{omero_id.group}:Image:{imported_id}" 318 try: 319 summary = hrm.parse_summary(image_file) 320 add_annotation_keyvalue(conn, target_id, summary) 321 except Exception as err: # pragma: no cover # pylint: disable-msg=broad-except 322 log.error(f"Creating a parameter summary from [{image_file}] failed: {err}") 323 324 return True
19@connect_and_set_group 20def from_omero(conn, omero_id, dest): 21 """Download the corresponding original file(s) from an image ID. 22 23 This only works for image IDs that were created with OMERO 5.0 or later as previous 24 versions don't have an "original file" linked to an image. 25 26 Note that files will be downloaded with their original name, which is not 27 necessarily the name shown by OMERO, e.g. if an image name was changed in OMERO. To 28 keep filesets consistent, we have to preserve the original names! 29 30 In addition to the original file(s), it also downloads a thumbnail of the requested 31 file from OMERO and puts it into the appropriate place so HRM will show it as a 32 preview until the user hits "re-generate preview". 33 34 Parameters 35 ---------- 36 conn : omero.gateway.BlitzGateway 37 The OMERO connection object. 38 omero_id : hrm_omero.misc.OmeroId 39 The ID of the OMERO image to be downloaded. 40 dest : str 41 The destination path. 42 43 Returns 44 ------- 45 bool 46 True in case the download was successful, False otherwise. 47 48 Raises 49 ------ 50 ValueError 51 Raised in case an object that is not of type `Image` was requested. 52 """ 53 log.trace(f"Downloading {omero_id.obj_type}:{omero_id.obj_id} to [{dest}]...") 54 55 # conn.setGroupForSession(-1) 56 conn.SERVICE_OPTS.setOmeroGroup(-1) # still working with OMERO-5.6.3 57 if omero_id.obj_type != "Image": 58 raise ValueError("Currently only the download of 'Image' objects is supported!") 59 60 # check if dest is a directory, rewrite it otherwise: 61 if not os.path.isdir(dest): 62 # FIXME: this should raise a ValueError as it's quite counter-intuitive that 63 # specifying a file *name* for the target doesn't have an effect on how the 64 # downloaded file will be called actually! 65 dest = os.path.dirname(dest) 66 from omero_model_OriginalFileI import OriginalFileI 67 68 # use image objects and getFileset() methods to determine original files, 69 # see the following OME forum thread for some more details: 70 # https://www.openmicroscopy.org/community/viewtopic.php?f=6&t=7563 71 target_obj = conn.getObject(omero_id.obj_type, omero_id.obj_id) 72 if not target_obj: 73 printlog("ERROR", f"ERROR: can't find image with ID [{omero_id.obj_id}]!") 74 return False 75 76 fset = target_obj.getFileset() 77 if not fset: # pragma: no cover 78 printlog("ERROR", f"ERROR: no original file(s) for [{omero_id.obj_id}] found!") 79 return False 80 81 # NOTE: the idea of offering to download the OME-TIFF from OMERO (i.e. the converted 82 # data) as an alternative has been discarded for the moment - see upstream HRM 83 # ticket #398 (http://hrm.svi.nl:8080/redmine/issues/398) 84 downloads = [] 85 # assemble a list of items to download 86 for fset_file in fset.listFiles(): 87 # for foo in dir(fset_file): 88 # log.error(foo) 89 file_name = fset_file.getName() 90 file_path = fset_file.getPath() 91 downloads.append((fset_file.getId(), os.path.join(file_path, file_name))) 92 93 # determine the common prefix, e.g. `hrm-test-02_3/2022-02/17/14-34-16.480/` 94 all_files = [x[1] for x in downloads] 95 strip = os.path.commonprefix(all_files).rindex("/") + 1 96 97 # strip the common prefix, check if any of the files already exist: 98 top_level = [] 99 for i, pair in enumerate(downloads): 100 rel_path = pair[1][strip:] 101 log.trace(f"relative path: {rel_path}") 102 top_level.append(rel_path.split("/")[0]) 103 abs_path = os.path.join(dest, rel_path) 104 downloads[i] = (pair[0], abs_path) 105 if os.path.exists(abs_path): 106 printlog("ERROR", f"ERROR: file '{abs_path}' already existing!") 107 return False 108 109 # now initiate the downloads for all original files: 110 for (file_id, tgt) in downloads: 111 try: 112 log.trace(f"Downloading original file [{file_id}] to [{tgt}]...") 113 os.makedirs(os.path.dirname(tgt), exist_ok=True) 114 conn.c.download(OriginalFileI(file_id), tgt) 115 except Exception as err: # pylint: disable-msg=broad-except 116 printlog("ERROR", f"ERROR: downloading {file_id} to '{tgt}' failed: {err}") 117 return False 118 printlog("SUCCESS", f"ID {file_id} downloaded as '{os.path.basename(tgt)}'") 119 120 changemodes(dest, top_level) 121 122 # NOTE: for filesets with a single file or e.g. ICS/IDS pairs it makes 123 # sense to use the target name of the first file to construct the name for 124 # the thumbnail, but it is unclear whether this is a universal approach: 125 fetch_thumbnail(conn, omero_id, downloads[0][1]) 126 return True
Download the corresponding original file(s) from an image ID.
This only works for image IDs that were created with OMERO 5.0 or later as previous versions don't have an "original file" linked to an image.
Note that files will be downloaded with their original name, which is not necessarily the name shown by OMERO, e.g. if an image name was changed in OMERO. To keep filesets consistent, we have to preserve the original names!
In addition to the original file(s), it also downloads a thumbnail of the requested file from OMERO and puts it into the appropriate place so HRM will show it as a preview until the user hits "re-generate preview".
Parameters
- conn (omero.gateway.BlitzGateway): The OMERO connection object.
- omero_id (hrm_omero.misc.OmeroId): The ID of the OMERO image to be downloaded.
- dest (str): The destination path.
Returns
- bool: True in case the download was successful, False otherwise.
Raises
- ValueError: Raised in case an object that is not of type
Image
was requested.
129def fetch_thumbnail(conn, omero_id, dest): 130 """Download the thumbnail of a given image from OMERO. 131 132 OMERO provides thumbnails for stored images, this function downloads the thumbnail 133 image and places it as preview in the corresponding HRM directory. 134 135 Parameters 136 ---------- 137 conn : omero.gateway.BlitzGateway 138 The OMERO connection object. 139 omero_id : hrm_omero.misc.OmeroId 140 The ID of the OMERO image to fetch the thumbnail for. 141 dest : str 142 The destination filename. 143 144 Returns 145 ------- 146 bool 147 True in case the download was successful, False otherwise. 148 """ 149 ##### WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING ##### 150 # 151 # do NOT decorate this function using `@connect_and_set_group`, see the 152 # explanation in the decorator definition for more details 153 # 154 ##### WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING ##### 155 log.info(f"Trying to fetch thumbnail for OMERO image [{omero_id.obj_id}]...") 156 log.trace(f"Requested target location: [{dest}].") 157 158 base_dir, fname = os.path.split(dest) 159 target_dir = Path(base_dir) / "hrm_previews" 160 target = Path(target_dir) / f"{fname}.preview_xy.jpg" 161 162 image_obj = conn.getObject("Image", omero_id.obj_id) 163 image_data = image_obj.getThumbnail() 164 log.trace(f"len(image_data)={len(image_data)}") 165 thumbnail = Image.open(BytesIO(image_data)) 166 try: 167 target_dir.mkdir(parents=True, exist_ok=True) 168 # TODO: consider using `misc.changemodes()` 169 # for an unkown reason using mode=(S_IRWXU | S_IRWXG) on the `mkdir()` call 170 # doesn't seem to work, so we have to add group-write in a second step: 171 target_dir.chmod(target_dir.stat().st_mode | stat.S_IWGRP) 172 thumbnail.save(target.as_posix(), format="jpeg") 173 printlog("SUCCESS", f"Thumbnail downloaded to '{target}'.") 174 target.chmod(target.stat().st_mode | stat.S_IWGRP) 175 log.success(f"Added group-write permissions to '{target}'.") 176 except Exception as err: # pylint: disable-msg=broad-except 177 printlog("ERROR", f"ERROR downloading thumbnail to '{target}': {err}") 178 return False 179 180 return True
Download the thumbnail of a given image from OMERO.
OMERO provides thumbnails for stored images, this function downloads the thumbnail image and places it as preview in the corresponding HRM directory.
Parameters
- conn (omero.gateway.BlitzGateway): The OMERO connection object.
- omero_id (hrm_omero.misc.OmeroId): The ID of the OMERO image to fetch the thumbnail for.
- dest (str): The destination filename.
Returns
- bool: True in case the download was successful, False otherwise.
183@connect_and_set_group 184def to_omero(conn, omero_id, image_file, omero_logfile="", _fetch_zip_only=False): 185 """Upload an image into a specific dataset in OMERO. 186 187 In case we know from the suffix that a given format is not supported by OMERO, the 188 upload will not be initiated at all (e.g. for SVI-HDF5, having the suffix '.h5'). 189 190 The import itself is done by instantiating the CLI class, assembling the required 191 arguments, and finally running `cli.invoke()`. This eventually triggers the 192 `importer()` method defined in [OMERO's Python bindings][1]. 193 194 [1]: https://github.com/ome/omero-py/blob/master/src/omero/plugins/import.py 195 196 Parameters 197 ---------- 198 conn : omero.gateway.BlitzGateway 199 The OMERO connection object. 200 omero_id : hrm_omero.misc.OmeroId 201 The ID of the target dataset in OMERO. 202 image_file : str 203 The local image file including the full path. 204 omero_logfile : str, optional 205 The prefix of files to be used to capture OMERO's `import` call stderr messages. 206 If the parameter is non-empty the `--debug ALL` option will be added to the 207 `omero` call with the output being placed in the specified file. If the 208 parameter is omitted or empty, debug messages will be disabled. 209 _fetch_zip_only : bool, optional 210 Replaces all parameters to the import call by `--advanced-help`, which is 211 **intended for INTERNAL TESTING ONLY**. No actual import will be attempted! 212 213 Returns 214 ------- 215 bool 216 True in case of success, False otherwise. 217 218 Raises 219 ------ 220 TypeError 221 Raised in case `image_file` is in a format that is not supported by OMERO. 222 ValueError 223 Raised in case `omero_id` is not pointing to a dataset. 224 """ 225 226 # TODO: revisit this, as e.g. BDV .h5 files are supported for now! 227 if image_file.lower().endswith((".h5", ".hdf5")): 228 msg = f"ERROR importing [{image_file}]: HDF5 format not supported by OMERO!" 229 printlog("ERROR", msg) 230 raise TypeError(msg) 231 232 if omero_id.obj_type != "Dataset": 233 msg = "Currently only the upload to 'Dataset' objects is supported!" 234 printlog("ERROR", msg) 235 raise ValueError(msg) 236 237 # we have to create the annotations *before* we actually upload the image 238 # data itself and link them to the image during the upload - the other way 239 # round is not possible right now as the CLI wrapper (see below) doesn't 240 # expose the ID of the newly created object in OMERO (confirmed by J-M and 241 # Sebastien on the 2015 OME Meeting): 242 #### namespace = "deconvolved.hrm" 243 #### mime = 'text/plain' 244 #### annotations = [] 245 #### # TODO: the list of suffixes should not be hardcoded here! 246 #### for suffix in ['.hgsb', '.log.txt', '.parameters.txt']: 247 #### if not os.path.exists(basename + suffix): 248 #### continue 249 #### ann = conn.createFileAnnfromLocalFile( 250 #### basename + suffix, mimetype=mime, ns=namespace, desc=None) 251 #### annotations.append(ann.getId()) 252 253 # currently there is no direct "Python way" to import data into OMERO, so we have to 254 # use the CLI wrapper for this... 255 # TODO: check the more recent code mentioned by the OME developers in the forum 256 # thread: https://forum.image.sc/t/automated-uploader-to-omero-in-python/38290 257 # https://gitlab.com/openmicroscopy/incubator/omero-python-importer/-/blob/master/import.py) 258 # and also see https://pypi.org/project/omero-upload/ 259 from omero.cli import CLI 260 261 cli = CLI() 262 cli.loadplugins() 263 cli.set_client(conn.c) 264 import_args = ["import"] 265 266 # disable upgrade checks (https://forum.image.sc/t/unable-to-use-cli-importer/26424) 267 import_args.extend(["--skip", "upgrade"]) 268 269 if omero_logfile: 270 log.warning(f"Messages (stderr) from import will go to [{omero_logfile}].") 271 import_args.extend(["--debug", "ALL"]) 272 import_args.extend(["--errs", omero_logfile]) 273 274 import_args.extend(["-d", omero_id.obj_id]) 275 276 # capture stdout and request YAML format to parse the output later on: 277 tempdir = tempfile.TemporaryDirectory(prefix="hrm-omero__") 278 cap_stdout = f"{tempdir.name}/omero-import-stdout" 279 log.debug(f"Capturing stdout of the 'omero' call into [{cap_stdout}]...") 280 import_args.extend(["--file", cap_stdout]) 281 import_args.extend(["--output", "yaml"]) 282 283 #### for ann_id in annotations: 284 #### import_args.extend(['--annotation_link', str(ann_id)]) 285 import_args.append(image_file) 286 if _fetch_zip_only: 287 # calling 'import --advanced-help' will trigger the download of OMERO.java.zip 288 # in case it is not yet present (the extract_image_id() call will then fail, 289 # resulting in the whole function returning "False") 290 printlog("WARNING", "As '_fetch_zip_only' is set NO IMPORT WILL BE ATTEMPTED!") 291 import_args = ["import", "--advanced-help"] 292 log.debug(f"import_args: {import_args}") 293 try: 294 cli.invoke(import_args, strict=True) 295 imported_id = extract_image_id(cap_stdout) 296 log.success(f"Imported OMERO image ID: {imported_id}") 297 except PermissionError as err: 298 printlog("ERROR", err) 299 omero_userdir = os.environ.get("OMERO_USERDIR", "<not-set>") 300 printlog("ERROR", f"Current OMERO_USERDIR value: {omero_userdir}") 301 printlog( 302 "ERROR", 303 ( 304 "Please make sure to read the documentation about the 'OMERO_USERDIR' " 305 "environment variable and also check if the file to be imported has " 306 "appropriate permissions!" 307 ), 308 ) 309 return False 310 except Exception as err: # pylint: disable-msg=broad-except 311 printlog("ERROR", f"ERROR: uploading '{image_file}' to {omero_id} failed!") 312 printlog("ERROR", f"OMERO error message: >>>{err}<<<") 313 printlog("WARNING", f"import_args: {import_args}") 314 return False 315 finally: 316 tempdir.cleanup() 317 318 target_id = f"G:{omero_id.group}:Image:{imported_id}" 319 try: 320 summary = hrm.parse_summary(image_file) 321 add_annotation_keyvalue(conn, target_id, summary) 322 except Exception as err: # pragma: no cover # pylint: disable-msg=broad-except 323 log.error(f"Creating a parameter summary from [{image_file}] failed: {err}") 324 325 return True
Upload an image into a specific dataset in OMERO.
In case we know from the suffix that a given format is not supported by OMERO, the upload will not be initiated at all (e.g. for SVI-HDF5, having the suffix '.h5').
The import itself is done by instantiating the CLI class, assembling the required
arguments, and finally running cli.invoke()
. This eventually triggers the
importer()
method defined in OMERO's Python bindings.
Parameters
- conn (omero.gateway.BlitzGateway): The OMERO connection object.
- omero_id (hrm_omero.misc.OmeroId): The ID of the target dataset in OMERO.
- image_file (str): The local image file including the full path.
- omero_logfile (str, optional):
The prefix of files to be used to capture OMERO's
import
call stderr messages. If the parameter is non-empty the--debug ALL
option will be added to theomero
call with the output being placed in the specified file. If the parameter is omitted or empty, debug messages will be disabled. - _fetch_zip_only (bool, optional):
Replaces all parameters to the import call by
--advanced-help
, which is intended for INTERNAL TESTING ONLY. No actual import will be attempted!
Returns
- bool: True in case of success, False otherwise.
Raises
- TypeError: Raised in case
image_file
is in a format that is not supported by OMERO. - ValueError: Raised in case
omero_id
is not pointing to a dataset.