changeset 2:7bee859bbd11 draft

planemo upload for repository hhttps://github.com/npinter/ROIsplitter commit 7391296e0c7c8d48b42a129d154b50b29fd41737
author galaxyp
date Thu, 11 Apr 2024 07:52:58 +0000
parents 064b53fd3131
children 24ccdcfbabac
files qupath_roi_splitter.py qupath_roi_splitter.xml
diffstat 2 files changed, 77 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- a/qupath_roi_splitter.py	Wed Jun 14 16:37:01 2023 +0000
+++ b/qupath_roi_splitter.py	Thu Apr 11 07:52:58 2024 +0000
@@ -6,12 +6,43 @@
 import pandas as pd
 
 
-def draw_poly(input_df, input_img, col=(0, 0, 0)):
+def draw_poly(input_df, input_img, col=(0, 0, 0), fill=False):
     s = np.array(input_df)
-    output_img = cv2.fillPoly(input_img, pts=np.int32([s]), color=col)
+    if fill:
+        output_img = cv2.fillPoly(input_img, pts=np.int32([s]), color=col)
+    else:
+        output_img = cv2.polylines(input_img, np.int32([s]), True, color=col, thickness=1)
     return output_img
 
 
+def draw_roi(input_roi, input_img, fill):
+    if len(input_roi["geometry"]["coordinates"]) == 1:
+        # Polygon w/o holes
+        input_img = draw_poly(input_roi["geometry"]["coordinates"][0], input_img, fill=fill)
+    else:
+        first_roi = True
+        for sub_roi in input_roi["geometry"]["coordinates"]:
+            # Polygon with holes
+            if not isinstance(sub_roi[0][0], list):
+                if first_roi:
+                    input_img = draw_poly(sub_roi, input_img, fill=fill)
+                    first_roi = False
+                else:
+                    # holes in ROI
+                    input_img = draw_poly(sub_roi, input_img, col=(255, 255, 255), fill=fill)
+            else:
+                # MultiPolygon with holes
+                for sub_coord in sub_roi:
+                    if first_roi:
+                        input_img = draw_poly(sub_coord, input_img, fill=fill)
+                        first_roi = False
+                    else:
+                        # holes in ROI
+                        input_img = draw_poly(sub_coord, input_img, col=(255, 255, 255), fill=fill)
+
+    return input_img
+
+
 def split_qupath_roi(in_roi):
     with open(in_roi) as file:
         qupath_roi = geojson.load(file)
@@ -28,30 +59,13 @@
         img.fill(255)
 
         for i, roi in enumerate(qupath_roi["features"]):
-            if roi["properties"]["classification"]["name"] == cell_type:
-                if len(roi["geometry"]["coordinates"]) == 1:
-                    # Polygon w/o holes
-                    img = draw_poly(roi["geometry"]["coordinates"][0], img)
-                else:
-                    first_roi = True
-                    for sub_roi in roi["geometry"]["coordinates"]:
-                        # Polygon with holes
-                        if not isinstance(sub_roi[0][0], list):
-                            if first_roi:
-                                img = draw_poly(sub_roi, img)
-                                first_roi = False
-                            else:
-                                # holes in ROI
-                                img = draw_poly(sub_roi, img, col=(255, 255, 255))
-                        else:
-                            # MultiPolygon with holes
-                            for sub_coord in sub_roi:
-                                if first_roi:
-                                    img = draw_poly(sub_coord, img)
-                                    first_roi = False
-                                else:
-                                    # holes in ROI
-                                    img = draw_poly(sub_coord, img, col=(255, 255, 255))
+            if not args.all:
+                if "classification" not in roi["properties"]:
+                    continue
+                if roi["properties"]["classification"]["name"] == cell_type:
+                    img = draw_roi(roi, img, args.fill)
+            else:
+                img = draw_roi(roi, img, args.fill)
 
         # get all black pixel
         coords_arr = np.column_stack(np.where(img == (0, 0, 0)))
@@ -63,7 +77,10 @@
         coords_arr_xy = np.delete(coords_arr_xy, 2, axis=1)
 
         # to pandas and rename columns to x and y
-        coords_df = pd.DataFrame(coords_arr_xy, columns=['x', 'y'])
+        coords_df = pd.DataFrame(coords_arr_xy, columns=['y', 'x'])
+
+        # reorder columns
+        coords_df = coords_df[['x', 'y']]
 
         # drop duplicates
         coords_df = coords_df.drop_duplicates(
@@ -76,7 +93,9 @@
 if __name__ == "__main__":
     parser = argparse.ArgumentParser(description="Split ROI coordinates of QuPath TMA annotation by cell type (classfication)")
     parser.add_argument("--qupath_roi", default=False, help="Input QuPath annotation (GeoJSON file)")
+    parser.add_argument("--fill", action="store_true", required=False, help="Fill pixels in ROIs")
     parser.add_argument('--version', action='version', version='%(prog)s 0.1.0')
+    parser.add_argument("--all", action="store_true", required=False, help="Extracts all ROIs")
     args = parser.parse_args()
 
     if args.qupath_roi:
--- a/qupath_roi_splitter.xml	Wed Jun 14 16:37:01 2023 +0000
+++ b/qupath_roi_splitter.xml	Thu Apr 11 07:52:58 2024 +0000
@@ -1,5 +1,9 @@
-<tool id="qupath_roi_splitter" name="QuPath ROI Splitter" version="0.1.0+galaxy1">
+<tool id="qupath_roi_splitter" name="QuPath ROI Splitter" version="@VERSION@+galaxy@VERSION_SUFFIX@">
     <description>Split ROI coordinates of QuPath TMA annotation by cell type (classification)</description>
+    <macros>
+        <token name="@VERSION@">0.2.0</token>
+        <token name="@VERSION_SUFFIX@">0</token>
+    </macros>
     <requirements>
         <requirement type="package" version="3.0.1">geojson</requirement>
         <requirement type="package" version="1.24.2">numpy</requirement>
@@ -8,13 +12,21 @@
     </requirements>
      <command detect_errors="exit_code"><![CDATA[
         #for $input in $input_collection
-            python3 '$__tool_directory__/qupath_roi_splitter.py' --qupath_roi '$input' &&
+            python3 '$__tool_directory__/qupath_roi_splitter.py'
+                --qupath_roi '$input'
+                $optional.fill
+                $optional.all
+             &&
         #end for
-        mkdir out &&
-        mv *.txt out/
+        mkdir out
+        && mv *.txt out/
     ]]></command>
     <inputs>
         <param name="input_collection" type="data_collection" format="geojson" label="Input QuPath annotation" help="Collection containing GeoJSON files"/>
+        <section name="optional" title="Optional">
+            <param name="fill" type="boolean" truevalue="--fill" falsevalue="" checked="false" label="Fill ROIs" help="Fill pixels in ROIs"/>
+            <param name="all" type="boolean" truevalue="--all" falsevalue="" checked="false" label="Extract all" help="Extracts all ROIs"/>
+        </section>
     </inputs>
     <outputs>
         <collection name="output_txts" type="list" label="${tool.name} on ${on_string}: ROI data">
@@ -29,6 +41,9 @@
                     <element name="annotations_TMA_F-5.geojson" value="annotations_TMA_F-5.geojson" />
                 </collection>
             </param>
+            <section name="optional">
+                <param name="fill" value="true"/>
+            </section>
             <output_collection name="output_txts" type="list" count="4">
                 <element name="F-5_Stroma">
                     <assert_contents>
@@ -52,4 +67,16 @@
 
         https://github.com/npinter/ROIsplitter
     ]]></help>
+    <citations>
+        <citation type="bibtex">
+            @misc{
+                toolsGalaxyP,
+                author = {Pinter, N, Föll, MC },
+                title = {Galaxy Proteomics Tools},
+                publisher = {GitHub}, journal = {GitHub repository},
+                year = {2024},
+                url = {https://github.com/galaxyproteomics/tools-galaxyp}
+            }
+        </citation>
+    </citations>
 </tool>