changeset 1:588d6fa22fc4 draft

planemo upload for repository https://github.com/Helmholtz-UFZ/galaxy-tools/tree/main/tools/omero commit 5b1b30d409355cee98485815c1dd4ac48649bcc1
author ufz
date Thu, 05 Sep 2024 11:55:55 +0000
parents 352e9d4eaf70
children e41f70e69349
files omero_metadata_import.xml omero_roi_upload.py test-data/input_roi.tsv test-data/omero_output.txt test-data/output_KV_import.txt test-data/output_table_import.txt test-data/output_table_roi.txt
diffstat 7 files changed, 199 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/omero_metadata_import.xml	Wed Aug 07 12:54:19 2024 +0000
+++ b/omero_metadata_import.xml	Thu Sep 05 11:55:55 2024 +0000
@@ -3,7 +3,7 @@
     <description> with ezomero </description>
     <macros>
         <token name="@TOOL_VERSION@">5.18.0</token>
-        <token name="@VERSION_SUFFIX@">0</token>
+        <token name="@VERSION_SUFFIX@">1</token>
     </macros>
     <xrefs>
         <xref type="bio.tools">omero</xref>
@@ -11,12 +11,13 @@
     <requirements>
         <requirement type="package" version="3.0.1">ezomero</requirement>
         <requirement type="package" version="2.2.2">pandas</requirement>
+        <!-- openjdk is needed: https://github.com/conda-forge/omero-py-feedstock/pull/16 -->
         <requirement type="package" version="21.0.2">openjdk</requirement>
     </requirements>
     <command detect_errors="exit_code"><![CDATA[
         python $__tool_directory__/omero_metadata_upload.py
-        --user $__user__.extra_preferences.get('omero|username', $test_username)
-        --pws $__user__.extra_preferences.get('omero|password', $test_password)
+        --user $__user__.extra_preferences.get('omero_account|username', $test_username)
+        --pws $__user__.extra_preferences.get('omero_account|username', $test_password)
         --host $omero_host
         --port $omero_port
         --obj_type $obj_type
@@ -29,7 +30,10 @@
         #end if
     ]]></command>
     <inputs>
-        <param argument="omero_host" type="text" optional="false" label="OMERO host URL"/>
+        <param name="omero_host" type="text" label="OMERO host URL">
+            <validator type="regex" message="Enter a valid host location, for example, your.omero.server">^[a-zA-Z0-9._-]*$</validator>
+            <validator type="expression" message="No two dots (..) allowed">'..' not in value</validator>
+        </param>
         <param argument="omero_port" type="integer" optional="false" value="4064" label="OMERO port"/>
         <param argument="obj_type" type="select" optional="true" label="Target Object Type">
             <option value="project">Project</option>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/omero_roi_upload.py	Thu Sep 05 11:55:55 2024 +0000
@@ -0,0 +1,165 @@
+import argparse
+import re
+
+import pandas as pd
+from ezomero import connect, post_roi
+from ezomero.rois import Ellipse, Label, Line, Point, Polygon, Polyline, Rectangle
+
+
+def parse_color(color_str):
+    if not color_str:
+        return None
+    return tuple(map(int, re.findall(r'\d+', color_str)))
+
+
+def parse_points(points_str):
+    if not points_str:
+        return None
+    # Remove leading and trailing brackets and split into individual points
+    points_str = points_str.strip("[]")
+    points = points_str.split("),(")
+    points = [point.strip("()") for point in points]  # Remove any remaining parentheses
+    return [tuple(map(float, point.split(','))) for point in points]
+
+
+def create_shape(row):
+    shape_type = row['shape']
+    shape = None
+
+    if shape_type == 'Ellipse':
+        shape = Ellipse(
+            x=row['x'],
+            y=row['y'],
+            x_rad=row['x_rad'],
+            y_rad=row['y_rad'],
+            z=row.get('z'),
+            c=row.get('c'),
+            t=row.get('t'),
+            fill_color=parse_color(row.get('fill_color')),
+            stroke_color=parse_color(row.get('stroke_color')),
+            stroke_width=row.get('stroke_width')
+        )
+    elif shape_type == 'Label':
+        shape = Label(
+            x=row['x'],
+            y=row['y'],
+            label=row['label'],
+            fontSize=row['fontSize'],
+            z=row.get('z'),
+            c=row.get('c'),
+            t=row.get('t'),
+            fill_color=parse_color(row.get('fill_color')),
+            stroke_color=parse_color(row.get('stroke_color')),
+            stroke_width=row.get('stroke_width')
+        )
+    elif shape_type == 'Line':
+        shape = Line(
+            x1=row['x1'],
+            y1=row['y1'],
+            x2=row['x2'],
+            y2=row['y2'],
+            markerStart=row.get('markerStart', None),
+            markerEnd=row.get('markerEnd', None),
+            label=row.get('label', None),
+            z=row.get('z'),
+            c=row.get('c'),
+            t=row.get('t'),
+            fill_color=parse_color(row.get('fill_color')),
+            stroke_color=parse_color(row.get('stroke_color')),
+            stroke_width=row.get('stroke_width')
+        )
+    elif shape_type == 'Point':
+        shape = Point(
+            x=row['x'],
+            y=row['y'],
+            z=row.get('z'),
+            c=row.get('c'),
+            t=row.get('t'),
+            fill_color=parse_color(row.get('fill_color')),
+            stroke_color=parse_color(row.get('stroke_color')),
+            stroke_width=row.get('stroke_width')
+        )
+    elif shape_type == 'Polygon':
+        shape = Polygon(
+            points=parse_points(row['points']),
+            z=row.get('z'),
+            c=row.get('c'),
+            t=row.get('t'),
+            fill_color=parse_color(row.get('fill_color')),
+            stroke_color=parse_color(row.get('stroke_color')),
+            stroke_width=row.get('stroke_width')
+        )
+    elif shape_type == 'Polyline':
+        shape = Polyline(
+            points=parse_points(row['points']),
+            z=row.get('z'),
+            c=row.get('c'),
+            t=row.get('t'),
+            fill_color=parse_color(row.get('fill_color')),
+            stroke_color=parse_color(row.get('stroke_color')),
+            stroke_width=row.get('stroke_width')
+        )
+    elif shape_type == 'Rectangle':
+        shape = Rectangle(
+            x=row['x'],
+            y=row['y'],
+            width=row['width'],
+            height=row['height'],
+            z=row.get('z'),
+            c=row.get('c'),
+            t=row.get('t'),
+            fill_color=parse_color(row.get('fill_color')),
+            stroke_color=parse_color(row.get('stroke_color')),
+            stroke_width=row.get('stroke_width')
+        )
+    return shape
+
+
+def main(input_file, conn, image_id, log_file):
+    # Open log file
+    with open(log_file, 'w') as log:
+        df = pd.read_csv(input_file, sep='\t')
+        for index, row in df.iterrows():
+            msg = f"Processing row {index + 1}/{len(df)}: {row.to_dict()}"
+            print(msg)
+            log.write(msg + "\n")
+            shape = create_shape(row)
+            if shape:
+                roi_name = row['roi_name'] if 'roi_name' in row else None
+                roi_description = row['roi_description'] if 'roi_description' in row else None
+                roi_id = post_roi(conn, image_id, [shape], name=roi_name, description=roi_description)
+                msg = f"ROI ID: {roi_id} for row {index + 1}"
+                print(msg)
+                log.write(msg + "\n")
+            else:
+                msg = f"Skipping row {index + 1}: Unable to create shape"
+                print(msg)
+                log.write(msg + "\n")
+
+
+if __name__ == "__main__":
+    parser = argparse.ArgumentParser(
+        description="Create shapes from a tabular file and optionally post them as an ROI to OMERO.")
+    parser.add_argument("--input_file", help="Path to the input tabular file.")
+    parser.add_argument("--image_id", type=int, required=True, help="ID of the image to which the ROI will be linked")
+    parser.add_argument("--host", type=str, required=True, help="OMERO server host")
+    parser.add_argument("--user", type=str, required=True, help="OMERO username")
+    parser.add_argument("--psw", type=str, required=True, help="OMERO password")
+    parser.add_argument("--port", type=int, default=4064, help="OMERO server port")
+    parser.add_argument("--log_file", type=str, default="process.txt", help="Log file path")
+
+    args = parser.parse_args()
+
+    conn = connect(
+        host=args.host,
+        user=args.user,
+        password=args.psw,
+        port=args.port,
+        group="",
+        secure=True
+    )
+
+    try:
+        main(args.input_file, conn, args.image_id, args.log_file)
+    finally:
+        conn.close()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/input_roi.tsv	Thu Sep 05 11:55:55 2024 +0000
@@ -0,0 +1,8 @@
+shape	x	y	x_rad	y_rad	label	fontSize	x1	y1	x2	y2	points	width	height	fill_color	stroke_color	stroke_width	z	c	t	roi_name	roi_description
+Ellipse	50.0	50.0	20.0	10.0										(255,0,0,128)	(0,0,0,255)	2	0	0	0	Example ROI	This is an example ROI
+Label	100.0	100.0			Test Label	12.0								(255,255,255,0)	(0,0,255,255)	1	0	0	0	Example ROI	This is an example ROI
+Line							200.0	200.0	250.0	250.0				(0,255,0,128)	(0,0,0,255)	2	0	1	0	Example ROI	This is an example ROI
+Point	150.0	150.0												(0,0,255,128)	(255,0,0,255)	3	0	2	0	Example ROI	This is an example ROI
+Polygon											(300,300),(350,350),(300,400)			(255,255,0,128)	(0,0,0,255)	2	1	0	0	Example ROI	This is an example ROI
+Polyline											(400,400),(450,450),(400,500)			(0,255,255,128)	(0,0,0,255)	3	0	0	0	Example ROI	This is an example ROI
+Rectangle	500.0	500.0										100.0	50.0	(255,0,255,128)	(0,0,0,255)	2	0	0	0	Example ROI	This is an example ROI
--- a/test-data/omero_output.txt	Wed Aug 07 12:54:19 2024 +0000
+++ b/test-data/omero_output.txt	Thu Sep 05 11:55:55 2024 +0000
@@ -1,2 +1,2 @@
-Image:1
-Image:2
+Image:3
+Image:4
--- a/test-data/output_KV_import.txt	Wed Aug 07 12:54:19 2024 +0000
+++ b/test-data/output_KV_import.txt	Thu Sep 05 11:55:55 2024 +0000
@@ -1,1 +1,1 @@
-SUCCESS: Successfully uploaded metadata for dataset with ID 1. Result: {'Key1': 'Value1', 'Key2': 'Value2'}
+SUCCESS: Successfully uploaded metadata for dataset with ID 2. Result: {'Key1': 'Value1', 'Key2': 'Value2'}
--- a/test-data/output_table_import.txt	Wed Aug 07 12:54:19 2024 +0000
+++ b/test-data/output_table_import.txt	Thu Sep 05 11:55:55 2024 +0000
@@ -1,2 +1,2 @@
-SUCCESS: Successfully uploaded metadata for project with ID 1. Result:      Key1    Key2
+SUCCESS: Successfully uploaded metadata for project with ID 2. Result:      Key1    Key2
 0  Value1  Value2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/output_table_roi.txt	Thu Sep 05 11:55:55 2024 +0000
@@ -0,0 +1,14 @@
+Processing row 1/7: {'shape': 'Ellipse', 'x': 50.0, 'y': 50.0, 'x_rad': 20.0, 'y_rad': 10.0, 'label': nan, 'fontSize': nan, 'x1': nan, 'y1': nan, 'x2': nan, 'y2': nan, 'points': nan, 'width': nan, 'height': nan, 'fill_color': '(255,0,0,128)', 'stroke_color': '(0,0,0,255)', 'stroke_width': 2, 'z': 0, 'c': 0, 't': 0, 'roi_name': 'Example ROI', 'roi_description': 'This is an example ROI'}
+ROI ID: 1 for row 1
+Processing row 2/7: {'shape': 'Label', 'x': 100.0, 'y': 100.0, 'x_rad': nan, 'y_rad': nan, 'label': 'Test Label', 'fontSize': 12.0, 'x1': nan, 'y1': nan, 'x2': nan, 'y2': nan, 'points': nan, 'width': nan, 'height': nan, 'fill_color': '(255,255,255,0)', 'stroke_color': '(0,0,255,255)', 'stroke_width': 1, 'z': 0, 'c': 0, 't': 0, 'roi_name': 'Example ROI', 'roi_description': 'This is an example ROI'}
+ROI ID: 2 for row 2
+Processing row 3/7: {'shape': 'Line', 'x': nan, 'y': nan, 'x_rad': nan, 'y_rad': nan, 'label': nan, 'fontSize': nan, 'x1': 200.0, 'y1': 200.0, 'x2': 250.0, 'y2': 250.0, 'points': nan, 'width': nan, 'height': nan, 'fill_color': '(0,255,0,128)', 'stroke_color': '(0,0,0,255)', 'stroke_width': 2, 'z': 0, 'c': 1, 't': 0, 'roi_name': 'Example ROI', 'roi_description': 'This is an example ROI'}
+ROI ID: 3 for row 3
+Processing row 4/7: {'shape': 'Point', 'x': 150.0, 'y': 150.0, 'x_rad': nan, 'y_rad': nan, 'label': nan, 'fontSize': nan, 'x1': nan, 'y1': nan, 'x2': nan, 'y2': nan, 'points': nan, 'width': nan, 'height': nan, 'fill_color': '(0,0,255,128)', 'stroke_color': '(255,0,0,255)', 'stroke_width': 3, 'z': 0, 'c': 2, 't': 0, 'roi_name': 'Example ROI', 'roi_description': 'This is an example ROI'}
+ROI ID: 4 for row 4
+Processing row 5/7: {'shape': 'Polygon', 'x': nan, 'y': nan, 'x_rad': nan, 'y_rad': nan, 'label': nan, 'fontSize': nan, 'x1': nan, 'y1': nan, 'x2': nan, 'y2': nan, 'points': '(300,300),(350,350),(300,400)', 'width': nan, 'height': nan, 'fill_color': '(255,255,0,128)', 'stroke_color': '(0,0,0,255)', 'stroke_width': 2, 'z': 1, 'c': 0, 't': 0, 'roi_name': 'Example ROI', 'roi_description': 'This is an example ROI'}
+ROI ID: 5 for row 5
+Processing row 6/7: {'shape': 'Polyline', 'x': nan, 'y': nan, 'x_rad': nan, 'y_rad': nan, 'label': nan, 'fontSize': nan, 'x1': nan, 'y1': nan, 'x2': nan, 'y2': nan, 'points': '(400,400),(450,450),(400,500)', 'width': nan, 'height': nan, 'fill_color': '(0,255,255,128)', 'stroke_color': '(0,0,0,255)', 'stroke_width': 3, 'z': 0, 'c': 0, 't': 0, 'roi_name': 'Example ROI', 'roi_description': 'This is an example ROI'}
+ROI ID: 6 for row 6
+Processing row 7/7: {'shape': 'Rectangle', 'x': 500.0, 'y': 500.0, 'x_rad': nan, 'y_rad': nan, 'label': nan, 'fontSize': nan, 'x1': nan, 'y1': nan, 'x2': nan, 'y2': nan, 'points': nan, 'width': 100.0, 'height': 50.0, 'fill_color': '(255,0,255,128)', 'stroke_color': '(0,0,0,255)', 'stroke_width': 2, 'z': 0, 'c': 0, 't': 0, 'roi_name': 'Example ROI', 'roi_description': 'This is an example ROI'}
+ROI ID: 7 for row 7