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

Add JsonWrapper class #386

Merged
merged 1 commit into from
Nov 4, 2024
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
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "vitessce"
version = "3.4.2"
version = "3.4.3"
authors = [
{ name="Mark Keller", email="[email protected]" },
]
Expand Down
48 changes: 48 additions & 0 deletions tests/test_wrappers.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
OmeZarrWrapper,
AnnDataWrapper,
CsvWrapper,
JsonWrapper,
MultivecZarrWrapper,
ImageOmeTiffWrapper,
ObsSegmentationsOmeTiffWrapper,
Expand Down Expand Up @@ -358,6 +359,53 @@ def test_csv_with_base_dir(self):
}
})

def test_json(self):
w = JsonWrapper(
json_path=data_path / 'test.segmentations.json',
data_type="obsSegmentations",
coordination_values={
"obsType": "nucleus"
}
)
w.local_json_uid = 'test_uid'

file_def_creator = w.make_json_file_def_creator(
"A",
"0"
)
file_def = file_def_creator('http://localhost:8000')
self.assertEqual(file_def, {
'fileType': 'obsSegmentations.json',
'url': 'http://localhost:8000/A/0/test_uid',
'coordinationValues': {
"obsType": "nucleus"
}
})

def test_json_with_base_dir(self):
w = JsonWrapper(
json_path='test.segmentations.json',
data_type="obsSegmentations",
coordination_values={
"obsType": "nucleus"
}
)
w.base_dir = data_path
w.local_json_uid = 'test_uid'

file_def_creator = w.make_json_file_def_creator(
"A",
"0"
)
file_def = file_def_creator('http://localhost:8000')
self.assertEqual(file_def, {
'fileType': 'obsSegmentations.json',
'url': 'http://localhost:8000/test.segmentations.json',
'coordinationValues': {
"obsType": "nucleus"
}
})

def test_multivec_zarr(self):
zarr_filepath = data_path / 'test_out.snap.multivec.zarr'

Expand Down
1 change: 1 addition & 0 deletions vitessce/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
OmeZarrWrapper,
MultiImageWrapper,
CsvWrapper,
JsonWrapper,
AnnDataWrapper,
MultivecZarrWrapper,
ImageOmeTiffWrapper,
Expand Down
89 changes: 89 additions & 0 deletions vitessce/wrappers.py
Original file line number Diff line number Diff line change
Expand Up @@ -808,6 +808,95 @@ def get_csv_url(self, base_url="", dataset_uid="", obj_i=""):
obj_i, self.local_csv_uid)


class JsonWrapper(AbstractWrapper):

"""
Wrap a JSON file by creating an instance of the ``JsonWrapper`` class.

:param str data_type: The data type of the information contained in the file.
:param str json_path: A local filepath JSON a JSON file.
:param str json_url: A remote URL of a CSV file.
:param dict options: The file options.
:param dict coordination_values: The coordination values.
:param \\*\\*kwargs: Keyword arguments inherited from :class:`~vitessce.wrappers.AbstractWrapper`
"""

def __init__(self, json_path=None, json_url=None, data_type=None, options=None, coordination_values=None,
**kwargs):
super().__init__(**kwargs)
self._repr = make_repr(locals())
self._json_path = json_path
self._json_url = json_url
self._data_type = norm_enum(data_type, dt)
self._options = options
self._coordination_values = coordination_values
self.is_remote = json_url is not None
self.local_json_uid = make_unique_filename(".json")
if data_type is None:
raise ValueError("Expected data_type to be provided")
if json_url is not None and json_path is not None:
raise ValueError(
"Did not expect json_url to be provided with json_path")
if json_url is None and json_path is None:
raise ValueError(
"Expected json_url or json_path to be provided")

def convert_and_save(self, dataset_uid, obj_i, base_dir=None):
# Only create out-directory if needed
if not self.is_remote:
super().convert_and_save(dataset_uid, obj_i, base_dir=base_dir)

file_def_creator = self.make_json_file_def_creator(
dataset_uid, obj_i)
routes = self.make_json_routes(dataset_uid, obj_i)

self.file_def_creators.append(file_def_creator)
self.routes += routes

def make_json_routes(self, dataset_uid, obj_i):
if self.is_remote:
return []
else:
# TODO: Move imports back to top when this is factored out.
from .routes import FileRoute
from starlette.responses import FileResponse

if self.base_dir is not None:
local_json_path = join(self.base_dir, self._json_path)
local_json_route_path = file_path_to_url_path(self._json_path)
else:
local_json_path = self._json_path
local_json_route_path = self._get_route_str(dataset_uid, obj_i, self.local_json_uid)

async def response_func(req):
return FileResponse(local_json_path, filename=os.path.basename(self._json_path))
routes = [
FileRoute(local_json_route_path, response_func, local_json_path),
]
return routes

def make_json_file_def_creator(self, dataset_uid, obj_i):
def json_file_def_creator(base_url):
file_def = {
"fileType": f"{self._data_type}.json",
"url": self.get_json_url(base_url, dataset_uid, obj_i),
}
if self._options is not None:
file_def["options"] = self._options
if self._coordination_values is not None:
file_def["coordinationValues"] = self._coordination_values
return file_def
return json_file_def_creator

def get_json_url(self, base_url="", dataset_uid="", obj_i=""):
if self.is_remote:
return self._json_url
if self.base_dir is not None:
return self._get_url_simple(base_url, file_path_to_url_path(self._json_path, prepend_slash=False))
return self._get_url(base_url, dataset_uid,
obj_i, self.local_json_uid)


class OmeZarrWrapper(AbstractWrapper):

"""
Expand Down
Loading