Skip to content
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

New Tools: OMERO get and OMERO filter using ezomero #61

Merged
merged 33 commits into from
Oct 22, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
55b8878
add new tools (omero get and omero filter) and updated the ci/pr pipe…
rmassei Oct 11, 2024
1ee41a8
use conditionals to more explicitely indicate the id required.
lldelisle Oct 11, 2024
85c9889
fix annotation part
lldelisle Oct 11, 2024
a18ab9d
convert omero_get to omero_get_id
lldelisle Oct 11, 2024
6045586
add get_value
lldelisle Oct 11, 2024
4351fdf
add single quotes
lldelisle Oct 11, 2024
f81b04d
Fix bad copy paste
lldelisle Oct 11, 2024
f9e9b42
add tests
lldelisle Oct 11, 2024
a62a925
remove unused f
lldelisle Oct 11, 2024
9293ed3
remove unused function
lldelisle Oct 11, 2024
3385216
fix function name
lldelisle Oct 11, 2024
ecf3085
fix spaces
lldelisle Oct 11, 2024
21e04d4
Merge pull request #3 from lldelisle/improve_omero_get
rmassei Oct 14, 2024
a0511de
Updated all the scripts and xml files according to previous review
rmassei Oct 15, 2024
a9b6b41
correct indentation of omero_filter and omero_get_id
rmassei Oct 15, 2024
fdafaeb
Update omero_filter.py
rmassei Oct 15, 2024
48b09d5
fixed code and xml from omero_filter for correct linting
rmassei Oct 15, 2024
bb43db1
Merge branch 'omero-upload' of github.com:rmassei/mb-galaxy-tools int…
rmassei Oct 15, 2024
cefb3b0
correct image name
rmassei Oct 15, 2024
483f29f
fixed indentation
rmassei Oct 15, 2024
f1665dc
fix the regex of omero_get_value and updated the sheed
rmassei Oct 15, 2024
b34059b
fixed the regex to handle single number plus comma separated numbers
rmassei Oct 15, 2024
904261b
Fix testing in output and omero_get_value.xml
rmassei Oct 15, 2024
0417225
Correct the cheetah sintax in omero_get_value.xml
rmassei Oct 15, 2024
54487c9
Correct the test in omero_get_value.xml - tsv output has 2 rows cons…
rmassei Oct 15, 2024
a720d50
Last corrections to the omero_get_value script to harmonize it with t…
rmassei Oct 16, 2024
707dbdf
add macros
bernt-matthias Oct 21, 2024
f81311b
omero import do not expose password
bernt-matthias Oct 21, 2024
823505a
add requirement macros
bernt-matthias Oct 21, 2024
222d6f7
add host port token
bernt-matthias Oct 21, 2024
16ee24a
bump
bernt-matthias Oct 21, 2024
167214c
add macros file
bernt-matthias Oct 21, 2024
59b96c0
fix macro expansion
bernt-matthias Oct 21, 2024
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
2 changes: 2 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,8 @@ jobs:
DID=$(omero obj new Dataset name='test_dts')
omero obj new ProjectDatasetLink parent=$PID child=$DID
omero import -d $DID .github/dummy-dts-omero
omero tag create --name test_tag --desc 'description of my_tag'
omero tag link Image:1 1
echo "Created the dummy dataset into OMERO"

# download or create large test data via script
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/pr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,8 @@ jobs:
DID=$(omero obj new Dataset name='test_dts')
omero obj new ProjectDatasetLink parent=$PID child=$DID
omero import -d $DID .github/dummy-dts-omero
omero tag create --name test_tag --desc 'description of my_tag'
omero tag link Image:1 1
echo "Created the dummy dataset into OMERO"

# download or create large test data via script
Expand Down
6 changes: 3 additions & 3 deletions tools/omero/.shed.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
categories:
- Imaging
name: omero_upload
description: Import images, region of interest, metadata into an OMERO.server using omero-py
long_description: Tool to import and link different objects into OMERO
description: Interact with an OMERO.server using omero-py and ezomero.
long_description: This set of tool allows to import images and metadata into an OMERO.server.
rmassei marked this conversation as resolved.
Show resolved Hide resolved
owner: ufz
remote_repository_url: https://github.com/Helmholtz-UFZ/galaxy-tools/tree/main/tools/omero
homepage_url: https://github.com/ome/omero-py/
Expand All @@ -13,4 +13,4 @@ suite:
name: "suite_omero_py"
description: "A suite of tools that brings the omero-py and ezomero project into Galaxy."
long_description: |
OMERO.py provides an interface to the OMERO.blitz server.
OMERO.py and ezomero provides an interface to the OMERO.blitz server.
80 changes: 80 additions & 0 deletions tools/omero/omero_filter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import argparse
import csv
import json

import ezomero as ez


def filter_ids_ezo(user, pws, host, port, filter, id, value1, value2=None, tsv_file="filter_list.tsv"):

# Transform the id input in a list of integer
id = id.split(',')
id = list(map(int, id))

# Function to write tabular file from the ezomero output
def write_ids_to_tsv(data, header):
with open(tsv_file, 'a+', newline='') as f:
rmassei marked this conversation as resolved.
Show resolved Hide resolved
f.seek(0)
is_empty = f.tell() == 0 # Check if file is empty
writer = csv.writer(f, delimiter='\t')
if is_empty:
writer.writerow([header]) # Write the header
for item in data:
writer.writerow([item]) # Write each ID

try:
with ez.connect(user, pws, "", host, port, secure=True) as conn:
if filter == "filename":
fn_ids = ez.filter_by_filename(conn, id, value1)
write_ids_to_tsv(fn_ids, [f"Images with filename {value1}"])
rmassei marked this conversation as resolved.
Show resolved Hide resolved
rmassei marked this conversation as resolved.
Show resolved Hide resolved
return fn_ids
elif filter == "KP":
kp_ims = ez.filter_by_kv(conn, id, value1, value2)
write_ids_to_tsv(kp_ims, [f"Images with KV {value1} and {value2}"])
rmassei marked this conversation as resolved.
Show resolved Hide resolved
return kp_ims
elif filter == "tag":
tg_dict = ez.filter_by_tag_value(conn, id, value1)
write_ids_to_tsv(tg_dict, [f"Images with tag {value1}"])
rmassei marked this conversation as resolved.
Show resolved Hide resolved
return tg_dict

else:
raise ValueError(f"Unsupported object type")

except Exception as e:
rmassei marked this conversation as resolved.
Show resolved Hide resolved
print(f"Connection error: {str(e)}")
return None


# Argument parsing
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Fetch and save data as TSV based on object type.")
parser.add_argument("--credential-file", dest="credential_file", type=str, required=True,
help="Credential file (JSON file with username and password for OMERO)")
parser.add_argument('--host', required=True,
help="Host server address.")
parser.add_argument('--port', required=True, type=int,
help='OMERO port')
parser.add_argument('--filter', required=True,
help="Filter type - Filename, Key-Value Pairs, Tag")
parser.add_argument('--id', required=True,
help="List of images IDs")
parser.add_argument('--value1', required=True,
help="First searching values - Filename, Key, Tag")
parser.add_argument('--value2', required=False,
help="Second searching values - Value (necessary just for Key-Value Pairs filter")
parser.add_argument('--tsv_file', default='filter_list.tsv', required=True,
rmassei marked this conversation as resolved.
Show resolved Hide resolved
help="Output TSV file path.")

args = parser.parse_args()

with open(args.credential_file, 'r') as f:
crds = json.load(f)

# Call the main function to get the object and save it as a TSV
filter_ids_ezo(user=crds['username'], pws=crds['password'], host=args.host,
port=args.port,
filter=args.filter,
value1=args.value1,
value2=args.value2,
id=args.id,
tsv_file=args.tsv_file)
102 changes: 102 additions & 0 deletions tools/omero/omero_filter.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<tool id="omero_filter_id" name="OMERO IDs" version="@TOOL_VERSION@+galaxy@VERSION_SUFFIX@"
rmassei marked this conversation as resolved.
Show resolved Hide resolved
profile="20.01" license="MIT">
<description> with ezomero </description>
<macros>
<token name="@TOOL_VERSION@">5.18.0</token>
<token name="@VERSION_SUFFIX@">0</token>
</macros>
<xrefs>
<xref type="bio.tools">omero</xref>
</xrefs>
<requirements>
<requirement type="package" version="3.0.1">ezomero</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_filter.py
rmassei marked this conversation as resolved.
Show resolved Hide resolved
--credential-file '$credentials'
--host $omero_host
--port $omero_port
--filter $filter
--value1 $value1
rmassei marked this conversation as resolved.
Show resolved Hide resolved
--id $did
--tsv_file $tsv
rmassei marked this conversation as resolved.
Show resolved Hide resolved
#if $filter == "KP"
--value2 $value2
#end if

]]></command>
<configfiles>
<configfile name="credentials"><![CDATA[
{
"username": "$__user__.extra_preferences.get('omero_account|username', $test_username)",
"password": "$__user__.extra_preferences.get('omero_account|password', $test_password)"
}
]]></configfile>
</configfiles>
<inputs>
<param name="omero_host" type="text" label="OMERO host URL">
rmassei marked this conversation as resolved.
Show resolved Hide resolved
<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="filter" type="select" optional="true" label="Select filter">
rmassei marked this conversation as resolved.
Show resolved Hide resolved
<option value="filename">Project</option>
<option value="KP">Screen</option>
<option value="tag">Dataset</option>
</param>
<param argument="value1" type="text" optional="false" label="First filter criteria (i.e. filename)"/>
rmassei marked this conversation as resolved.
Show resolved Hide resolved
<param argument="value2" type="text" optional="true" label="Second filter criteria (just valid for KP search)"/>
<param name="did" type="text" optional="false" label="List of images IDs"/>
<param name="test_username" type="hidden" value=""/>
<param name="test_password" type="hidden" value=""/>
</inputs>
<outputs>
<data name="tsv" format="tabular"/>
</outputs>
<tests>
<test>
<param name="omero_host" value="host.docker.internal"/>
<param name="omero_port" value="6064"/>
<param name="filter" value="filename"/>
<param name="value1" value="sample_image_2.jpg"/>
<param name="did" value="1,2"/>
<param name="test_username" value="root"/>
<param name="test_password" value="omero"/>
<output name="tsv" value="output_filter_filename.tsv" ftype="tabular">
<assert_contents>
<has_text text="Images with filename sample_image_2.jpg"/>
<has_text text="2"/>
rmassei marked this conversation as resolved.
Show resolved Hide resolved
</assert_contents>
</output>
</test>
<test>
<param name="omero_host" value="host.docker.internal"/>
<param name="omero_port" value="6064"/>
<param name="filter" value="tag"/>
<param name="value1" value="test_tag"/>
<param name="did" value="1,2"/>
<param name="test_username" value="root"/>
<param name="test_password" value="omero"/>
<output name="tsv" value="output_filter_tag.tsv" ftype="tabular">
<assert_contents>
<has_text text="Images with tag test_tag"/>
<has_text text="1"/>
</assert_contents>
</output>
</test>
</tests>
<help>
Description
-----------

Tool to filter images IDs by filename, Key-Value Pairs and Tag value.
For Key-Value Pairs search, two values are required (Value1 = Key, Value2 = Pair).
IDs are a list of image IDs which can be fetched using the omero_get tool.

</help>
<citations>
<citation type="doi">10.1038/nmeth.1896</citation>
</citations>
</tool>
90 changes: 90 additions & 0 deletions tools/omero/omero_get.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import argparse
import csv
import json

import ezomero as ez


def get_object_ezo(user, pws, host, port, obj_type, id=None, tsv_file="id_list.tsv"):
# Function to write tabular file from the ezomero output
def write_ids_to_tsv(data, header):
with open(tsv_file, 'a+', newline='') as f:
f.seek(0)
is_empty = f.tell() == 0 # Check if file is empty
writer = csv.writer(f, delimiter='\t')
if is_empty:
writer.writerow([header]) # Write the header
for item in data:
writer.writerow([item]) # Write each ID

# Function to write tabular file from a dictionary ezomero output
def write_dict_to_tsv(data, headers):
with open(tsv_file, 'a+', newline='') as f:
f.seek(0)
is_empty = f.tell() == 0 # Check if file is empty
writer = csv.writer(f, delimiter='\t')
if is_empty:
writer.writerow(headers) # Write the headers
for key, value in data.items():
writer.writerow([key, value]) # Write each key-value pair

try:
with ez.connect(user, pws, "", host, port, secure=True) as conn:
if obj_type == "dataset":
ds_ids = ez.get_dataset_ids(conn, project=int(id))
write_ids_to_tsv(ds_ids, "Dataset IDs")
return ds_ids
elif obj_type == "image":
ds_ims = ez.get_image_ids(conn, dataset=int(id))
write_ids_to_tsv(ds_ims, "Image IDs")
return ds_ims
elif obj_type == "annotation":
ma_dict = ez.get_map_annotation(conn, int(id))
write_dict_to_tsv(ma_dict, ["Annotation ID", "Annotation Value"])
rmassei marked this conversation as resolved.
Show resolved Hide resolved
return ma_dict
elif obj_type == "project":
proj_ids = ez.get_project_ids(conn)
write_ids_to_tsv(proj_ids, "Project IDs")
return proj_ids
elif obj_type == "roi":
roi_ids = ez.get_roi_ids(conn, int(id))
write_ids_to_tsv(roi_ids, "ROI IDs")
return roi_ids
elif obj_type == "table":
table = ez.get_table(conn, int(id))
write_dict_to_tsv(table, ["Table ID", "Table Value"])
rmassei marked this conversation as resolved.
Show resolved Hide resolved
return table
else:
raise ValueError(f"Unsupported object type: {obj_type}")

except Exception as e:
print(f"Connection error: {str(e)}")
return None


# Argument parsing
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Fetch and save data as TSV based on object type.")
parser.add_argument("--credential-file", dest="credential_file", type=str,
required=True, help="Credential file (JSON file with username and password for OMERO)")
parser.add_argument('--host', required=True,
help="Host server address.")
parser.add_argument('--port', required=True, type=int,
help='OMERO port')
parser.add_argument('--obj_type', required=True,
help="Type of object to fetch: dataset, image, annotation, project, roi, or table.")
parser.add_argument('--id', required=False,
help="ID of the specific OMERO object.")
parser.add_argument('--tsv_file', default='id_list.tsv', required=True,
rmassei marked this conversation as resolved.
Show resolved Hide resolved
help="Output TSV file path.")
args = parser.parse_args()

with open(args.credential_file, 'r') as f:
crds = json.load(f)

# Call the main function to get the object and save it as a TSV
get_object_ezo(user=crds['username'], pws=crds['password'], host=args.host,
port=args.port,
obj_type=args.obj_type,
id=args.id,
tsv_file=args.tsv_file)
Loading
Loading