changeset 0:c5928c28e2f0 draft default tip

planemo upload for repository https://github.com/galaxyproject/tools-iuc/tree/main/tools/spatialdata commit 87bff76d897c5a4277d9987cf26432a18e0458cd-dirty
author iuc
date Sat, 14 Mar 2026 15:15:45 +0000
parents
children
files macros.xml spatialdata_plot.xml
diffstat 2 files changed, 1130 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/macros.xml	Sat Mar 14 15:15:45 2026 +0000
@@ -0,0 +1,442 @@
+<macros>
+    <token name="@TOOL_VERSION@">0.7.2</token>
+    <token name="@VERSION_SUFFIX@">0</token>
+    <token name="@PROFILE@">25.0</token>
+    <xml name="requirements">
+        <requirements>
+            <requirement type="package" version="@TOOL_VERSION@">spatialdata</requirement>
+            <requirement type="package" version="0.6.0">spatialdata-io</requirement>
+            <requirement type="package" version="0.2.14">spatialdata-plot</requirement>
+            <!-- spatialdata is not compatible with ome-zarr > 0.13.0 check here: https://github.com/conda-forge/spatialdata-feedstock/pull/33-->
+            <requirement type="package" version="0.13.0">ome-zarr</requirement>
+            <!-- The zarr writer in Previous anndata doesn't support serializing ArrowStringArray. pining anndata and pandas -->
+            <requirement type="package" version="0.12.10">anndata</requirement>
+            <requirement type="package" version="2.3.3">pandas</requirement>
+            <requirement type="package" version="0.20.0">rioxarray</requirement>
+            <requirement type="package" version="3.0">zip</requirement>
+        </requirements>
+    </xml>
+    <xml name="creator">
+        <creator>
+            <person givenName="Amirhossein" familyName="Naghsh Nilchi" email="nilchia@informatik.uni-freiburg.de"/>
+            <person givenName="Pavan" familyName="Videm" email="videmp@informatik.uni-freiburg.de"/>
+            <person givenName="Björn" familyName="Grüning" email="gruening@informatik.uni-freiburg.de"/>
+            <organization name="European Galaxy Team" url="https://usegalaxy-eu.github.io/people"/>
+        </creator>
+    </xml>
+    <xml name="sanitize_digits">
+        <sanitizer invalid_char="">
+            <valid initial="string.digits">
+                <add value=","/>
+                <add value="."/>
+                <yield/>
+            </valid>
+       </sanitizer>
+    </xml>
+    <xml name="sanitize_query" token_validinitial="string.printable">
+        <sanitizer>
+            <valid initial="@VALIDINITIAL@">
+                <remove value="&apos;"/>
+            </valid>
+       </sanitizer>
+    </xml>
+    <xml name="matplotlib_color">
+        <option value="AliceBlue">AliceBlue</option>
+        <option value="AntiqueWhite">AntiqueWhite</option>
+        <option value="Aqua">Aqua</option>
+        <option value="Aquamarine">Aquamarine</option>
+        <option value="Azure">Azure</option>
+        <option value="Beige">Beige</option>
+        <option value="Bisque">Bisque</option>
+        <option value="Black">Black</option>
+        <option value="BlanchedAlmond">BlanchedAlmond</option>
+        <option value="Blue">Blue</option>
+        <option value="BlueViolet">BlueViolet</option>
+        <option value="Brown">Brown</option>
+        <option value="BurlyWood">BurlyWood</option>
+        <option value="CadetBlue">CadetBlue</option>
+        <option value="Chartreuse">Chartreuse</option>
+        <option value="Chocolate">Chocolate</option>
+        <option value="Coral">Coral</option>
+        <option value="CornflowerBlue">CornflowerBlue</option>
+        <option value="Cornsilk">Cornsilk</option>
+        <option value="Crimson">Crimson</option>
+        <option value="Cyan">Cyan</option>
+        <option value="DarkBlue">DarkBlue</option>
+        <option value="DarkCyan">DarkCyan</option>
+        <option value="DarkGoldenRod">DarkGoldenRod</option>
+        <option value="DarkGray">DarkGray</option>
+        <option value="DarkGrey">DarkGrey</option>
+        <option value="DarkGreen">DarkGreen</option>
+        <option value="DarkKhaki">DarkKhaki</option>
+        <option value="DarkMagenta">DarkMagenta</option>
+        <option value="DarkOliveGreen">DarkOliveGreen</option>
+        <option value="DarkOrange">DarkOrange</option>
+        <option value="DarkOrchid">DarkOrchid</option>
+        <option value="DarkRed">DarkRed</option>
+        <option value="DarkSalmon">DarkSalmon</option>
+        <option value="DarkSeaGreen">DarkSeaGreen</option>
+        <option value="DarkSlateBlue">DarkSlateBlue</option>
+        <option value="DarkSlateGray">DarkSlateGray</option>
+        <option value="DarkSlateGrey">DarkSlateGrey</option>
+        <option value="DarkTurquoise">DarkTurquoise</option>
+        <option value="DarkViolet">DarkViolet</option>
+        <option value="DeepPink">DeepPink</option>
+        <option value="DeepSkyBlue">DeepSkyBlue</option>
+        <option value="DimGray">DimGray</option>
+        <option value="DimGrey">DimGrey</option>
+        <option value="DodgerBlue">DodgerBlue</option>
+        <option value="FireBrick">FireBrick</option>
+        <option value="FloralWhite">FloralWhite</option>
+        <option value="ForestGreen">ForestGreen</option>
+        <option value="Fuchsia">Fuchsia</option>
+        <option value="Gainsboro">Gainsboro</option>
+        <option value="GhostWhite">GhostWhite</option>
+        <option value="Gold">Gold</option>
+        <option value="GoldenRod">GoldenRod</option>
+        <option value="Gray">Gray</option>
+        <option value="Grey">Grey</option>
+        <option value="Green">Green</option>
+        <option value="GreenYellow">GreenYellow</option>
+        <option value="HoneyDew">HoneyDew</option>
+        <option value="HotPink">HotPink</option>
+        <option value="IndianRed">IndianRed</option>
+        <option value="Indigo">Indigo</option>
+        <option value="Ivory">Ivory</option>
+        <option value="Khaki">Khaki</option>
+        <option value="Lavender">Lavender</option>
+        <option value="LavenderBlush">LavenderBlush</option>
+        <option value="LawnGreen">LawnGreen</option>
+        <option value="LemonChiffon">LemonChiffon</option>
+        <option value="LightBlue">LightBlue</option>
+        <option value="LightCoral">LightCoral</option>
+        <option value="LightCyan">LightCyan</option>
+        <option value="LightGoldenRodYellow">LightGoldenRodYellow</option>
+        <option value="LightGray">LightGray</option>
+        <option value="LightGrey">LightGrey</option>
+        <option value="LightGreen">LightGreen</option>
+        <option value="LightPink">LightPink</option>
+        <option value="LightSalmon">LightSalmon</option>
+        <option value="LightSeaGreen">LightSeaGreen</option>
+        <option value="LightSkyBlue">LightSkyBlue</option>
+        <option value="LightSlateGray">LightSlateGray</option>
+        <option value="LightSlateGrey">LightSlateGrey</option>
+        <option value="LightSteelBlue">LightSteelBlue</option>
+        <option value="LightYellow">LightYellow</option>
+        <option value="Lime">Lime</option>
+        <option value="LimeGreen">LimeGreen</option>
+        <option value="Linen">Linen</option>
+        <option value="Magenta">Magenta</option>
+        <option value="Maroon">Maroon</option>
+        <option value="MediumAquaMarine">MediumAquaMarine</option>
+        <option value="MediumBlue">MediumBlue</option>
+        <option value="MediumOrchid">MediumOrchid</option>
+        <option value="MediumPurple">MediumPurple</option>
+        <option value="MediumSeaGreen">MediumSeaGreen</option>
+        <option value="MediumSlateBlue">MediumSlateBlue</option>
+        <option value="MediumSpringGreen">MediumSpringGreen</option>
+        <option value="MediumTurquoise">MediumTurquoise</option>
+        <option value="MediumVioletRed">MediumVioletRed</option>
+        <option value="MidnightBlue">MidnightBlue</option>
+        <option value="MintCream">MintCream</option>
+        <option value="MistyRose">MistyRose</option>
+        <option value="Moccasin">Moccasin</option>
+        <option value="NavajoWhite">NavajoWhite</option>
+        <option value="Navy">Navy</option>
+        <option value="OldLace">OldLace</option>
+        <option value="Olive">Olive</option>
+        <option value="OliveDrab">OliveDrab</option>
+        <option value="Orange">Orange</option>
+        <option value="OrangeRed">OrangeRed</option>
+        <option value="Orchid">Orchid</option>
+        <option value="PaleGoldenRod">PaleGoldenRod</option>
+        <option value="PaleGreen">PaleGreen</option>
+        <option value="PaleTurquoise">PaleTurquoise</option>
+        <option value="PaleVioletRed">PaleVioletRed</option>
+        <option value="PapayaWhip">PapayaWhip</option>
+        <option value="PeachPuff">PeachPuff</option>
+        <option value="Peru">Peru</option>
+        <option value="Pink">Pink</option>
+        <option value="Plum">Plum</option>
+        <option value="PowderBlue">PowderBlue</option>
+        <option value="Purple">Purple</option>
+        <option value="RebeccaPurple">RebeccaPurple</option>
+        <option value="Red">Red</option>
+        <option value="RosyBrown">RosyBrown</option>
+        <option value="RoyalBlue">RoyalBlue</option>
+        <option value="SaddleBrown">SaddleBrown</option>
+        <option value="Salmon">Salmon</option>
+        <option value="SandyBrown">SandyBrown</option>
+        <option value="SeaGreen">SeaGreen</option>
+        <option value="SeaShell">SeaShell</option>
+        <option value="Sienna">Sienna</option>
+        <option value="Silver">Silver</option>
+        <option value="SkyBlue">SkyBlue</option>
+        <option value="SlateBlue">SlateBlue</option>
+        <option value="SlateGray">SlateGray</option>
+        <option value="SlateGrey">SlateGrey</option>
+        <option value="Snow">Snow</option>
+        <option value="SpringGreen">SpringGreen</option>
+        <option value="SteelBlue">SteelBlue</option>
+        <option value="Tan">Tan</option>
+        <option value="Teal">Teal</option>
+        <option value="Thistle">Thistle</option>
+        <option value="Tomato">Tomato</option>
+        <option value="Turquoise">Turquoise</option>
+        <option value="Violet">Violet</option>
+        <option value="Wheat">Wheat</option>
+        <option value="White">White</option>
+        <option value="WhiteSmoke">WhiteSmoke</option>
+        <option value="Yellow">Yellow</option>
+        <option value="YellowGreen">YellowGreen</option>
+    </xml>
+    <xml name="matplotlib_pyplot_colormap">
+        <option value="viridis">viridis (Perceptually Uniform Sequential)</option>
+        <option value="plasma">plasma (Perceptually Uniform Sequential)</option>
+        <option value="inferno">inferno (Perceptually Uniform Sequential)</option>
+        <option value="magma">magma (Perceptually Uniform Sequential)</option>
+        <option value="cividis">cividis (Perceptually Uniform Sequential)</option>
+        <option value="Greys">Greys (Sequential)</option>
+        <option value="Purples">Purples (Sequential)</option>
+        <option value="Blues">Blues (Sequential)</option>
+        <option value="Greens">Greens (Sequential)</option>
+        <option value="Oranges">Oranges (Sequential)</option>
+        <option value="Reds">Reds (Sequential)</option>
+        <option value="YlOrBr">YlOrBr (Sequential)</option>
+        <option value="YlOrRd">YlOrRd (Sequential)</option>
+        <option value="OrRd">OrRd (Sequential)</option>
+        <option value="PuRd">PuRd (Sequential)</option>
+        <option value="RdPu">RdPu (Sequential)</option>
+        <option value="BuPu">BuPu (Sequential)</option>
+        <option value="GnBu">GnBu (Sequential)</option>
+        <option value="PuBu">PuBu (Sequential)</option>
+        <option value="YlGnBu">YlGnBu (Sequential)</option>
+        <option value="PuBuGn">PuBuGn (Sequential)</option>
+        <option value="BuGn">BuGn (Sequential)</option>
+        <option value="YlGn">YlGn (Sequential)</option>
+        <option value="binary">binary (Sequential 2)</option>
+        <option value="gist_yarg">gist_yarg (Sequential 2)</option>
+        <option value="gist_gray">gist_gray (Sequential 2)</option>
+        <option value="gray">gray (Sequential 2)</option>
+        <option value="bone">bone (Sequential 2)</option>
+        <option value="pink">pink (Sequential 2)</option>
+        <option value="spring">spring (Sequential 2)</option>
+        <option value="summer">summer (Sequential 2)</option>
+        <option value="autumn">autumn (Sequential 2)</option>
+        <option value="winter">winter (Sequential 2)</option>
+        <option value="cool">cool (Sequential 2)</option>
+        <option value="Wistia">Wistia (Sequential 2)</option>
+        <option value="hot">hot (Sequential 2)</option>
+        <option value="afmhot">afmhot (Sequential 2)</option>
+        <option value="gist_heat">gist_heat (Sequential 2)</option>
+        <option value="copper">copper (Sequential 2)</option>
+        <option value="PiYG">PiYG (Diverging)</option>
+        <option value="PRGn">PRGn (Diverging)</option>
+        <option value="BrBG">BrBG (Diverging)</option>
+        <option value="PuOr">PuOr (Diverging)</option>
+        <option value="RdGy">RdGy (Diverging)</option>
+        <option value="RdBu">RdBu (Diverging)</option>
+        <option value="RdYlBu">RdYlBu (Diverging)</option>
+        <option value="RdYlGn">RdYlGn (Diverging)</option>
+        <option value="Spectral">Spectral (Diverging)</option>
+        <option value="coolwarm">coolwarm (Diverging)</option>
+        <option value="bwr">bwr (Diverging)</option>
+        <option value="seismic">seismic (Diverging)</option>
+        <option value="twilight">twilight (Cyclic)</option>
+        <option value="twilight_shifted">twilight_shifted (Cyclic)</option>
+        <option value="hsv">hsv (Cyclic)</option>
+        <option value="Pastel1">Pastel1 (Qualitative)</option>
+        <option value="Pastel2">Pastel2 (Qualitative)</option>
+        <option value="Paired">Paired (Qualitative)</option>
+        <option value="Accent">Accent (Qualitative)</option>
+        <option value="Dark2">Dark2 (Qualitative)</option>
+        <option value="Set1">Set1 (Qualitative)</option>
+        <option value="Set2">Set2 (Qualitative)</option>
+        <option value="Set3">Set3 (Qualitative)</option>
+        <option value="tab10">tab10 (Qualitative)</option>
+        <option value="tab20">tab20 (Qualitative)</option>
+        <option value="tab20b">tab20b (Qualitative)</option>
+        <option value="tab20c">tab20c (Qualitative)</option>
+        <option value="flag">flag (Miscellaneous)</option>
+        <option value="prism">prism (Miscellaneous)</option>
+        <option value="ocean">ocean (Miscellaneous)</option>
+        <option value="gist_earth">gist_earth (Miscellaneous)</option>
+        <option value="terrain">terrain (Miscellaneous)</option>
+        <option value="gist_stern">gist_stern (Miscellaneous)</option>
+        <option value="gnuplot">gnuplot (Miscellaneous)</option>
+        <option value="gnuplot2">gnuplot2 (Miscellaneous)</option>
+        <option value="CMRmap">CMRmap (Miscellaneous)</option>
+        <option value="cubehelix">cubehelix (Miscellaneous)</option>
+        <option value="brg">brg (Miscellaneous)</option>
+        <option value="gist_rainbow">gist_rainbow (Miscellaneous)</option>
+        <option value="rainbow">rainbow (Miscellaneous)</option>
+        <option value="jet">jet (Miscellaneous)</option>
+        <option value="nipy_spectral">nipy_spectral (Miscellaneous)</option>
+        <option value="gist_ncar">gist_ncar (Miscellaneous)</option>
+    </xml>
+
+    <xml name="cmap_param">
+        <param argument="cmap" type="select" multiple="true" label="Matplotlib colormap name">
+            <expand macro="matplotlib_pyplot_colormap"/>
+        </param>
+    </xml>
+    <xml name="palette_param">
+        <param name="palette" type="select" multiple="true" label="Palette for discrete annotations" help="Must match the number of groups. The list can contain multiple palettes (one per group) to be visualized. If groups is provided but not palette, palette is set to default lightgray">
+            <expand macro="matplotlib_color"/>
+        </param>
+    </xml>
+    <xml name="normalize_condi">
+        <conditional name="normalize_condi">
+            <param name="normalize" type="select" label="Apply matplotlib colormap normalization for continuous annotations?">
+                <option value="no">No</option>
+                <option value="yes">Yes</option>
+            </param>
+            <when value="no"/>
+            <when value="yes">
+                <param name="vmin" type="float" optional="true" label="Min value" help="Values within the range [vmin, vmax] from the input data will be linearly mapped to [0, 1]. If either vmin or vmax is not provided, they default to the minimum and maximum values of the input, respectively." />
+                <param name="vmax" type="float" optional="true" label="Max value" help="Values within the range [vmin, vmax] from the input data will be linearly mapped to [0, 1]. If either vmin or vmax is not provided, they default to the minimum and maximum values of the input, respectively." />
+                <param name="clip" type="boolean" truevalue="True" falsevalue="False" checked="false" label="Clip" help="If clipping is on, values below vmin are mapped to 0 and values above vmax are mapped to 1" />
+            </when>
+        </conditional>
+    </xml>
+    <xml name="cmap_or_palette_condi">
+        <conditional name="cmap_or_palette_condi">
+            <param name="color_map_type" type="select" label="Color mapping type">
+                <option value="none">None</option>
+                <option value="cmap">Colormap (for continuous data)</option>
+                <option value="palette">Palette (for discrete/categorical data)</option>
+            </param>
+            <when value="none"/>
+            <when value="cmap">
+                <expand macro="cmap_param"/>
+            </when>
+            <when value="palette">
+                <expand macro="palette_param"/>
+            </when>
+        </conditional>
+    </xml>
+
+    <!-- Input/Output macros -->
+    <xml name="input_spatialdata">
+        <param name="input_spatialdata" type="data" format="spatialdata.zip" label="SpatialData object"/>
+    </xml>
+
+    <!-- Common parameter macros -->
+    <xml name="param_element_name" token_label="Element name" token_help="" token_optional="false">
+        <param name="element_name" type="text" label="@LABEL@" help="@HELP@" optional="@OPTIONAL@">
+            <expand macro="sanitize_query"/>
+            <yield/>
+        </param>
+    </xml>
+
+    <xml name="param_output_element_name" token_value="transformed_element" token_label="Output element name" token_help="">
+        <param name="output_element_name" type="text" value="@VALUE@" label="@LABEL@" help="@HELP@">
+            <expand macro="sanitize_query"/>
+        </param>
+    </xml>
+
+    <xml name="param_table_name" token_value="table" token_optional="false" token_label="Table name" token_help="">
+        <param name="table_name" type="text" value="@VALUE@" optional="@OPTIONAL@" label="@LABEL@" help="@HELP@">
+            <expand macro="sanitize_query"/>
+        </param>
+    </xml>
+
+    <xml name="param_coordinate_system" token_value="global" token_label="Coordinate system" token_help="">
+        <param name="coordinate_system" type="text" value="@VALUE@" label="@LABEL@" help="@HELP@">
+            <expand macro="sanitize_query"/>
+        </param>
+    </xml>
+
+    <xml name="param_target_coordinate_system" token_value="global" token_label="Target coordinate system" token_help="">
+        <param name="target_coordinate_system" type="text" value="@VALUE@" label="@LABEL@" help="@HELP@">
+            <expand macro="sanitize_query"/>
+        </param>
+    </xml>
+
+    <xml name="param_axes" token_value="x,y" token_label="Axes" token_help="Comma-separated list of axes (e.g., 'x,y' or 'x,y,z')">
+        <param name="axes" type="text" value="@VALUE@" label="@LABEL@" help="@HELP@">
+            <expand macro="sanitize_query"/>
+        </param>
+    </xml>
+
+    <xml name="param_region_key" token_value="region" token_optional="false" token_label="Region key" token_help="">
+        <param name="region_key" type="text" value="@VALUE@" optional="@OPTIONAL@" label="@LABEL@" help="@HELP@">
+            <expand macro="sanitize_query"/>
+        </param>
+    </xml>
+
+    <xml name="param_instance_key" token_value="instance_id" token_optional="false" token_label="Instance key" token_help="">
+        <param name="instance_key" type="text" value="@VALUE@" optional="@OPTIONAL@" label="@LABEL@" help="@HELP@">
+            <expand macro="sanitize_query"/>
+        </param>
+    </xml>
+
+    <xml name="param_value_key" token_optional="false" token_label="Value key" token_help="">
+        <param name="value_key" type="text" optional="@OPTIONAL@" label="@LABEL@" help="@HELP@">
+            <expand macro="sanitize_query"/>
+        </param>
+    </xml>
+
+    <xml name="coordinate_bounds_params">
+        <param name="min_coordinate" type="text" label="Minimum coordinates" help="Comma-separated (e.g., '0,0')">
+            <expand macro="sanitize_digits"/>
+        </param>
+        <param name="max_coordinate" type="text" label="Maximum coordinates" help="Comma-separated (e.g., '100,100')">
+            <expand macro="sanitize_digits"/>
+        </param>
+    </xml>
+
+    <!-- Option group macros -->
+    <xml name="join_type_options">
+        <option value="left_exclusive">Left Exclusive</option>
+        <option value="inner">Inner</option>
+        <option value="right">Right</option>
+        <option value="right_exclusive">Right Exclusive</option>
+    </xml>
+
+    <xml name="param_join_type" token_selected="left">
+        <param name="how" type="select" label="Join type">
+            <option value="@SELECTED@" selected="true">@SELECTED@</option>
+            <expand macro="join_type_options"/>
+        </param>
+    </xml>
+
+    <xml name="agg_func_options">
+        <option value="sum">Sum</option>
+        <option value="mean">Mean</option>
+        <option value="count">Count</option>
+    </xml>
+
+    <xml name="param_agg_func" token_optional="false" token_selected="sum" token_help="">
+        <param name="agg_func" type="select" optional="@OPTIONAL@" label="Aggregation function">
+            <option value="@SELECTED@" selected="true">@SELECTED@</option>
+            <expand macro="agg_func_options"/>
+        </param>
+    </xml>
+
+    <xml name="param_table_layer" token_optional="true" token_label="Layer of the AnnData table to use for coloring if color is in table.var" token_help="If None, sdata.table.X of the default table is used for coloring.">
+        <param name="table_layer" type="text" optional="@OPTIONAL@" label="@LABEL@" help="@HELP@">
+            <expand macro="sanitize_query"/>
+        </param>
+    </xml>
+
+    <xml name="param_color" token_label="Color column" token_help="Column name from table.obs or table.var to use for coloring. Use comma to separate multiple keys. It can also be a color name.">
+        <param name="color" type="text" optional="true" label="@LABEL@" help="@HELP@">
+            <expand macro="sanitize_query"/>
+        </param>
+    </xml>
+
+    <xml name="param_rendering_method" token_optional="true" token_label="Rendering method" token_help="When None, the method is chosen based on the size of the data.">
+        <param name="method" type="select" optional="@OPTIONAL@" label="@LABEL@" help="@HELP@">
+            <yield/>
+            <option value="matplotlib">Matplotlib</option>
+            <option value="datashader">Datashader</option>
+        </param>
+    </xml>
+
+    <xml name="citations">
+        <citations>
+            <citation type="doi">10.1038/s41592-024-02212-x</citation>
+        </citations>
+    </xml>
+</macros>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/spatialdata_plot.xml	Sat Mar 14 15:15:45 2026 +0000
@@ -0,0 +1,688 @@
+<tool id="spatialdata_plot" name="SpatialData Plot" version="@TOOL_VERSION@+galaxy@VERSION_SUFFIX@" profile="@PROFILE@">
+    <description>rich static plotting from SpatialData objects</description>
+    <macros>
+        <import>macros.xml</import>
+    </macros>
+    <expand macro="requirements"/>
+    <expand macro="creator" />
+    <command detect_errors="exit_code"><![CDATA[
+        unzip -q '$input_spatialdata' -d input &&
+
+        ## Rename directory to spatialdata if it has a different name
+        dir_name=\$(ls -d input/*/ | head -1 | xargs basename) &&
+        if [ "\$dir_name" != "spatialdata" ]; then
+            mv "input/\$dir_name" input/spatialdata;
+        fi &&
+
+        ## run the plotting pipeline
+        cat 'spdata_plot.py' &&
+        python3 'spdata_plot.py'
+    ]]></command>
+    <configfiles>
+        <configfile name="spdata_plot_config" filename="spdata_plot.py">
+import spatialdata as sd
+import spatialdata_plot
+
+## Load the SpatialData object
+spdata = sd.read_zarr("./input/spatialdata")
+
+print(spdata)
+
+## Render images
+#for $img in $render_images:
+spdata = spdata.pl.render_images(
+    #if $img.image_element:
+    element='$img.image_element',
+    #else:
+    element=None,
+    #end if
+    #if $img.channel:
+    channel='$img.channel',
+    #end if
+    #if str($img.cmap_or_palette_condi.color_map_type) == 'cmap':
+        #set $cmap_list = [str(x.strip()) for x in str($img.cmap_or_palette_condi.cmap).split(',')]
+    cmap=$cmap_list,
+    #end if
+    #if str($img.normalize_condi.normalize) == 'yes':
+    norm=Normalize(
+        vmin=$img.normalize_condi.vmin if str($img.normalize_condi.vmin) != '' else None,
+        vmax=$img.normalize_condi.vmax if str($img.normalize_condi.vmax) != '' else None,
+        clip=$img.normalize_condi.clip
+    ),
+    #end if
+    #if str($img.cmap_or_palette_condi.color_map_type) == 'palette':
+        #set $palette_list = [str(x.strip()) for x in str($img.cmap_or_palette_condi.palette).split(',')]
+    palette=$palette_list,
+    #end if
+    alpha=$img.alpha,
+    #if $img.scale:
+    scale='$img.scale',
+    #end if
+)
+#end for
+
+## Render labels
+#for $lbl in $render_labels:
+spdata = spdata.pl.render_labels(
+    #if $lbl.labels_element:
+    element='$lbl.labels_element',
+    #else:
+    element=None,
+    #end if
+    #if $lbl.color:
+    color='$lbl.color',
+    #end if
+    #if $lbl.groups:
+        #set $groups_list = [str(x.strip()) for x in str($lbl.groups).split(',')]
+    groups=$groups_list,
+    #end if
+    #if str($lbl.cmap_or_palette_condi.color_map_type) == 'palette':
+        #set $palette_list = [str(x.strip()) for x in str($lbl.cmap_or_palette_condi.palette).split(',')]
+    palette=$palette_list,
+    #end if
+    contour_px=$lbl.contour_px,
+    #if str($lbl.cmap_or_palette_condi.color_map_type) == 'cmap':
+        #set $cmap_list = [str(x.strip()) for x in str($lbl.cmap_or_palette_condi.cmap).split(',')]
+    cmap=$cmap_list,
+    #end if
+    #if str($lbl.normalize_condi.normalize) == 'yes':
+    norm=Normalize(
+        vmin=$lbl.normalize_condi.vmin if str($lbl.normalize_condi.vmin) != '' else None,
+        vmax=$lbl.normalize_condi.vmax if str($lbl.normalize_condi.vmax) != '' else None,
+        clip=$lbl.normalize_condi.clip
+    ),
+    #end if
+    outline_alpha=$lbl.outline_alpha,
+    fill_alpha=$lbl.fill_alpha,
+    #if $lbl.scale:
+    scale='$lbl.scale',
+    #else
+    scale=None,
+    #end if
+    #if $lbl.table_name:
+    table_name='$lbl.table_name',
+    #else
+    table_name=None,
+    #end if
+    #if $lbl.table_layer:
+    table_layer='$lbl.table_layer',
+    #else
+    table_layer=None,
+    #end if
+)
+#end for
+
+## Render points
+#for $pt in $render_points:
+spdata = spdata.pl.render_points(
+    #if $pt.points_element:
+    element='$pt.points_element',
+    #else:
+    element=None,
+    #end if
+    #if $pt.color:
+    color='$pt.color',
+    #end if
+    #if str($pt.alpha) != '':
+    alpha=$pt.alpha,
+    #end if
+    #if $pt.groups:
+     #set $groups_list = [str(x.strip()) for x in str($pt.groups).split(',')]
+    groups=$groups_list,
+    #end if
+    #if str($pt.cmap_or_palette_condi.color_map_type) == 'palette':
+        #set $palette_list = [str(x.strip()) for x in str($pt.cmap_or_palette_condi.palette).split(',')]
+    palette=$palette_list,
+    #end if
+    #if str($pt.cmap_or_palette_condi.color_map_type) == 'cmap':
+        #set $cmap_list = [str(x.strip()) for x in str($pt.cmap_or_palette_condi.cmap).split(',')]
+    cmap=$cmap_list,
+    #end if
+    #if str($pt.normalize_condi.normalize) == 'yes':
+    norm=Normalize(
+        vmin=$pt.normalize_condi.vmin if str($pt.normalize_condi.vmin) != '' else None,
+        vmax=$pt.normalize_condi.vmax if str($pt.normalize_condi.vmax) != '' else None,
+        clip=$pt.normalize_condi.clip
+    ),
+    #end if
+    size=$pt.size,
+    #if $pt.method:
+    method='$pt.method',
+    #else:
+    method=None,
+    #end if
+    #if $pt.table_name:
+    table_name='$pt.table_name',
+    #else
+    table_name=None,
+    #end if
+    #if $pt.table_layer:
+    table_layer='$pt.table_layer',
+    #else
+    table_layer=None,
+    #end if
+
+)
+#end for
+
+## Render shapes
+#for $shp in $render_shapes:
+spdata = spdata.pl.render_shapes(
+    #if $shp.shapes_element:
+    element='$shp.shapes_element',
+    #else:
+    element=None,
+    #end if
+    #if $shp.color:
+    color='$shp.color',
+    #end if
+    #if str($shp.fill_alpha) != '':
+    fill_alpha=$shp.fill_alpha,
+    #end if
+    #if str($shp.groups) != '':
+        #set $groups_list = [str(x.strip()) for x in str($shp.groups).split(',')]
+    groups=$groups_list,
+    #end if
+    #if str($shp.cmap_or_palette_condi.color_map_type) == 'palette':
+        #set $palette_list = [str(x.strip()) for x in str($shp.cmap_or_palette_condi.palette).split(',')]
+    palette=$palette_list,
+    #end if
+
+    #if str($shp.outline_condi.outline_type) == 'no':
+    outline_width=None,
+    outline_color=None,
+    outline_alpha=None,
+    #else if str($shp.outline_condi.outline_type) == 'yes':
+    outline_width=$shp.outline_condi.outline_width1,
+    outline_color='$shp.outline_condi.outline_color1',
+    outline_alpha=$shp.outline_condi.outline_alpha1,
+    #else if str($shp.outline_condi.outline_type) == 'yes2':
+    outline_width=[$shp.outline_condi.outline_width1, $shp.outline_condi.outline_width2],
+    outline_color=['$shp.outline_condi.outline_color1', '$shp.outline_condi.outline_color2'],
+    outline_alpha=[$shp.outline_condi.outline_alpha1, $shp.outline_condi.outline_alpha2],
+    #end if
+
+    #if str($shp.cmap_or_palette_condi.color_map_type) == 'cmap':
+        #set $cmap_list = [str(x.strip()) for x in str($shp.cmap_or_palette_condi.cmap).split(',')]
+    cmap=$cmap_list,
+    #end if
+    #if str($shp.normalize_condi.normalize) == 'yes':
+    norm=Normalize(
+        vmin=$shp.normalize_condi.vmin if str($shp.normalize_condi.vmin) != '' else None,
+        vmax=$shp.normalize_condi.vmax if str($shp.normalize_condi.vmax) != '' else None,
+        clip=$shp.normalize_condi.clip
+    ),
+    #end if
+    scale=$shp.scale,
+    #if $shp.method and str($shp.method) != 'None':
+    method='$shp.method',
+    #else:
+    method=None,
+    #end if
+    #if $shp.table_name:
+    table_name='$shp.table_name',
+    #else
+    table_name=None,
+    #end if
+    #if $shp.table_layer:
+    table_layer='$shp.table_layer',
+    #else
+    table_layer=None,
+    #end if
+    #if $shp.shape and str($shp.shape) != 'None':
+    shape='$shp.shape',
+    #else:
+    shape=None,
+    #end if
+)
+#end for
+
+## Show the plot
+spdata.pl.show(
+    #if $show_params.coordinate_systems:
+        #set $coordinate_systems_list = [str(x.strip()) for x in str($show_params.coordinate_systems).split(',')]
+    coordinate_systems=$coordinate_systems_list,
+    #end if
+    figsize=($show_params.figsize_width, $show_params.figsize_height),
+    dpi=$show_params.dpi,
+    ncols=$show_params.ncols,
+    #if str($show_params.legend_fontsize) != '':
+    legend_fontsize=$show_params.legend_fontsize,
+    #end if
+    legend_fontweight='$show_params.legend_fontweight',
+    legend_loc='$show_params.legend_loc',
+    na_in_legend=$show_params.na_in_legend,
+    #if $show_params.title:
+    title='$show_params.title',
+    #end if
+    share_extent=$show_params.share_extent,
+    save='plot.${show_params.format}'
+)
+
+print("Plot saved successfully")
+        </configfile>
+    </configfiles>
+    <inputs>
+        <expand macro="input_spatialdata"/>
+        <repeat name="render_images" min="0" title="Render Images">
+                <param name="image_element" type="text" optional="true" label="Image element name" help="Name of the image element to render. Leave empty to render all images.">
+                    <expand macro="sanitize_query"/>
+                </param>
+                <param name="channel" type="text" optional="true" label="Channel(s)" help="Comma-separated list of channel names or indices to plot. Leave empty for all channels.">
+                    <expand macro="sanitize_query"/>
+                </param>
+                <expand macro="cmap_or_palette_condi"/>
+                <expand macro="normalize_condi"/>
+                <param name="alpha" type="float" value="1.0" min="0.0" max="1.0" label="Alpha (opacity)" help="Transparency level (0=transparent, 1=opaque)"/>
+                <param name="scale" type="text" optional="true" label="Scale" help="Resolution control: leave empty for auto, 'full' for highest resolution, or specify a scale name. Please note that full resolution, takes more time to render.">
+                    <expand macro="sanitize_query"/>
+                </param>
+        </repeat>
+
+        <repeat name="render_labels" min="0" title="Render Labels">
+                <param name="labels_element" type="text" optional="true" label="Labels element name" help="Name of the labels element to render. Leave empty to render all labels.">
+                    <expand macro="sanitize_query"/>
+                </param>
+                <expand macro="param_color"/>
+                <param name="groups" type="text" optional="true" label="Groups to show" help=" When using color and the key represents discrete labels, groups can be used to show only a subset of them. Other values are set to NA. The list can contain multiple discrete labels to be visualized.">
+                    <expand macro="sanitize_query"/>
+                </param>
+                <expand macro="cmap_or_palette_condi"/>
+                <param name="contour_px" type="integer" value="3" min="0" label="Contour width (pixels)" help="Width of contour to draw for each segment. 0 fills entire segment."/>
+                <expand macro="normalize_condi"/>
+                <param name="outline_alpha" type="float" value="0.0" min="0.0" max="1.0" label="Alpha value for the outline of the labels" help=" Invisible by default." />
+                <param name="fill_alpha" type="float" value="0.4" min="0.0" max="1.0" label="Alpha value for the fill of the labels."/>
+                <param name="scale" type="text" optional="true" label="Scale" help="Resolution control: leave empty for auto, 'full' for highest resolution, or specify a scale name. Please note that full resolution, takes more time to render.">
+                    <expand macro="sanitize_query"/>
+                </param>
+                <expand macro="param_table_name" value="" optional="true" help="Name of table containing color columns"/>
+                <expand macro="param_table_layer"/>
+        </repeat>
+
+        <repeat name="render_points" min="0" title="Render Points">
+                <param name="points_element" type="text" optional="true" label="Points element name" help="Name of the points element to render. Leave empty to render all points.">
+                    <expand macro="sanitize_query"/>
+                </param>
+                <expand macro="param_color"/>
+                <param name="alpha" type="float" optional="true" min="0.0" max="1.0" label="Alpha (opacity)"/>
+                <param name="groups" type="text" optional="true" label="Groups to show" help=" When using color and the key represents discrete labels, groups can be used to show only a subset of them. Other values are set to NA. The list can contain multiple discrete labels to be visualized.">
+                    <expand macro="sanitize_query"/>
+                </param>
+                <expand macro="cmap_or_palette_condi"/>
+                <expand macro="normalize_condi"/>
+                <param name="size" type="float" value="1.0" min="0.0" label="Point size"/>
+                <expand macro="param_rendering_method"/>
+                <expand macro="param_table_name" value="" optional="true" help="Name of table containing color columns"/>
+                <expand macro="param_table_layer"/>
+        </repeat>
+
+        <repeat name="render_shapes" min="0" title="Render Shapes">
+                <param name="shapes_element" type="text" optional="true" label="Shapes element name" help="Name of the shapes element to render. Leave empty to render all shapes.">
+                    <expand macro="sanitize_query"/>
+                </param>
+                <expand macro="param_color"/>
+                <param name="fill_alpha" type="float" optional="true" min="0.0" max="1.0" label="Fill alpha" help="By default, it is set to 1.0 or, if a color is given that implies an alpha, that value is used for fill_alpha. If an alpha channel is present in a cmap passed by the user, fill_alpha will overwrite the value present in the cmap."/>
+                <param name="groups" type="text" optional="true" label="Groups to show" help=" When using color and the key represents discrete labels, groups can be used to show only a subset of them. Other values are set to NA. The list can contain multiple discrete labels to be visualized.">
+                    <expand macro="sanitize_query"/>
+                </param>
+                <expand macro="cmap_or_palette_condi"/>
+                <conditional name="outline_condi">
+                    <param name="outline_type" type="select" label="Shape outline type">
+                        <option value="no">No outline</option>
+                        <option value="yes">Yes, one outline</option>
+                        <option value="yes2">Yes, two outlines</option>
+                    </param>
+                    <when value="no"/>
+                    <when value="yes">
+                        <param name="outline_width1" type="float" optional="false" value="1.5" min="0.0" label="Outline width"/>
+                        <param name="outline_color1" type="text" optional="false" value="#000000" label="Outline color" help="Color name or hex code">
+                            <expand macro="sanitize_query"/>
+                        </param>
+                        <param name="outline_alpha1" type="float" optional="false" value="1.0" min="0.0" max="1.0" label="Outline alpha"/>
+                    </when>
+                    <when value="yes2">
+                        <param name="outline_width1" type="float" optional="false" value="1.5" min="0.0" label="First outline width"/>
+                        <param name="outline_color1" type="text" optional="false" value="#000000" label="First outline color" help="Color name or hex code">
+                            <expand macro="sanitize_query"/>
+                        </param>
+                        <param name="outline_alpha1" type="float" optional="false" value="1.0" min="0.0" max="1.0" label="First outline alpha"/>
+                        <param name="outline_width2" type="float" optional="false" value="0.5" min="0.0" label="Second outline width"/>
+                        <param name="outline_color2" type="text" optional="false" value="#ffffff" label="Second outline color" help="Color name or hex code">
+                            <expand macro="sanitize_query"/>
+                        </param>
+                        <param name="outline_alpha2" type="float" optional="false" value="1.0" min="0.0" max="1.0" label="Second outline alpha"/>
+                    </when>
+                </conditional>
+                <expand macro="normalize_condi"/>
+                <param name="scale" type="float" min="0" value="1.0" label="Scale factor" help="Value to scale circles"/>
+                <expand macro="param_rendering_method" help="When Auto, the method is chosen based on the size of the data.">
+                    <option value="None">Auto</option>
+                </expand>
+                <expand macro="param_table_name" value="" optional="true"/>
+                <expand macro="param_table_layer"/>
+                <param name="shape" type="select" optional="true" label="Convert shapes to" help="If Auto, the shapes are rendered as they are">
+                    <option value="None">Keep original shapes</option>
+                    <option value="circle">Circle</option>
+                    <option value="hex">Hexagon</option>
+                    <option value="visium_hex">Visium hexagon (adjacent)</option>
+                    <option value="square">Square</option>
+                </param>
+        </repeat>
+
+        <section name="show_params" title="Plot Display Parameters" expanded="true">
+            <param name="coordinate_systems" type="text" optional="true" label="Coordinate system(s)" help="Comma-separated list of coordinate systems to plot. Leave empty for all.  If a coordinate system doesn't contain any relevant elements (as specified in the render_* calls), it is automatically not plotted.">
+                <expand macro="sanitize_query"/>
+            </param>
+            <param name="figsize_width" type="float" value="6.4" min="0.1" label="Figure width (inches)"/>
+            <param name="figsize_height" type="float" value="4.8" min="0.1" label="Figure height (inches)"/>
+            <param name="dpi" type="integer" value="100" min="1" label="DPI (resolution)" help="Dots per inch for the output image"/>
+            <param name="ncols" type="integer" value="4" min="1" label="Number of columns"/>
+            <param name="legend_fontsize" type="integer" optional="true" min="1" label="Legend font size"/>
+            <param name="legend_fontweight" type="select" label="Legend font weight">
+                <option value="bold" selected="true">Bold</option>
+                <option value="normal">Normal</option>
+                <option value="light">Light</option>
+            </param>
+            <param name="legend_loc" type="select" label="Legend location">
+                <option value="right margin" selected="true">Right margin</option>
+                <option value="upper right">Upper right</option>
+                <option value="upper left">Upper left</option>
+                <option value="lower left">Lower left</option>
+                <option value="lower right">Lower right</option>
+                <option value="center">Center</option>
+            </param>
+            <param name="na_in_legend" type="boolean" truevalue="True" falsevalue="False" checked="true" label="Show NA values in legend?"/>
+            <param name="title" type="text" optional="true" label="Plot title" help="If not provided the plot will have the name of the coordinate system as title..">
+                <expand macro="sanitize_query"/>
+            </param>
+            <param name="share_extent" type="boolean" truevalue="True" falsevalue="False" checked="true" label="Share extent across subplots?"/>
+            <param name="format" type="select" label="Image format">
+                <option value="eps">EPS</option>
+                <option value="jpg" selected="true">JPG</option>
+                <option value="pdf">PDF</option>
+                <option value="png">PNG</option>
+                <option value="svg">SVG</option>
+                <option value="tiff">TIFF</option>
+            </param>
+        </section>
+    </inputs>
+    <outputs>
+        <data name="plot_output" format="jpg" from_work_dir="figures/plot.jpg" label="${tool.name} on ${on_string}: plot">
+            <change_format>
+                <when input="show_params.format" value="eps" format="eps"/>
+                <when input="show_params.format" value="jpg" format="jpg"/>
+                <when input="show_params.format" value="pdf" format="pdf"/>
+                <when input="show_params.format" value="png" format="png"/>
+                <when input="show_params.format" value="svg" format="svg"/>
+                <when input="show_params.format" value="tiff" format="tiff"/>
+            </change_format>
+        </data>
+    </outputs>
+    <tests>
+        <!-- test 1 - render images -->
+        <test>
+            <param name="input_spatialdata" location="https://zenodo.org/records/18746346/files/xenium_spatialdata.spatialdata.zip"/>
+            <repeat name="render_images">
+                <param name="image_element" value="he_image"/>
+            </repeat>
+            <assert_stdout>
+                <has_text text="spdata.pl.render_images"/>
+                <has_text text="element=&apos;he_image&apos;"/>
+            </assert_stdout>
+            <output name="plot_output" ftype="jpg">
+                <assert_contents>
+                    <has_image_center_of_mass center_of_mass="83,245" eps="5"/>
+                    <has_image_channels channels="3"/>
+                    <has_image_height height="491"/>
+                    <has_image_width width="174"/>
+                </assert_contents>
+            </output>
+        </test>
+        <!-- test 2 - render labels -->
+        <test>
+            <param name="input_spatialdata" location="https://zenodo.org/records/18746346/files/xenium_spatialdata.spatialdata.zip"/>
+            <repeat name="render_labels">
+                <param name="labels_element" value="cell_labels"/>
+                <param name="color" value="total_counts"/>
+                <param name="contour_px" value="2"/>
+                <param name="outline_alpha" value="0.5"/>
+                <param name="fill_alpha" value="0.5"/>
+            </repeat>
+            <assert_stdout>
+                <has_text text="spdata.pl.render_labels"/>
+                <has_text text="element=&apos;cell_labels&apos;"/>
+                <has_text text="color=&apos;total_counts&apos;"/>
+                <has_text text="contour_px=2"/>
+                <has_text text="outline_alpha=0.5"/>
+                <has_text text="fill_alpha=0.5"/>
+            </assert_stdout>
+            <output name="plot_output" ftype="jpg">
+                <assert_contents>
+                    <has_image_center_of_mass center_of_mass="155,245" eps="5"/>
+                    <has_image_channels channels="3"/>
+                    <has_image_height height="491"/>
+                    <has_image_width width="320"/>
+                </assert_contents>
+            </output>
+        </test>
+        <!-- test 3 - render points -->
+        <test>
+            <param name="input_spatialdata" location="https://zenodo.org/records/18746346/files/merscope_spatialdata.spatialdata.zip"/>
+            <repeat name="render_points">
+                <param name="points_element" value="slide_name_region_transcripts"/>
+                <param name="color" value="fov"/>
+                <param name="alpha" value="0.7"/>
+                <param name="size" value="2.0"/>
+            </repeat>
+            <assert_stdout>
+                <has_text text="spdata.pl.render_points"/>
+                <has_text text="element=&apos;slide_name_region_transcripts&apos;"/>
+                <has_text text="color=&apos;fov&apos;"/>
+                <has_text text="alpha=0.7"/>
+                <has_text text="size=2.0"/>
+            </assert_stdout>
+            <output name="plot_output" ftype="jpg">
+                <assert_contents>
+                    <has_image_center_of_mass center_of_mass="295, 245" eps="10"/>
+                    <has_image_channels channels="3"/>
+                    <has_image_height height="491"/>
+                    <has_image_width width="586"/>
+                </assert_contents>
+            </output>
+        </test>
+        <!-- test 4 - render shapes -->
+        <test>
+            <param name="input_spatialdata" location="https://zenodo.org/records/18746346/files/merscope_spatialdata.spatialdata.zip"/>
+            <repeat name="render_shapes">
+                <param name="shapes_element" value="slide_name_region_polygons"/>
+                <param name="color" value="EntityID"/>
+                <param name="fill_alpha" value="0.3"/>
+                <conditional name="outline_condi">
+                    <param name="outline_type" value="yes"/>
+                    <param name="outline_width1" value="1.0"/>
+                    <param name="outline_color1" value="#ff0000"/>
+                    <param name="outline_alpha1" value="0.8"/>
+                </conditional>
+            </repeat>
+            <assert_stdout>
+                <has_text text="spdata.pl.render_shapes"/>
+                <has_text text="element=&apos;slide_name_region_polygons&apos;"/>
+                <has_text text="color=&apos;EntityID&apos;"/>
+                <has_text text="fill_alpha=0.3"/>
+                <has_text text="outline_width=1.0"/>
+                <has_text text="outline_color=&apos;#ff0000&apos;"/>
+                <has_text text="outline_alpha=0.8"/>
+            </assert_stdout>
+            <output name="plot_output" ftype="jpg">
+                <assert_contents>
+                    <has_image_center_of_mass center_of_mass="290, 247" eps="5"/>
+                    <has_image_channels channels="3"/>
+                    <has_image_height height="491"/>
+                    <has_image_width width="582"/>
+                </assert_contents>
+            </output>
+        </test>
+        <!-- test 5 - combination: image + labels (xenium) -->
+        <test>
+            <param name="input_spatialdata" location="https://zenodo.org/records/18746346/files/xenium_spatialdata.spatialdata.zip"/>
+            <repeat name="render_images">
+                <param name="image_element" value="morphology_focus"/>
+            </repeat>
+            <repeat name="render_labels">
+                <param name="labels_element" value="cell_labels"/>
+                <param name="contour_px" value="1"/>
+                <param name="outline_alpha" value="0.7"/>
+                <param name="fill_alpha" value="0.0"/>
+            </repeat>
+            <assert_stdout>
+                <has_text text="spdata.pl.render_images"/>
+                <has_text text="element=&apos;morphology_focus&apos;"/>
+                <has_text text="spdata.pl.render_labels"/>
+                <has_text text="element=&apos;cell_labels&apos;"/>
+            </assert_stdout>
+            <output name="plot_output" ftype="jpg">
+                <assert_contents>
+                    <has_image_center_of_mass center_of_mass="81, 247" eps="5"/>
+                    <has_image_channels channels="3"/>
+                    <has_image_height height="491"/>
+                    <has_image_width width="248"/>
+                </assert_contents>
+            </output>
+        </test>
+        <!-- test 6 - combination: points + shapes (merscope) -->
+        <test>
+            <param name="input_spatialdata" location="https://zenodo.org/records/18746346/files/merscope_spatialdata.spatialdata.zip"/>
+            <repeat name="render_points">
+                <param name="points_element" value="slide_name_region_transcripts"/>
+                <param name="alpha" value="0.5"/>
+                <param name="size" value="1.5"/>
+            </repeat>
+            <repeat name="render_shapes">
+                <param name="shapes_element" value="slide_name_region_polygons"/>
+                <param name="fill_alpha" value="0.0"/>
+                <conditional name="outline_condi">
+                    <param name="outline_type" value="yes"/>
+                    <param name="outline_width1" value="0.5"/>
+                    <param name="outline_color1" value="#ffffff"/>
+                    <param name="outline_alpha1" value="1.0"/>
+                </conditional>
+            </repeat>
+            <assert_stdout>
+                <has_text text="spdata.pl.render_points"/>
+                <has_text text="element=&apos;slide_name_region_transcripts&apos;"/>
+                <has_text text="spdata.pl.render_shapes"/>
+                <has_text text="element=&apos;slide_name_region_polygons&apos;"/>
+            </assert_stdout>
+            <output name="plot_output" ftype="jpg">
+                <assert_contents>
+                    <has_image_center_of_mass center_of_mass="245, 244" eps="5"/>
+                    <has_image_channels channels="3"/>
+                    <has_image_height height="491"/>
+                    <has_image_width width="492"/>
+                </assert_contents>
+            </output>
+        </test>
+        <!-- test 7 - combination: image + points + shapes (merscope) -->
+        <test>
+            <param name="input_spatialdata" location="https://zenodo.org/records/18746346/files/merscope_spatialdata.spatialdata.zip"/>
+            <repeat name="render_images">
+                <param name="image_element" value="slide_name_region_z3"/>
+            </repeat>
+            <repeat name="render_points">
+                <param name="points_element" value="slide_name_region_transcripts"/>
+                <param name="alpha" value="0.6"/>
+                <param name="size" value="2.0"/>
+            </repeat>
+            <repeat name="render_shapes">
+                <param name="shapes_element" value="slide_name_region_polygons"/>
+                <param name="fill_alpha" value="0.0"/>
+                <conditional name="outline_condi">
+                    <param name="outline_type" value="yes"/>
+                    <param name="outline_width1" value="1.0"/>
+                    <param name="outline_color1" value="#00ff00"/>
+                    <param name="outline_alpha1" value="0.8"/>
+                </conditional>
+            </repeat>
+            <assert_stdout>
+                <has_text text="spdata.pl.render_images"/>
+                <has_text text="element=&apos;slide_name_region_z3&apos;"/>
+                <has_text text="spdata.pl.render_points"/>
+                <has_text text="element=&apos;slide_name_region_transcripts&apos;"/>
+                <has_text text="spdata.pl.render_shapes"/>
+                <has_text text="element=&apos;slide_name_region_polygons&apos;"/>
+            </assert_stdout>
+            <output name="plot_output" ftype="jpg">
+                <assert_contents>
+                    <has_image_center_of_mass center_of_mass="242, 244" eps="5"/>
+                    <has_image_channels channels="3"/>
+                    <has_image_height height="491"/>
+                    <has_image_width width="492"/>
+                </assert_contents>
+            </output>
+        </test>
+    </tests>
+    <help><![CDATA[
+**What it does**
+
+This tool creates rich static plots from SpatialData objects. It provides comprehensive visualization capabilities for spatial omics data, including images, labels (segmentation masks), point data (e.g., transcripts), and geometric shapes (e.g., cell boundaries).
+
+-----
+
+**Rendering Options**
+
+The tool supports four types of spatial elements:
+
+**1. Images**: Render microscopy images, H&E stains, or fluorescence channels
+   - Select specific channels or view all
+   - Apply colormaps and adjust transparency
+   - Control resolution and rendering quality
+
+**2. Labels**: Visualize segmentation masks (cells, nuclei, tissues)
+   - Color by categorical or continuous variables from annotation tables
+   - Adjust contour width and fill transparency
+   - Show only specific groups/categories
+
+**3. Points**: Display point-based data (e.g., transcript locations)
+   - Color by features or metadata
+   - Adjust point size and transparency
+   - Choose between matplotlib (smaller datasets) or datashader (large datasets) rendering
+
+**4. Shapes**: Render geometric shapes (circles, polygons, boundaries)
+   - Color by annotations or use solid colors
+   - Control outline and fill properties
+   - Convert shapes to standard geometries (circles, hexagons, squares)
+
+-----
+
+**Display Parameters**
+
+- **Coordinate Systems**: Select which spatial coordinate systems to visualize
+- **Figure Layout**: Control subplot arrangement, figure size, and resolution
+- **Legend**: Customize font, position, and content
+- **Title**: Add custom titles to plots
+
+-----
+
+**Usage Tips**
+
+1. **Layer Multiple Elements**: Enable multiple render options (e.g., images + labels + points) to create overlay visualizations
+2. **Color by Annotations**: Use the 'color' parameter to visualize gene expression or cell type labels from annotation tables
+3. **Performance**: For large datasets, consider using datashader rendering method for points and shapes
+4. **Resolution**: Use 'scale' parameter to balance between rendering speed and image quality
+
+-----
+
+**Output**
+
+The tool generates a static plot image in the selected format (JPG, PNG, PDF, SVG, EPS, or TIFF) containing the rendered visualization(s). Multiple coordinate systems will be displayed as separate subplots arranged in a grid.
+
+-----
+
+**More Information**
+
+- `SpatialData Plot documentation <https://spatialdata.scverse.org/projects/plot/en/stable/>`__
+- `SpatialData documentation <https://spatialdata.scverse.org/>`__
+
+    ]]></help>
+    <expand macro="citations" />
+</tool>
\ No newline at end of file