Skip to content

add bellavista prepare #6946

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
May 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions tools/bellavista/.shed.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
name: bellavista
owner: iuc
description: Open-Source Visualization for Imaging-Based Spatial Transcriptomics
homepage_url: https://github.com/pkosurilab/BellaVista
long_description: |
BellaVista is an open-source Python package developed for 10x Genomics Xenium, Vizgen MERSCOPE, and custom (home-built) MERFISH datasets utilizing napari for interactive data exploration.
remote_repository_url: https://github.com/galaxyproject/tools-iuc/tree/master/tools/bellavista
type: unrestricted
categories:
- Single Cell
- Spatial Omics
- Transcriptomics
- Imaging
auto_tool_repositories:
name_template: "{{ tool_id }}"
description_template: "Wrapper for {{ tool_name }}."
74 changes: 74 additions & 0 deletions tools/bellavista/bellavista.bash
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#!/usr/bin/bash

# turn off visualization
sed -i 's/"plot_image": true,/"plot_image": false,/g' config.json
sed -i 's/"plot_transcripts": true,/"plot_transcripts": false,/g' config.json
sed -i 's/"plot_cell_seg": true,/"plot_cell_seg": false,/g' config.json
sed -i 's/"plot_nuclear_seg": true,/"plot_nuclear_seg": false,/g' config.json
sed -i 's/"plot_allgenes": true,/"plot_allgenes": false,/g' config.json

# start time
START_TIME=$(date +%s)

echo "Time limit set to ${TIME_LIMIT_SECONDS} seconds"

touch './bellavista.log'
/opt/bellavista/bellavista/bin/bellavista "./config.json" 2>&1 | tee './bellavista.log' &
TOOL_PID=$!

# function to handle complete cleanup
cleanup() {
# Kill all processes
pkill -P $TOOL_PID 2>/dev/null || true
kill -9 $TOOL_PID 2>/dev/null || true

# Make sure any background processes from this script are terminated
jobs -p | xargs -r kill -9 2>/dev/null || true

echo "Bella Vista stopped."
exit 0
}

# Set trap to ensure cleanup on script exit
trap cleanup EXIT INT TERM

while sleep 1; do
# Check if the job is finished
if grep -q "Bella Vista input files created!" './bellavista.log' && \
[ -d "./BellaVista_output/OMEzarrImages" ] && \
[ -f "./BellaVista_output/OMEzarrImages/.zgroup" ]; then
echo "Bella Vista input files created! Stopping the tool..."
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you need an additional safe-guards here.

What happens if this string never appears? Should we kill the tool after X hours? The X hours can be taken optionally from an ENV var, so the admin can overwrite it?

Also would it make sense to actually check if the result file exist?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a timeout to the script.
For the output I'm not sure how to check. the main output would be the image in zarr format.
Now I just check if the directory and .zgroup file exists

kill -INT $TOOL_PID
sleep 1
# If still running, use stronger signal
if ps -p $TOOL_PID > /dev/null; then
kill -9 $TOOL_PID
fi
break
elif grep -q "Bella Vista input files created!" './bellavista.log'; then
echo "Log indicates completion but output directory structure is incomplete. Continuing..."
fi

# Check timeout
CURRENT_TIME=$(date +%s)
ELAPSED_TIME=$((CURRENT_TIME - START_TIME))

if [[ "$ELAPSED_TIME" =~ ^[0-9]+$ ]] && [[ "$TIME_LIMIT_SECONDS" =~ ^[0-9]+$ ]]; then
if [ $ELAPSED_TIME -ge $TIME_LIMIT_SECONDS ]; then
echo "Time limit of ${TIME_LIMIT_SECONDS} seconds reached. Please contact admins. Stopping the tool..."
kill -INT $TOOL_PID
sleep 1
# If still running, use SIGKILL (force quit)
if ps -p $TOOL_PID > /dev/null; then
kill -9 $TOOL_PID
fi
break
fi
fi
done

# Final cleanup
cleanup

# check this line in test. It should not be printed
echo "Script completed."
213 changes: 213 additions & 0 deletions tools/bellavista/bellavista_prepare.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
<tool id="bellavista_prepare" name="Bellavista" version="@TOOL_VERSION@+galaxy@VERSION_SUFFIX@" profile="@PROFILE@">
<description>Prepare large images for bellavista visualizer</description>
<creator>
<organization name="European Galaxy Team" url="https://galaxyproject.org/eu/" />
<person givenName="Amirhossein" familyName="Naghsh Nilchi" email="[email protected]" />
<person givenName="Pavan" familyName="Videm" email="[email protected]" />
<person givenName="Björn" familyName="Grüning" email="[email protected]" />
</creator>
<macros>
<import>macros.xml</import>
</macros>
<expand macro="requirements"/>
<command detect_errors="exit_code"><![CDATA[
export TIME_LIMIT_SECONDS=$timeout &&
export BELLAVISTA_DIR=`pwd`/input/ &&
mkdir -p 'input' 'input/BellaVista_output' &&
chmod -R 777 'input/' &&
#if $technology_conditional.plot_genes.plot_transcripts == "true":
ln -s '$technology_conditional.plot_genes.transcript_filename' './input/${technology_conditional.plot_genes.transcript_filename.element_identifier}.${technology_conditional.plot_genes.transcript_filename.ext}' &&
#end if
#for $image in $technology_conditional.images:
ln -s '$image' 'input/${image.element_identifier}.${image.ext}' &&
#end for
ln -s '$bellavista_config_file' './input/config.json' &&
#if $technology_conditional.plot_cell_segmentation.plot_cell_seg == "true":
ln -s '$technology_conditional.plot_cell_segmentation.cell_segmentation' './input/${technology_conditional.plot_cell_segmentation.cell_segmentation.element_identifier}.${technology_conditional.plot_cell_segmentation.cell_segmentation.ext}' &&
#end if
#if $technology_conditional.plot_nuclear_segmentation.plot_nuclear_seg == "true":
ln -s '$technology_conditional.plot_nuclear_segmentation.nuclear_segmentation' './input/${technology_conditional.plot_nuclear_segmentation.nuclear_segmentation.element_identifier}.${technology_conditional.plot_nuclear_segmentation.nuclear_segmentation.ext}' &&
#end if
#if $technology_conditional.technology == "MERSCOPE":
ln -s '$technology_conditional.um_to_px_transform' './input/micron_to_mosaic_pixel_transform.csv' &&
#end if
cat ./input/config.json &&

cd "\$BELLAVISTA_DIR" &&
bash '$__tool_directory__/bellavista.bash' &&
cd .. &&

tar -czf 'bellavista.tar.gz' 'input/BellaVista_output'
]]></command>
<configfiles>
<configfile name="bellavista_config_file"><![CDATA[
{
"system": "$technology",
"data_folder": "./",
"create_bellavista_inputs": true,

"visualization_parameters": {
"plot_image": true,
#if $technology_conditional.plot_genes.plot_transcripts == "true":
"plot_transcripts": true,
#else
"plot_transcripts": false,
#end if
#if $technology_conditional.plot_cell_segmentation.plot_cell_seg == "true":
"plot_cell_seg": true,
#else
"plot_cell_seg": false,
#end if
#if $technology_conditional.plot_nuclear_segmentation.plot_nuclear_seg == "true":
"plot_nuclear_seg": true,
#else
"plot_nuclear_seg": false,
#end if
"genes_visible_on_startup": false,
#if $technology_conditional.plot_genes.plot_all_genes.all_genes == "Yes":
"plot_allgenes": true,
#else
"plot_allgenes": false,
#set $gene_list = ['"' + str(x.strip()) + '"' for x in str($technology_conditional.plot_genes.plot_all_genes.selected_genes).split(',')]
#set $genes = ','.join($gene_list)
"selected_genes": $genes,
#end if
"rotate_angle": $rotate_angle,
"transcript_point_size": $transcript_point_size
},

"input_files": {
#set $last_index = len($technology_conditional.images) - 1
"images": [
#for $i in range(len($images)):
"$images[$i].element_identifier.$images[$i].ext"#if $i != $last_index#,#end if
#end for
],
#if $technology_conditional.plot_cell_segmentation.plot_cell_seg == "true":
"cell_segmentation": "${technology_conditional.plot_cell_segmentation.cell_segmentation.element_identifier}.${technology_conditional.plot_cell_segmentation.cell_segmentation.ext}",
#end if
#if $technology_conditional.plot_nuclear_segmentation.plot_nuclear_seg == "true":
"nuclear_segmentation": "${technology_conditional.plot_nuclear_segmentation.nuclear_segmentation.element_identifier}.${technology_conditional.plot_nuclear_segmentation.nuclear_segmentation.ext}",
#end if
#if $technology_conditional.technology == "MERSCOPE":
"um_to_px_transform": "micron_to_mosaic_pixel_transform.csv",
#end if
#if $technology_conditional.plot_genes.plot_transcripts == "true":
"transcript_filename": "${technology_conditional.plot_genes.transcript_filename.element_identifier}.${technology_conditional.plot_genes.transcript_filename.ext}",
#end if
"z_plane": $technology_conditional.z_plane
}
}
]]></configfile>
</configfiles>
<inputs>
<conditional name="technology_conditional">
<param name="technology" type="select" label="Spatial transcriptomic technology">
<option value="Xenium">Xenium</option>
<option value="MERSCOPE" selected="true">MERSCOPE</option>
</param>
<when value="Xenium">
<expand macro="common_param"/>
</when>
<when value="MERSCOPE">
<expand macro="common_param">
<param name="um_to_px_transform" type="data" format="csv" optional="false" label="micron to pixel transformations"/>
</expand>
</when>
</conditional>
<section name="advanced_output" title="Advanced output options">
<param name="config" type="boolean" truevalue="True" falsevalue="False" checked="true" label="Output config file?"/>
</section>
<param name="timeout" type="hidden" min="0" max="21600" value="3600" label="timeout" help="hidden input to set timeout in seconds" />
</inputs>
<outputs>
<data name="bellavista_output" format="tar.gz" label="${tool.name} on ${on_string}: Bellavista prepared inputs" from_work_dir="./bellavista.tar.gz" />
<data name="config" format="json" label="${tool.name} on ${on_string}: config file" from_work_dir="input/config.json">
<filter>advanced_output['config']</filter>
</data>
</outputs>
<tests>
<test expect_num_outputs="2">
<conditional name="technology_conditional">
<param name="technology" value="MERSCOPE"/>
<param name="images" location="https://zenodo.org/records/15319018/files/mosaic_PolyT_z3.tif,https://zenodo.org/records/15319018/files/mosaic_PolyT_z4.tif"/>
<conditional name="plot_genes">
<param name="plot_transcripts" value="true"/>
<param name="transcript_filename" location="https://zenodo.org/records/15319018/files/detected_transcripts.csv"/>
</conditional>
<conditional name="plot_cell_segmentation">
<param name="plot_cell_seg" value="false"/>
</conditional>
<conditional name="plot_nuclear_segmentation">
<param name="plot_nuclear_seg" value="false"/>
</conditional>
<param name="um_to_px_transform" location="https://zenodo.org/records/15319018/files/micron_to_mosaic_pixel_transform.csv"/>
<param name="z_plane" value="3"/>
<param name="transcript_point_size" value="1"/>
<param name="rotate_angle" value="0"/>
</conditional>
<section name="advanced_output">
<param name="config" value="true"/>
</section>
<output name="bellavista_output">
<assert_contents>
<has_archive_member path="input/BellaVista_output/gene_dict.pkl"/>
<has_archive_member path="input/BellaVista_output/OMEzarrImages"/>
<has_archive_member path="input/BellaVista_output/um_to_px_transforms.pkl"/>
</assert_contents>
</output>
<output name="config">
<assert_contents>
<has_text text="MERSCOPE"/>
<has_text text="&quot;create_bellavista_inputs&quot;: true"/>
<has_text text="&quot;plot_cell_seg&quot;: false"/>
</assert_contents>
</output>
<assert_stdout>
<has_text text="Creating Bella Vista input files for Vizgen MERSCOPE"/>
<has_text text="Bella Vista input files created!"/>
<not_has_text text="Script completed."/>
</assert_stdout>
</test>
<test expect_num_outputs="0">
<conditional name="technology_conditional">
<param name="technology" value="MERSCOPE"/>
<param name="images" location="https://zenodo.org/records/15319018/files/mosaic_PolyT_z3.tif,https://zenodo.org/records/15319018/files/mosaic_PolyT_z4.tif"/>
<conditional name="plot_genes">
<param name="plot_transcripts" value="true"/>
<param name="transcript_filename" location="https://zenodo.org/records/15319018/files/detected_transcripts.csv"/>
</conditional>
<conditional name="plot_cell_segmentation">
<param name="plot_cell_seg" value="false"/>
</conditional>
<conditional name="plot_nuclear_segmentation">
<param name="plot_nuclear_seg" value="false"/>
</conditional>
<param name="um_to_px_transform" location="https://zenodo.org/records/15319018/files/micron_to_mosaic_pixel_transform.csv"/>
<param name="z_plane" value="3"/>
<param name="transcript_point_size" value="1"/>
<param name="rotate_angle" value="0"/>
</conditional>
<section name="advanced_output">
<param name="config" value="true"/>
</section>
<param name="timeout" value="1"/>
<assert_stdout>
<has_text text="Time limit of 1 seconds reached. Please contact admins. Stopping the tool..."/>
<has_text text="Bella Vista stopped"/>
<not_has_text text="Script completed."/>
</assert_stdout>
</test>
</tests>
<help><![CDATA[
BellaVista is an open-source visualization tool for imaging-based spatial transcriptomics data. It allows users to visualize and explore spatial transcriptomics data in a user-friendly interface. The tool supports MERSCOPE and Xenium imaging-based spatial transcriptomics technologies.

Users can customize the visualization by selecting specific genes, adjusting image rotation angles, and controlling the size of transcript points. BellaVista also provides options for plotting cell and nuclear segmentation, enhancing the exploration of spatial transcriptomics data.

.. image:: https://raw.githubusercontent.com/pkosurilab/BellaVista/c8129bb8954c92962a87606595c09b35cc414295/images/bellavista_figure.png
:height: 500
:width: 700
]]>
</help>
<expand macro="citations"/>
</tool>
73 changes: 73 additions & 0 deletions tools/bellavista/macros.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<macros>
<token name="@TOOL_VERSION@">0.0.2</token>
<token name="@VERSION_SUFFIX@">0</token>
<token name="@PROFILE@">23.0</token>
<xml name="requirements">
<requirements>
<container type="docker">quay.io/bgruening/bellavista:0.0.2-3</container>
<yield/>
</requirements>
</xml>
<xml name="common_param">
<param name="images" type="data" format="tiff,ome.tiff" multiple="true" optional="false" label="Images"/>
<conditional name="plot_genes">
<param name="plot_transcripts" type="select" label="Plot transcripts?">
<option value="false">No</option>
<option value="true" selected="true">Yes</option>
</param>
<when value="false"></when>
<when value="true">
<param name="transcript_filename" type="data" format="csv,parquet" optional="false" label="transcript spatial locations"/>
<conditional name="plot_all_genes">
<param name="all_genes" type="select" label="Plot all genes?">
<option value="Yes" selected="true">Yes</option>
<option value="No">No</option>
</param>
<when value="Yes"/>
<when value="No">
<param name="selected_genes" type="text" optional="false" value="" label="Comma separated list of custom genes">
<sanitizer>
<valid initial="string.printable">
<remove value="&apos;"/>
</valid>
</sanitizer>
</param>
</when>
</conditional>
</when>
</conditional>
<conditional name="plot_cell_segmentation">
<param name="plot_cell_seg" type="select" label="Plot cell segmentation?">
<option value="false">No</option>
<option value="true" selected="true">Yes</option>
</param>
<when value="false"></when>
<when value="true">
<param name="cell_segmentation" type="data" format="parquet,zarr" optional="false" label="Cell segmentations"/>
</when>
</conditional>
<conditional name="plot_nuclear_segmentation">
<param name="plot_nuclear_seg" type="select" label="Plot nuclear segmentation?">
<option value="false" selected="true">No</option>
<option value="true">Yes</option>
</param>
<when value="false"></when>
<when value="true">
<param name="nuclear_segmentation" type="data" format="parquet,zarr" optional="false" label="Nuclear segmentations"/>
</when>
</conditional>
<yield />
<param name="z_plane" type="integer" min="0" value="0" label="z-plane of image to be visualize"/>
<param name="transcript_point_size" type="integer" min="0" value="1" label="Size of the points representing individual transcripts"/>
<param name="rotate_angle" type="integer" min="-180" max="180" value="0" label="Image rotation angle in degrees"/>
</xml>
<xml name="citations">
<citations>
<citation type="doi">10.1016/j.bpj.2024.11.3199</citation>
<citation type="bibtex">@Manual{github,
title = {Open-source Visualization for Imaging-Based Spatial Transcriptomics},
url = {https://github.com/pkosurilab/BellaVista}}
</citation>
</citations>
</xml>
</macros>