hrm_omero.omero
Functions related to direct interaction with OMERO.
1"""Functions related to direct interaction with OMERO.""" 2 3from datetime import datetime, timedelta 4 5import yaml 6from Ice import ConnectionLostException # pylint: disable-msg=no-name-in-module 7from loguru import logger as log 8 9import omero.gateway 10 11from .decorators import connect_and_set_group 12from .misc import printlog 13 14 15def connect(user, passwd, host, port=4064): # pragma: no cover 16 """Establish the connection to an OMERO server. 17 18 DEPRECATED function, rather use BlitzGateway's `connect()` in a context manager or 19 in a try/finally block to ensure the connection is properly `close()`d in any case! 20 21 NOTE: this does NOT check credentials - it only talks to the OMERO server to create 22 the connection object. To verify a login, use `check_credentials()`. 23 24 Parameters 25 ---------- 26 user : str 27 The OMERO user name (e.g. `demo_user_01`). 28 passwd : str 29 The corresponding OMERO user password. 30 host : str 31 The OMERO server hostname or IP address. 32 port : int, optional 33 The OMERO port number, by default 4064. 34 35 Returns 36 ------- 37 omero.gateway.BlitzGateway 38 The OMERO connection object. 39 """ 40 log.warning("'connect()' is DEPRECATED, will be removed in an upcoming release!") 41 conn = omero.gateway.BlitzGateway( 42 user, passwd, host=host, port=port, secure=True, useragent="HRM-OMERO.connector" 43 ) 44 conn.connect() 45 group = conn.getGroupFromContext() 46 log.debug("Created new OMERO connection [user={}, group={}].", user, group.getId()) 47 return conn 48 49 50def check_credentials(conn): 51 """Check if supplied credentials are valid and print a message to stdout. 52 53 Parameters 54 ---------- 55 conn : omero.gateway.BlitzGateway 56 The OMERO connection object. 57 58 Returns 59 ------- 60 bool 61 True if connecting was successful (i.e. credentials are correct), False 62 otherwise. 63 """ 64 log.debug("Trying to connect to OMERO...") 65 connected = conn.connect() 66 if connected: 67 uid = conn.getUserId() 68 name = conn.getUser().getName() 69 printlog("SUCCESS", f"Connected to OMERO [user={name}, uid={uid}].") 70 else: 71 printlog("WARNING", "ERROR logging into OMERO.") 72 73 try: 74 group = conn.getGroupFromContext() 75 log.debug(f"User's default group is {group.getId()} ({group.getName()}).") 76 except ConnectionLostException: 77 log.warning("Getting group context failed, password might be wrong!") 78 return False 79 80 return connected 81 82 83def extract_image_id(fname): 84 """Parse the YAML returned by an 'omero import' call and extract the image ID. 85 86 Parameters 87 ---------- 88 fname : str 89 The path to the `yaml` file to parse. 90 91 Returns 92 ------- 93 int or None 94 The OMERO ID of the newly imported image, e.g. `1568386` or `None` in case 95 parsing the file failed for any reason. 96 """ 97 try: 98 with open(fname, "r", encoding="utf-8") as stream: 99 parsed = yaml.safe_load(stream) 100 if len(parsed[0]["Image"]) != 1: 101 msg = f"Unexpected YAML retrieved from OMERO, unable to parse:\n{parsed}" 102 printlog("ERROR", msg) 103 raise SyntaxError(msg) 104 image_id = parsed[0]["Image"][0] 105 except Exception as err: # pylint: disable-msg=broad-except 106 printlog("ERROR", f"Error parsing imported image ID from YAML output: {err}") 107 return None 108 109 log.success(f"Successfully parsed Image ID from YAML: {image_id}") 110 return image_id 111 112 113@connect_and_set_group 114def add_annotation_keyvalue(conn, omero_id, annotation): 115 """Add a key-value "map" annotation to an OMERO object. 116 117 Parameters 118 ---------- 119 conn : omero.gateway.BlitzGateway 120 The OMERO connection object. 121 omero_id : hrm_omero.misc.OmeroId 122 The ID of the OMERO object that should receive the annotation. 123 annotation : dict(dict) 124 The map annotation as returned by `hrm_omero.hrm.parse_summary()`. 125 126 Returns 127 ------- 128 bool 129 True in case of success, False otherwise. 130 131 Raises 132 ------ 133 RuntimeError 134 Raised in case re-establishing the OMERO connection fails. 135 """ 136 log.trace(f"Adding a map annotation to {omero_id}") 137 target_obj = conn.getObject(omero_id.obj_type, omero_id.obj_id) 138 if target_obj is None: 139 log.warning(f"Unable to identify target object {omero_id} in OMERO!") 140 return False 141 142 for section in annotation: 143 namespace = f"Huygens Remote Manager - {section}" 144 log.trace(f"Using namespace [{namespace}] for annotation.") 145 map_ann = omero.gateway.MapAnnotationWrapper(conn) 146 map_ann.setValue(annotation[section].items()) 147 map_ann.setNs(namespace) 148 map_ann.save() 149 target_obj.linkAnnotation(map_ann) 150 log.debug(f"Added key-value annotation using namespace [{namespace}].") 151 152 log.success(f"Added annotation to {omero_id}.") 153 154 return True 155 156 157@connect_and_set_group 158def new_project(conn, omero_id, proj_name): # pragma: no cover 159 """Create a new Project in OMERO. 160 161 Parameters 162 ---------- 163 conn : omero.gateway.BlitzGateway 164 The OMERO connection object. 165 omero_id : hrm_omero.misc.OmeroId 166 The ID of an OMERO object denoting an Experimenter. 167 proj_name : str 168 The name of the project to be created. 169 """ 170 raise NotImplementedError("Creating Projects is not yet implemented.") 171 172 173@connect_and_set_group 174def new_dataset(conn, omero_id, ds_name): # pragma: no cover 175 """Create a new Project in OMERO. 176 177 Parameters 178 ---------- 179 conn : omero.gateway.BlitzGateway 180 The OMERO connection object. 181 omero_id : hrm_omero.misc.OmeroId 182 The ID of an OMERO object denoting a Project or an Experimenter. 183 ds_name : str 184 The name of the dataset to be created. 185 """ 186 raise NotImplementedError("Creating Datasets is not yet implemented.") 187 188 189def find_recently_imported(conn, ds_id, label, age=15): 190 """Speculative way of identifying a recently imported image in a dataset. 191 192 Check children of a dataset in OMERO until one is found that is matching following 193 criteria: 194 195 * the import date is not more than the specified `age` tolerance ago (in seconds) 196 * the object name is matching the given label 197 198 Usually it will hit the right object in the first iteration as `listChildren()` 199 seems to give the images in reverse order of their import (newest ones first). 200 201 Parameters 202 ---------- 203 conn : omero.gateway.BlitzGateway 204 The OMERO connection object. 205 ds_id : int or int-like 206 The ID of the dataset where to look for the image. 207 label : str 208 The label of the imported image, in the simplest case this is usually just the 209 file name of the original file without any path components. 210 age : int, optional 211 The maximum age in seconds that the identified image object in OMERO is allowed 212 to have, by default 15. 213 214 Returns 215 ------- 216 omero.gateway._ImageWrapper or None 217 The "Image" object as returned by OMERO's BlitzGateway or None in case no image 218 object matching the criteria could be found. 219 """ 220 imported = None 221 dset = conn.getObject("Dataset", ds_id) 222 for image in dset.listChildren(): 223 if image.getName() != label: 224 continue 225 226 oldest_allowed_date = datetime.now() - timedelta(seconds=age) 227 date = image.getDate() 228 if date >= oldest_allowed_date: 229 imported = image 230 log.success(f"Found imported image: {image.getId()}") 231 break 232 233 return imported
16def connect(user, passwd, host, port=4064): # pragma: no cover 17 """Establish the connection to an OMERO server. 18 19 DEPRECATED function, rather use BlitzGateway's `connect()` in a context manager or 20 in a try/finally block to ensure the connection is properly `close()`d in any case! 21 22 NOTE: this does NOT check credentials - it only talks to the OMERO server to create 23 the connection object. To verify a login, use `check_credentials()`. 24 25 Parameters 26 ---------- 27 user : str 28 The OMERO user name (e.g. `demo_user_01`). 29 passwd : str 30 The corresponding OMERO user password. 31 host : str 32 The OMERO server hostname or IP address. 33 port : int, optional 34 The OMERO port number, by default 4064. 35 36 Returns 37 ------- 38 omero.gateway.BlitzGateway 39 The OMERO connection object. 40 """ 41 log.warning("'connect()' is DEPRECATED, will be removed in an upcoming release!") 42 conn = omero.gateway.BlitzGateway( 43 user, passwd, host=host, port=port, secure=True, useragent="HRM-OMERO.connector" 44 ) 45 conn.connect() 46 group = conn.getGroupFromContext() 47 log.debug("Created new OMERO connection [user={}, group={}].", user, group.getId()) 48 return conn
Establish the connection to an OMERO server.
DEPRECATED function, rather use BlitzGateway's connect()
in a context manager or
in a try/finally block to ensure the connection is properly close()
d in any case!
NOTE: this does NOT check credentials - it only talks to the OMERO server to create
the connection object. To verify a login, use check_credentials()
.
Parameters
- user (str):
The OMERO user name (e.g.
demo_user_01
). - passwd (str): The corresponding OMERO user password.
- host (str): The OMERO server hostname or IP address.
- port (int, optional): The OMERO port number, by default 4064.
Returns
- omero.gateway.BlitzGateway: The OMERO connection object.
51def check_credentials(conn): 52 """Check if supplied credentials are valid and print a message to stdout. 53 54 Parameters 55 ---------- 56 conn : omero.gateway.BlitzGateway 57 The OMERO connection object. 58 59 Returns 60 ------- 61 bool 62 True if connecting was successful (i.e. credentials are correct), False 63 otherwise. 64 """ 65 log.debug("Trying to connect to OMERO...") 66 connected = conn.connect() 67 if connected: 68 uid = conn.getUserId() 69 name = conn.getUser().getName() 70 printlog("SUCCESS", f"Connected to OMERO [user={name}, uid={uid}].") 71 else: 72 printlog("WARNING", "ERROR logging into OMERO.") 73 74 try: 75 group = conn.getGroupFromContext() 76 log.debug(f"User's default group is {group.getId()} ({group.getName()}).") 77 except ConnectionLostException: 78 log.warning("Getting group context failed, password might be wrong!") 79 return False 80 81 return connected
Check if supplied credentials are valid and print a message to stdout.
Parameters
- conn (omero.gateway.BlitzGateway): The OMERO connection object.
Returns
- bool: True if connecting was successful (i.e. credentials are correct), False otherwise.
84def extract_image_id(fname): 85 """Parse the YAML returned by an 'omero import' call and extract the image ID. 86 87 Parameters 88 ---------- 89 fname : str 90 The path to the `yaml` file to parse. 91 92 Returns 93 ------- 94 int or None 95 The OMERO ID of the newly imported image, e.g. `1568386` or `None` in case 96 parsing the file failed for any reason. 97 """ 98 try: 99 with open(fname, "r", encoding="utf-8") as stream: 100 parsed = yaml.safe_load(stream) 101 if len(parsed[0]["Image"]) != 1: 102 msg = f"Unexpected YAML retrieved from OMERO, unable to parse:\n{parsed}" 103 printlog("ERROR", msg) 104 raise SyntaxError(msg) 105 image_id = parsed[0]["Image"][0] 106 except Exception as err: # pylint: disable-msg=broad-except 107 printlog("ERROR", f"Error parsing imported image ID from YAML output: {err}") 108 return None 109 110 log.success(f"Successfully parsed Image ID from YAML: {image_id}") 111 return image_id
Parse the YAML returned by an 'omero import' call and extract the image ID.
Parameters
- fname (str):
The path to the
yaml
file to parse.
Returns
- int or None: The OMERO ID of the newly imported image, e.g.
1568386
orNone
in case parsing the file failed for any reason.
114@connect_and_set_group 115def add_annotation_keyvalue(conn, omero_id, annotation): 116 """Add a key-value "map" annotation to an OMERO object. 117 118 Parameters 119 ---------- 120 conn : omero.gateway.BlitzGateway 121 The OMERO connection object. 122 omero_id : hrm_omero.misc.OmeroId 123 The ID of the OMERO object that should receive the annotation. 124 annotation : dict(dict) 125 The map annotation as returned by `hrm_omero.hrm.parse_summary()`. 126 127 Returns 128 ------- 129 bool 130 True in case of success, False otherwise. 131 132 Raises 133 ------ 134 RuntimeError 135 Raised in case re-establishing the OMERO connection fails. 136 """ 137 log.trace(f"Adding a map annotation to {omero_id}") 138 target_obj = conn.getObject(omero_id.obj_type, omero_id.obj_id) 139 if target_obj is None: 140 log.warning(f"Unable to identify target object {omero_id} in OMERO!") 141 return False 142 143 for section in annotation: 144 namespace = f"Huygens Remote Manager - {section}" 145 log.trace(f"Using namespace [{namespace}] for annotation.") 146 map_ann = omero.gateway.MapAnnotationWrapper(conn) 147 map_ann.setValue(annotation[section].items()) 148 map_ann.setNs(namespace) 149 map_ann.save() 150 target_obj.linkAnnotation(map_ann) 151 log.debug(f"Added key-value annotation using namespace [{namespace}].") 152 153 log.success(f"Added annotation to {omero_id}.") 154 155 return True
Add a key-value "map" annotation to an OMERO object.
Parameters
- conn (omero.gateway.BlitzGateway): The OMERO connection object.
- omero_id (hrm_omero.misc.OmeroId): The ID of the OMERO object that should receive the annotation.
- annotation (dict(dict)):
The map annotation as returned by
hrm_omero.hrm.parse_summary()
.
Returns
- bool: True in case of success, False otherwise.
Raises
- RuntimeError: Raised in case re-establishing the OMERO connection fails.
158@connect_and_set_group 159def new_project(conn, omero_id, proj_name): # pragma: no cover 160 """Create a new Project in OMERO. 161 162 Parameters 163 ---------- 164 conn : omero.gateway.BlitzGateway 165 The OMERO connection object. 166 omero_id : hrm_omero.misc.OmeroId 167 The ID of an OMERO object denoting an Experimenter. 168 proj_name : str 169 The name of the project to be created. 170 """ 171 raise NotImplementedError("Creating Projects is not yet implemented.")
Create a new Project in OMERO.
Parameters
- conn (omero.gateway.BlitzGateway): The OMERO connection object.
- omero_id (hrm_omero.misc.OmeroId): The ID of an OMERO object denoting an Experimenter.
- proj_name (str): The name of the project to be created.
174@connect_and_set_group 175def new_dataset(conn, omero_id, ds_name): # pragma: no cover 176 """Create a new Project in OMERO. 177 178 Parameters 179 ---------- 180 conn : omero.gateway.BlitzGateway 181 The OMERO connection object. 182 omero_id : hrm_omero.misc.OmeroId 183 The ID of an OMERO object denoting a Project or an Experimenter. 184 ds_name : str 185 The name of the dataset to be created. 186 """ 187 raise NotImplementedError("Creating Datasets is not yet implemented.")
Create a new Project in OMERO.
Parameters
- conn (omero.gateway.BlitzGateway): The OMERO connection object.
- omero_id (hrm_omero.misc.OmeroId): The ID of an OMERO object denoting a Project or an Experimenter.
- ds_name (str): The name of the dataset to be created.
190def find_recently_imported(conn, ds_id, label, age=15): 191 """Speculative way of identifying a recently imported image in a dataset. 192 193 Check children of a dataset in OMERO until one is found that is matching following 194 criteria: 195 196 * the import date is not more than the specified `age` tolerance ago (in seconds) 197 * the object name is matching the given label 198 199 Usually it will hit the right object in the first iteration as `listChildren()` 200 seems to give the images in reverse order of their import (newest ones first). 201 202 Parameters 203 ---------- 204 conn : omero.gateway.BlitzGateway 205 The OMERO connection object. 206 ds_id : int or int-like 207 The ID of the dataset where to look for the image. 208 label : str 209 The label of the imported image, in the simplest case this is usually just the 210 file name of the original file without any path components. 211 age : int, optional 212 The maximum age in seconds that the identified image object in OMERO is allowed 213 to have, by default 15. 214 215 Returns 216 ------- 217 omero.gateway._ImageWrapper or None 218 The "Image" object as returned by OMERO's BlitzGateway or None in case no image 219 object matching the criteria could be found. 220 """ 221 imported = None 222 dset = conn.getObject("Dataset", ds_id) 223 for image in dset.listChildren(): 224 if image.getName() != label: 225 continue 226 227 oldest_allowed_date = datetime.now() - timedelta(seconds=age) 228 date = image.getDate() 229 if date >= oldest_allowed_date: 230 imported = image 231 log.success(f"Found imported image: {image.getId()}") 232 break 233 234 return imported
Speculative way of identifying a recently imported image in a dataset.
Check children of a dataset in OMERO until one is found that is matching following criteria:
- the import date is not more than the specified
age
tolerance ago (in seconds) - the object name is matching the given label
Usually it will hit the right object in the first iteration as listChildren()
seems to give the images in reverse order of their import (newest ones first).
Parameters
- conn (omero.gateway.BlitzGateway): The OMERO connection object.
- ds_id (int or int-like): The ID of the dataset where to look for the image.
- label (str): The label of the imported image, in the simplest case this is usually just the file name of the original file without any path components.
- age (int, optional): The maximum age in seconds that the identified image object in OMERO is allowed to have, by default 15.
Returns
- omero.gateway._ImageWrapper or None: The "Image" object as returned by OMERO's BlitzGateway or None in case no image object matching the criteria could be found.