# Advanced Features This reference covers advanced OMERO operations including permissions, deletion, filesets, and administrative tasks. ## Deleting Objects ### Delete with Wait ```python # Delete objects and wait for completion project_ids = [1, 2, 3] conn.deleteObjects("Project", project_ids, wait=True) print("Deletion complete") # Delete without waiting (asynchronous) conn.deleteObjects("Dataset", [dataset_id], wait=False) ``` ### Delete with Callback Monitoring ```python from omero.callbacks import CmdCallbackI # Start delete operation handle = conn.deleteObjects("Project", [project_id]) # Create callback to monitor progress cb = CmdCallbackI(conn.c, handle) print("Deleting, please wait...") # Poll for completion while not cb.block(500): # Check every 500ms print(".", end="", flush=True) print("\nDeletion finished") # Check for errors response = cb.getResponse() if isinstance(response, omero.cmd.ERR): print("Error occurred:") print(response) else: print("Deletion successful") # Clean up cb.close(True) # Also closes handle ``` ### Delete Different Object Types ```python # Delete images image_ids = [101, 102, 103] conn.deleteObjects("Image", image_ids, wait=True) # Delete datasets dataset_ids = [10, 11] conn.deleteObjects("Dataset", dataset_ids, wait=True) # Delete ROIs roi_ids = [201, 202] conn.deleteObjects("Roi", roi_ids, wait=True) # Delete annotations annotation_ids = [301, 302] conn.deleteObjects("Annotation", annotation_ids, wait=True) ``` ### Delete with Cascade ```python # Deleting a project will cascade to contained datasets # This behavior depends on server configuration project_id = 123 conn.deleteObjects("Project", [project_id], wait=True) # Datasets and images may be deleted or orphaned # depending on delete specifications ``` ## Filesets Filesets represent collections of original imported files. They were introduced in OMERO 5.0. ### Check if Image Has Fileset ```python image = conn.getObject("Image", image_id) fileset = image.getFileset() if fileset: print(f"Image is part of fileset {fileset.getId()}") else: print("Image has no fileset (pre-OMERO 5.0)") ``` ### Access Fileset Information ```python image = conn.getObject("Image", image_id) fileset = image.getFileset() if fileset: fs_id = fileset.getId() print(f"Fileset ID: {fs_id}") # List all images in this fileset print("Images in fileset:") for fs_image in fileset.copyImages(): print(f" {fs_image.getId()}: {fs_image.getName()}") # List original imported files print("\nOriginal files:") for orig_file in fileset.listFiles(): print(f" {orig_file.getPath()}/{orig_file.getName()}") print(f" Size: {orig_file.getSize()} bytes") ``` ### Get Fileset Directly ```python # Get fileset object fileset = conn.getObject("Fileset", fileset_id) if fileset: # Access images for image in fileset.copyImages(): print(f"Image: {image.getName()}") # Access files for orig_file in fileset.listFiles(): print(f"File: {orig_file.getName()}") ``` ### Download Original Files ```python import os fileset = image.getFileset() if fileset: download_dir = "./original_files" os.makedirs(download_dir, exist_ok=True) for orig_file in fileset.listFiles(): file_name = orig_file.getName() file_path = os.path.join(download_dir, file_name) print(f"Downloading: {file_name}") # Get file as RawFileStore raw_file_store = conn.createRawFileStore() raw_file_store.setFileId(orig_file.getId()) # Download in chunks with open(file_path, 'wb') as f: offset = 0 chunk_size = 1024 * 1024 # 1MB chunks size = orig_file.getSize() while offset < size: chunk = raw_file_store.read(offset, chunk_size) f.write(chunk) offset += len(chunk) raw_file_store.close() print(f"Saved to: {file_path}") ``` ## Group Permissions OMERO uses group-based permissions to control data access. ### Permission Levels - **PRIVATE** (`rw----`): Only owner can read/write - **READ-ONLY** (`rwr---`): Group members can read, only owner can write - **READ-ANNOTATE** (`rwra--`): Group members can read and annotate - **READ-WRITE** (`rwrw--`): Group members can read and write ### Check Current Group Permissions ```python # Get current group group = conn.getGroupFromContext() # Get permissions permissions = group.getDetails().getPermissions() perm_string = str(permissions) # Map to readable names permission_names = { 'rw----': 'PRIVATE', 'rwr---': 'READ-ONLY', 'rwra--': 'READ-ANNOTATE', 'rwrw--': 'READ-WRITE' } perm_name = permission_names.get(perm_string, 'UNKNOWN') print(f"Group: {group.getName()}") print(f"Permissions: {perm_name} ({perm_string})") ``` ### List User's Groups ```python # Get all groups for current user print("User's groups:") for group in conn.getGroupsMemberOf(): print(f" {group.getName()} (ID: {group.getId()})") # Get group permissions perms = group.getDetails().getPermissions() print(f" Permissions: {perms}") ``` ### Get Group Members ```python # Get group group = conn.getObject("ExperimenterGroup", group_id) # List members print(f"Members of {group.getName()}:") for member in group.getMembers(): print(f" {member.getFullName()} ({member.getOmeName()})") ``` ## Cross-Group Queries ### Query Across All Groups ```python # Set context to query all accessible groups conn.SERVICE_OPTS.setOmeroGroup('-1') # Now queries span all groups image = conn.getObject("Image", image_id) if image: group = image.getDetails().getGroup() print(f"Image found in group: {group.getName()}") # List projects across all groups for project in conn.getObjects("Project"): group = project.getDetails().getGroup() print(f"Project: {project.getName()} (Group: {group.getName()})") ``` ### Switch to Specific Group ```python # Get image's group image = conn.getObject("Image", image_id) group_id = image.getDetails().getGroup().getId() # Switch to that group's context conn.SERVICE_OPTS.setOmeroGroup(group_id) # Subsequent operations use this group projects = conn.listProjects() # Only from this group ``` ### Reset to Default Group ```python # Get default group default_group_id = conn.getEventContext().groupId # Switch back to default conn.SERVICE_OPTS.setOmeroGroup(default_group_id) ``` ## Administrative Operations ### Check Admin Status ```python # Check if current user is admin if conn.isAdmin(): print("User has admin privileges") # Check if full admin if conn.isFullAdmin(): print("User is full administrator") else: # Check specific privileges privileges = conn.getCurrentAdminPrivileges() print(f"Admin privileges: {privileges}") ``` ### List Administrators ```python # Get all administrators print("Administrators:") for admin in conn.getAdministrators(): print(f" ID: {admin.getId()}") print(f" Username: {admin.getOmeName()}") print(f" Full Name: {admin.getFullName()}") ``` ### Set Object Owner (Admin Only) ```python import omero.model # Create annotation with specific owner (requires admin) tag_ann = omero.gateway.TagAnnotationWrapper(conn) tag_ann.setValue("Admin-created tag") # Set owner user_id = 5 tag_ann._obj.details.owner = omero.model.ExperimenterI(user_id, False) tag_ann.save() print(f"Created annotation owned by user {user_id}") ``` ### Substitute User Connection (Admin Only) ```python # Connect as admin admin_conn = BlitzGateway(admin_user, admin_pass, host=host, port=4064) admin_conn.connect() # Get target user target_user_id = 10 user = admin_conn.getObject("Experimenter", target_user_id) username = user.getOmeName() # Create connection as that user user_conn = admin_conn.suConn(username) print(f"Connected as {username}") # Perform operations as that user for project in user_conn.listProjects(): print(f" {project.getName()}") # Close connections user_conn.close() admin_conn.close() ``` ### List All Users ```python # Get all users (admin operation) print("All users:") for user in conn.getObjects("Experimenter"): print(f" ID: {user.getId()}") print(f" Username: {user.getOmeName()}") print(f" Full Name: {user.getFullName()}") print(f" Email: {user.getEmail()}") print() ``` ## Service Access OMERO provides various services for specific operations. ### Update Service ```python # Get update service updateService = conn.getUpdateService() # Save and return object roi = omero.model.RoiI() roi.setImage(image._obj) saved_roi = updateService.saveAndReturnObject(roi) # Save multiple objects objects = [obj1, obj2, obj3] saved_objects = updateService.saveAndReturnArray(objects) ``` ### ROI Service ```python # Get ROI service roi_service = conn.getRoiService() # Find ROIs for image result = roi_service.findByImage(image_id, None) # Get shape statistics shape_ids = [shape.id.val for roi in result.rois for shape in roi.copyShapes()] stats = roi_service.getShapeStatsRestricted(shape_ids, 0, 0, [0]) ``` ### Metadata Service ```python # Get metadata service metadataService = conn.getMetadataService() # Load annotations by type and namespace ns_to_include = ["mylab.analysis"] ns_to_exclude = [] annotations = metadataService.loadSpecifiedAnnotations( 'omero.model.FileAnnotation', ns_to_include, ns_to_exclude, None ) for ann in annotations: print(f"Annotation: {ann.getId().getValue()}") ``` ### Query Service ```python # Get query service queryService = conn.getQueryService() # Build query (more complex queries) params = omero.sys.ParametersI() params.addLong("image_id", image_id) query = "select i from Image i where i.id = :image_id" image = queryService.findByQuery(query, params) ``` ### Thumbnail Service ```python # Get thumbnail service thumbnailService = conn.createThumbnailStore() # Set current image thumbnailService.setPixelsId(image.getPrimaryPixels().getId()) # Get thumbnail thumbnail = thumbnailService.getThumbnail(96, 96) # Close service thumbnailService.close() ``` ### Raw File Store ```python # Get raw file store rawFileStore = conn.createRawFileStore() # Set file ID rawFileStore.setFileId(orig_file_id) # Read file data = rawFileStore.read(0, rawFileStore.size()) # Close rawFileStore.close() ``` ## Object Ownership and Details ### Get Object Details ```python image = conn.getObject("Image", image_id) # Get details details = image.getDetails() # Owner information owner = details.getOwner() print(f"Owner ID: {owner.getId()}") print(f"Username: {owner.getOmeName()}") print(f"Full Name: {owner.getFullName()}") # Group information group = details.getGroup() print(f"Group: {group.getName()} (ID: {group.getId()})") # Creation information creation_event = details.getCreationEvent() print(f"Created: {creation_event.getTime()}") # Update information update_event = details.getUpdateEvent() print(f"Updated: {update_event.getTime()}") ``` ### Get Permissions ```python # Get object permissions details = image.getDetails() permissions = details.getPermissions() # Check specific permissions can_edit = permissions.canEdit() can_annotate = permissions.canAnnotate() can_link = permissions.canLink() can_delete = permissions.canDelete() print(f"Can edit: {can_edit}") print(f"Can annotate: {can_annotate}") print(f"Can link: {can_link}") print(f"Can delete: {can_delete}") ``` ## Event Context ### Get Current Event Context ```python # Get event context (current session info) ctx = conn.getEventContext() print(f"User ID: {ctx.userId}") print(f"Username: {ctx.userName}") print(f"Group ID: {ctx.groupId}") print(f"Group Name: {ctx.groupName}") print(f"Session ID: {ctx.sessionId}") print(f"Is Admin: {ctx.isAdmin}") ``` ## Complete Admin Example ```python from omero.gateway import BlitzGateway # Connect as admin ADMIN_USER = 'root' ADMIN_PASS = 'password' HOST = 'omero.example.com' PORT = 4064 with BlitzGateway(ADMIN_USER, ADMIN_PASS, host=HOST, port=PORT) as admin_conn: print("=== Administrator Operations ===\n") # List all users print("All Users:") for user in admin_conn.getObjects("Experimenter"): print(f" {user.getOmeName()}: {user.getFullName()}") # List all groups print("\nAll Groups:") for group in admin_conn.getObjects("ExperimenterGroup"): perms = group.getDetails().getPermissions() print(f" {group.getName()}: {perms}") # List members for member in group.getMembers(): print(f" - {member.getOmeName()}") # Query across all groups print("\nAll Projects (all groups):") admin_conn.SERVICE_OPTS.setOmeroGroup('-1') for project in admin_conn.getObjects("Project"): owner = project.getDetails().getOwner() group = project.getDetails().getGroup() print(f" {project.getName()}") print(f" Owner: {owner.getOmeName()}") print(f" Group: {group.getName()}") # Connect as another user target_user_id = 5 user = admin_conn.getObject("Experimenter", target_user_id) if user: print(f"\n=== Operating as {user.getOmeName()} ===\n") user_conn = admin_conn.suConn(user.getOmeName()) # List that user's projects for project in user_conn.listProjects(): print(f" {project.getName()}") user_conn.close() ``` ## Best Practices 1. **Permissions**: Always check permissions before operations 2. **Group Context**: Set appropriate group context for queries 3. **Admin Operations**: Use admin privileges sparingly and carefully 4. **Delete Confirmation**: Always confirm before deleting objects 5. **Callback Monitoring**: Monitor long delete operations with callbacks 6. **Fileset Awareness**: Check for filesets when working with images 7. **Service Cleanup**: Close services when done (thumbnailStore, rawFileStore) 8. **Cross-Group Queries**: Use `-1` group ID for cross-group access 9. **Error Handling**: Always handle permission and access errors 10. **Documentation**: Document administrative operations clearly ## Troubleshooting ### Permission Denied ```python try: conn.deleteObjects("Project", [project_id], wait=True) except Exception as e: if "SecurityViolation" in str(e): print("Permission denied: You don't own this object") else: raise ``` ### Object Not Found ```python # Check if object exists before accessing obj = conn.getObject("Image", image_id) if obj is None: print(f"Image {image_id} not found or not accessible") else: # Process object pass ``` ### Group Context Issues ```python # If object not found, try cross-group query conn.SERVICE_OPTS.setOmeroGroup('-1') obj = conn.getObject("Image", image_id) if obj: # Switch to object's group for further operations group_id = obj.getDetails().getGroup().getId() conn.SERVICE_OPTS.setOmeroGroup(group_id) ```