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

Adding support to tables #58

Merged
merged 24 commits into from
Nov 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
542a85f
added optional pandas and optional imports + bool var
erickmartins Aug 30, 2022
4437e53
Automated updating coverage badge
erickmartins Aug 30, 2022
35153a7
updated readme for tables
erickmartins Aug 30, 2022
274a0ab
Merge branch 'tables' of https://github.com/TheJacksonLaboratory/ezom…
erickmartins Aug 30, 2022
0f22e0a
Automated updating coverage badge
erickmartins Aug 30, 2022
0000554
signature and docstring for `post_table`
erickmartins Aug 31, 2022
17892ab
Merge branch 'tables' of https://github.com/TheJacksonLaboratory/ezom…
erickmartins Aug 31, 2022
491e675
outline of post_table done
erickmartins Aug 31, 2022
4210cbf
Automated updating coverage badge
erickmartins Aug 31, 2022
ba89eb9
get_table outline
erickmartins Aug 31, 2022
4290b4c
function stubs are all in place
erickmartins Aug 31, 2022
3ef55dd
updated gh action to only run on main
erickmartins Aug 31, 2022
03bcf3d
get_table for pandas
erickmartins Sep 1, 2022
47b3560
get_table done
erickmartins Sep 1, 2022
cf29c5a
post_tables working for pandas
erickmartins Sep 6, 2022
6ed18cb
working for both cases!
erickmartins Sep 6, 2022
7b10432
testing GH action
erickmartins Sep 9, 2022
8bfb8e2
Automated updating coverage badge
erickmartins Sep 9, 2022
c49d8c6
reoganized setup and test files
erickmartins Sep 9, 2022
3a132c8
Merge branch 'tables' of https://github.com/TheJacksonLaboratory/ezom…
erickmartins Sep 9, 2022
3a652c8
minimal table testing
erickmartins Sep 9, 2022
cc540a6
tests passing - no across_groups for post_tables
erickmartins Sep 9, 2022
f8374a1
deleted debug prints
erickmartins Nov 1, 2022
bf86379
catching non-existing and non-table annotations
erickmartins Nov 1, 2022
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: 1 addition & 1 deletion .github/workflows/run_tests_pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
run: |
python -m pip install --upgrade pip
pip install flake8 pytest
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
pip install .[tables]
- name: Test with pytest
run: |
pytest tests/
Expand Down
6 changes: 4 additions & 2 deletions .github/workflows/run_tests_push.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
name: Run Tests on push
on: push
on:
push:
branches: [ main ]
jobs:
test:
runs-on: ubuntu-latest
Expand All @@ -16,7 +18,7 @@ jobs:
run: |
python -m pip install --upgrade pip
pip install flake8 pytest
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
pip install .[tables]
- name: Test with pytest and generate coverage report/badge
run: |
pip install coverage coverage-badge
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ A module with convenience functions for writing Python code that interacts with

# Installation

Just `pip install ezomero` and you should be good to go! The repo contains a `requirements.txt` file with the specific package versions we test `ezomero` with, but any Python>=3.8 and latest `omero-py` and `numpy` _should_ work - note that this package is in active development!
Just `pip install ezomero` and you should be good to go! The repo contains the specific package versions we test `ezomero` with in `setup.py`, but any Python>=3.8 and latest `omero-py` and `numpy` _should_ work - note that this package is in active development!

If you want to use `get_table` and `post_table` to/from Pandas dataframes, you need to install `ezomero[tables]` - that install an optional `pandas` dependency. Installing ezomero without this will default `get_table` and `post_table` to use lists of row lists as their default.

# Usage

Expand Down
4 changes: 2 additions & 2 deletions coverage.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 5 additions & 1 deletion ezomero/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
post_file_annotation,
post_project,
post_screen,
post_roi)
post_roi,
post_table)
from ._gets import (get_image,
get_image_ids,
get_project_ids,
Expand All @@ -37,6 +38,7 @@
get_user_id,
get_original_filepaths,
get_pyramid_levels,
get_table,
get_shape)

__all__ = ['post_dataset',
Expand All @@ -46,6 +48,7 @@
'post_project',
'post_screen',
'post_roi',
'post_table',
'get_image',
'get_image_ids',
'get_project_ids',
Expand All @@ -63,6 +66,7 @@
'get_user_id',
'get_original_filepaths',
'get_pyramid_levels',
'get_table',
'get_shape',
'put_map_annotation',
'filter_by_filename',
Expand Down
91 changes: 89 additions & 2 deletions ezomero/_gets.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,19 @@
import numpy as np
from ._ezomero import do_across_groups
from omero.gateway import FileAnnotationWrapper
from omero import ApiUsageException
from omero import ApiUsageException, InternalException
from omero.model import MapAnnotationI, TagAnnotationI
from omero.rtypes import rint, rlong
from omero.sys import Parameters
from omero.model import enums as omero_enums
from .rois import Point, Line, Rectangle, Ellipse, Polygon, Polyline, Label
import importlib.util
# try importing pandas
if (importlib.util.find_spec('pandas')):
import pandas as pd
has_pandas = True
else:
has_pandas = False


# gets
Expand Down Expand Up @@ -863,7 +870,7 @@ def get_file_annotation(conn, file_ann_id, folder_path=None,
conn : ``omero.gateway.BlitzGateway`` object
OMERO connection.
file_ann_id : int
ID of map annotation to get.
ID of file annotation to get.
folder_path : str
Path where file annotation will be saved. Defaults to local script
directory.
Expand Down Expand Up @@ -1077,6 +1084,50 @@ def get_pyramid_levels(conn, image_id, across_groups=True):
return levels


@do_across_groups
def get_table(conn, file_ann_id, across_groups=True):
"""Get a table from its FileAnnotation object.

Parameters
----------
conn : ``omero.gateway.BlitzGateway`` object
OMERO connection.
file_ann_id : int
ID of FileAnnotation table to get.
across_groups : bool, optional
Defines cross-group behavior of function - set to
``False`` to disable it.

Returns
-------
table : object
Object containing the actual table. It can be either a list of
row-lists or a pandas Dataframe in case the optional pandas dependency
was installed.

Examples
--------
>>> table = get_table(conn, 62)
>>> print(table[0])
['ID', 'X', 'Y']
"""
if type(file_ann_id) is not int:
raise TypeError('File annotation ID must be an integer')
ann = conn.getObject('FileAnnotation', file_ann_id)
table = None
if ann:
orig_table_file = conn.getObject('OriginalFile', ann.getFile().id)
resources = conn.c.sf.sharedResources()
try:
table_obj = resources.openTable(orig_table_file._obj)
table = _create_table(table_obj)
except InternalException:
logging.warning(f" FileAnnotation {file_ann_id} is not a table.")
else:
logging.warning(f' FileAnnotation {file_ann_id} does not exist.')
return table


@do_across_groups
def get_shape(conn, shape_id, across_groups=True):
"""Get an ezomero shape object from an OMERO Shape id
Expand Down Expand Up @@ -1112,6 +1163,42 @@ def get_shape(conn, shape_id, across_groups=True):
return _omero_shape_to_shape(omero_shape)


def _create_table(table_obj):
if importlib.util.find_spec('pandas'):
columns = []
for col in table_obj.getHeaders():
columns.append(col.name)
table = pd.DataFrame(columns=columns)
rowCount = table_obj.getNumberOfRows()
data = table_obj.read(list(range(len(columns))), 0, rowCount)
for col in data.columns:
col_data = []
for v in col.values:
col_data.append(v)
table[col.name] = col_data

else:
table = []
columns = []
data_lists = []
for col in table_obj.getHeaders():
columns.append(col.name)
table.append(columns)
rowCount = table_obj.getNumberOfRows()
data = table_obj.read(list(range(len(columns))), 0, rowCount)
for col in data.columns:
col_data = []
for v in col.values:
col_data.append(v)
data_lists.append(col_data)
# transpose data_lists
data_lists = [list(i) for i in zip(*data_lists)]
for row in data_lists:
table.append(row)

return table


def _omero_shape_to_shape(omero_shape):
""" Helper function to convert ezomero shapes into omero shapes"""
shape_type = omero_shape.ice_id().split("::omero::model::")[1]
Expand Down
Loading