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

NickAkhmetov/HMP-540/Update get_view_config_builder to use get_assaytype instead of get_assay #82

Merged
merged 19 commits into from
Dec 19, 2023
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
26 changes: 13 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,25 @@ $ cd portal-visualization
$ pip install .
...
$ src/vis-preview.py --help
usage: vis-preview.py [-h] (--url URL | --json JSON) [--types_url URL]
usage: vis-preview.py [-h] (--url URL | --json JSON) [--assaytypes_url URL]
[--assets_url URL] [--token TOKEN] [--marker MARKER]
[--to_json]

Given HuBMAP Dataset JSON, generate a Vitessce viewconf, and load vitessce.io.

optional arguments:
-h, --help show this help message and exit
--url URL URL which returns Dataset JSON
--json JSON File containing Dataset JSON
--types_url URL Type service; default:
https://search.api.hubmapconsortium.org/v3
--assets_url URL Assets endpoint; default:
https://assets.hubmapconsortium.org
--token TOKEN Globus groups token; Only needed if data is not public
--marker MARKER Marker to highlight in visualization; Only used in some
visualizations.
--to_json Output viewconf, rather than open in browser.
```
-h, --help show this help message and exit
--url URL URL which returns Dataset JSON
--json JSON File containing Dataset JSON
--assaytypes_url URL AssayType service; default:
https://ingest.api.hubmapconsortium.org/assaytype/
--assets_url URL Assets endpoint; default:
https://assets.hubmapconsortium.org
--token TOKEN Globus groups token; Only needed if data is not public
--marker MARKER Marker to highlight in visualization; Only used in
some visualizations.
--to_json Output viewconf, rather than open in browser.
```

## Background

Expand Down
2 changes: 1 addition & 1 deletion VERSION.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.0.13
0.1.0
4 changes: 2 additions & 2 deletions src/defaults.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"types_url": "https://search.api.hubmapconsortium.org/v3",
"assets_url": "https://assets.hubmapconsortium.org"
"assets_url": "https://assets.hubmapconsortium.org",
"assaytypes_url": "https://ingest.api.hubmapconsortium.org/assaytype/"
}
1 change: 1 addition & 0 deletions src/portal_visualization/assays.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@
SCATAC_SEQ_SCI = "sc_atac_seq_sci"
SCATAC_SEQ_SNARE = "sc_atac_seq_snare"
SCATAC_SEQ_SN = "sn_atac_seq"
SALMON_RNASSEQ_SLIDE = "salmon_rnaseq_slideseq"
59 changes: 44 additions & 15 deletions src/portal_visualization/builder_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,47 +18,76 @@
from .assays import (
SEQFISH,
MALDI_IMS,
NANODESI
NANODESI,
SALMON_RNASSEQ_SLIDE
)


def get_view_config_builder(entity, get_assay):
data_types = entity["data_types"]
assay_objs = [get_assay(dt) for dt in data_types]
assay_names = [assay.name for assay in assay_objs]
hints = [hint for assay in assay_objs for hint in assay.vitessce_hints]
def get_ancestor_assaytypes(entity, get_assaytype):
return [get_assaytype(ancestor).get('assaytype')
for ancestor
in entity.get('immediate_ancestors')]


# This function is the main entrypoint for the builder factory.
# It returns the correct builder for the given entity.
#
# The entity is a dict that contains the entity UUID and metadata.
# `get_assaytype` is a function which takes an entity UUID and returns
# a dict containing the assaytype and vitessce-hints for that entity.
def get_view_config_builder(entity, get_assaytype):
if (entity.get('uuid') is None):
raise ValueError("Provided entity does not have a uuid")
assay = get_assaytype(entity)
assay_name = assay.get('assaytype')
hints = assay.get('vitessce-hints', [])

dag_provenance_list = entity.get('metadata', {}).get('dag_provenance_list', [])
dag_names = [dag['name']
for dag in dag_provenance_list if 'name' in dag]
if "is_image" in hints:
if 'sprm' in hints and 'anndata' in hints:
# e.g. CellDIVE [DeepCell + SPRM]
# sample entity: c3be5650e93907b68ddbdb22b948db32
return MultiImageSPRMAnndataViewConfBuilder
if "codex" in hints:
if ('sprm-to-anndata.cwl' in dag_names):
# e.g. 'CODEX [Cytokit + SPRM]
# sample entity: 43213991a54ce196d406707ffe2e86bd
return StitchedCytokitSPRMViewConfBuilder
# Cannot find an example of this in the wild, every CODEX entity has the
# sprm-to-anndata.cwl in its dag_provenance_list
return TiledSPRMViewConfBuilder
# Both SeqFISH and IMS were submitted very early on, before the
# special image pyramid datasets existed. Their assay names should be in
# the `entity["data_types"]` while newer ones, like NanoDESI, are in the parents
if SEQFISH in assay_names:
# Check types of image pyramid ancestors to determine which builder to use
ancestor_assaytypes = get_ancestor_assaytypes(entity, get_assaytype)
# e.g. c6a254b2dc2ed46b002500ade163a7cc
if SEQFISH in [assaytype for assaytype in ancestor_assaytypes]:
return SeqFISHViewConfBuilder
if MALDI_IMS in assay_names:
# e.g. 3bc3ad124014a632d558255626bf38c9
if MALDI_IMS in [assaytype for assaytype in ancestor_assaytypes]:
return IMSViewConfBuilder
if NANODESI in [dt for e in entity["immediate_ancestors"] for dt in e["data_types"]]:
# e.g. 6b93107731199733f266bbd0f3bc9747
if NANODESI in [assaytype for assaytype in ancestor_assaytypes]:
return NanoDESIViewConfBuilder
# e.g. f9ae931b8b49252f150d7f8bf1d2d13f
return ImagePyramidViewConfBuilder
if "rna" in hints:
# This is the zarr-backed anndata pipeline.
if "anndata-to-ui.cwl" in dag_names:
if "salmon_rnaseq_slideseq" in data_types:
if assay_name == SALMON_RNASSEQ_SLIDE:
# e.g. 2a590db3d7ab1e1512816b165d95cdcf
return SpatialRNASeqAnnDataZarrViewConfBuilder
# e.g. e65175561b4b17da5352e3837aa0e497
return RNASeqAnnDataZarrViewConfBuilder
# e.g. c019a1cd35aab4d2b4a6ff221e92aaab
return RNASeqViewConfBuilder
if "atac" in hints:
# e.g. d4493657cde29702c5ed73932da5317c
return ATACSeqViewConfBuilder
# any entity with no hints, e.g. 2c2179ea741d3bbb47772172a316a2bf
return NullViewConfBuilder


def has_visualization(entity, get_assay):
builder = get_view_config_builder(entity, get_assay)
def has_visualization(entity, get_assaytype):
builder = get_view_config_builder(entity, get_assaytype)
return builder != NullViewConfBuilder
20 changes: 10 additions & 10 deletions src/vis-preview.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,13 @@

import requests

from hubmap_commons.type_client import TypeClient

from portal_visualization.builder_factory import get_view_config_builder


def main(): # pragma: no cover
defaults = json.load((Path(__file__).parent / 'defaults.json').open())
types_default_url = defaults['types_url']
assets_default_url = defaults['assets_url']
assaytypes_default_url = defaults['assaytypes_url']

parser = argparse.ArgumentParser(description='''
Given HuBMAP Dataset JSON, generate a Vitessce viewconf, and load vitessce.io.''')
Expand All @@ -28,9 +26,9 @@ def main(): # pragma: no cover
'--json', type=Path, help='File containing Dataset JSON')

parser.add_argument(
'--types_url', metavar='URL',
help=f'Type service; default: {types_default_url}',
default=types_default_url)
'--assaytypes_url', metavar='URL',
help=f'AssayType service; default: {assaytypes_default_url}',
default=assaytypes_default_url)
parser.add_argument(
'--assets_url', metavar='URL',
help=f'Assets endpoint; default: {assets_default_url}',
Expand Down Expand Up @@ -60,11 +58,13 @@ def main(): # pragma: no cover
json_str = args.json.read_text()
entity = json.loads(json_str)

def get_assay(name):
type_client = TypeClient(args.types_url)
return type_client.getAssayType(name)
def get_assaytype(uuid):
headers = {}
if args.token:
headers['Authorization'] = f'Bearer {args.token}'
requests.get(f'{defaults["assaytypes_url"]}/{uuid}', headers=headers).json()

Builder = get_view_config_builder(entity=entity, get_assay=get_assay)
Builder = get_view_config_builder(entity, get_assaytype)
builder = Builder(entity, args.token, args.assets_url)
print(f'Using: {builder.__class__.__name__}', file=stderr)
conf_cells = builder.get_conf_cells(marker=marker)
Expand Down
11 changes: 11 additions & 0 deletions test/assaytype-fixtures/04e7385339167e541ad42a2636e18398.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"assaytype": "codex_cytokit_v1",
"contains-pii": false,
"description": "CODEX [Cytokit + SPRM]",
"primary": false,
"vitessce-hints": [
"codex",
"is_image",
"is_tiled"
]
}
10 changes: 10 additions & 0 deletions test/assaytype-fixtures/210d118a14c8624b6bb9610a9062656e.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"assaytype": "sn_atac_seq",
"contains-pii": false,
"description": "snATAC-seq [SnapATAC]",
"primary": false,
"vitessce-hints": [
"is_sc",
"atac"
]
}
10 changes: 10 additions & 0 deletions test/assaytype-fixtures/2a590db3d7ab1e1512816b165d95cdcf.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"assaytype": "salmon_rnaseq_slideseq",
"contains-pii": false,
"description": "Slide-seq [Salmon]",
"primary": false,
"vitessce-hints": [
"is_sc",
"rna"
]
}
9 changes: 9 additions & 0 deletions test/assaytype-fixtures/2c2179ea741d3bbb47772172a316a2bf.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"assaytype": "bulk-RNA",
"contains-pii": true,
"description": "Bulk RNA-seq",
"dir-schema": "bulkrnaseq-v0",
"primary": true,
"tbl-schema": "bulkrnaseq-v0",
"vitessce-hints": []
}
11 changes: 11 additions & 0 deletions test/assaytype-fixtures/3bc3ad124014a632d558255626bf38c9.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"assaytype": "MALDI-IMS",
"contains-pii": false,
"description": "MALDI IMS",
"dir-schema": "ims-v0",
"primary": true,
"tbl-schema": "ims-v2",
"vitessce-hints": [
"maldi"
]
}
11 changes: 11 additions & 0 deletions test/assaytype-fixtures/43213991a54ce196d406707ffe2e86bd.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"assaytype": "codex_cytokit_v1",
"contains-pii": false,
"description": "CODEX [Cytokit + SPRM]",
"primary": false,
"vitessce-hints": [
"codex",
"is_image",
"is_tiled"
]
}
9 changes: 9 additions & 0 deletions test/assaytype-fixtures/6b93107731199733f266bbd0f3bc9747.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"assaytype": "NanoDESI",
"contains-pii": false,
"description": "NanoDESI",
"dir-schema": "ims-v0",
"primary": true,
"tbl-schema": "ims-v2",
"vitessce-hints": []
}
11 changes: 11 additions & 0 deletions test/assaytype-fixtures/9db61adfc017670a196ea9b3ca1852a0.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"assaytype": "image_pyramid",
"contains-pii": false,
"description": "Image Pyramid",
"primary": false,
"vitessce-hints": [
"is_image",
"pyramid",
"is_support"
]
}
11 changes: 11 additions & 0 deletions test/assaytype-fixtures/a6116772446f6d1c1f6b3d2e9735cfe0.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"assaytype": "image_pyramid",
"contains-pii": false,
"description": "Image Pyramid",
"primary": false,
"vitessce-hints": [
"is_image",
"pyramid",
"is_support"
]
}
10 changes: 10 additions & 0 deletions test/assaytype-fixtures/c019a1cd35aab4d2b4a6ff221e92aaab.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"assaytype": "salmon_sn_rnaseq_10x",
"contains-pii": false,
"description": "snRNA-seq [Salmon]",
"primary": false,
"vitessce-hints": [
"is_sc",
"rna"
]
}
12 changes: 12 additions & 0 deletions test/assaytype-fixtures/c3be5650e93907b68ddbdb22b948db32.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"assaytype": "celldive_deepcell",
"contains-pii": false,
"description": "CellDIVE [DeepCell + SPRM]",
"primary": false,
"vitessce-hints": [
"sprm",
"anndata",
"is_image",
"is_tiled"
]
}
9 changes: 9 additions & 0 deletions test/assaytype-fixtures/c6a254b2dc2ed46b002500ade163a7cc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"assaytype": "seqFish",
"contains-pii": false,
"description": "seqFISH",
"dir-schema": "seqfish-v0",
"primary": true,
"tbl-schema": "seqfish-v0",
"vitessce-hints": []
}
10 changes: 10 additions & 0 deletions test/assaytype-fixtures/d4493657cde29702c5ed73932da5317c.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"assaytype": "sc_atac_seq_sci",
"contains-pii": false,
"description": "sciATAC-seq [SnapATAC]",
"primary": false,
"vitessce-hints": [
"is_sc",
"atac"
]
}
11 changes: 11 additions & 0 deletions test/assaytype-fixtures/e1c4370da5523ab5c9be581d1d76ca20.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"assaytype": "image_pyramid",
"contains-pii": false,
"description": "Image Pyramid",
"primary": false,
"vitessce-hints": [
"is_image",
"pyramid",
"is_support"
]
}
10 changes: 10 additions & 0 deletions test/assaytype-fixtures/e65175561b4b17da5352e3837aa0e497.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"assaytype": "salmon_sn_rnaseq_10x",
"contains-pii": false,
"description": "snRNA-seq [Salmon]",
"primary": false,
"vitessce-hints": [
"is_sc",
"rna"
]
}
10 changes: 10 additions & 0 deletions test/assaytype-fixtures/ea4cfecb8495b36694d9a951510dc3c6.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"assaytype": "salmon_rnaseq_slideseq",
"contains-pii": false,
"description": "Slide-seq [Salmon]",
"primary": false,
"vitessce-hints": [
"is_sc",
"rna"
]
}
Loading
Loading