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

SkeletonClient changes, mainly simplification of output formats #265

Merged
merged 30 commits into from
Nov 18, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
c25022b
Compressed SWC format option.
kebwi Oct 23, 2024
dae1c34
lint/ruff corrections
kebwi Oct 23, 2024
cd7227e
Bulk skeleton generation.
kebwi Oct 27, 2024
106113d
New skeleton cache query endpoint
kebwi Oct 29, 2024
f94bd9e
Ruff corrections
kebwi Oct 29, 2024
a44d647
Trivial change
kebwi Oct 29, 2024
1c5c2ac
Removed debugging code. Labeled protected functions.
kebwi Oct 30, 2024
7eae57a
Ruff correctdions.
kebwi Oct 30, 2024
b8cb070
Ruff corrections.
kebwi Oct 30, 2024
7d68e4d
Ruff changes that make the code definitively HARDER to read. Is this …
kebwi Oct 30, 2024
87c1d36
Converted print statements to logging calls.
kebwi Oct 30, 2024
3e936d9
Server version checking for new API endpoints.
kebwi Oct 30, 2024
e69e249
Ruff conformity.
kebwi Oct 30, 2024
0c8f286
Added SkeletonClient.skeletons_exist().
kebwi Nov 4, 2024
6a9bcd2
Ruff changes.
kebwi Nov 4, 2024
4696006
Skeleton Client documentation
kebwi Nov 4, 2024
dd343d8
Merge branch 'master' into skeleton_dev3
kebwi Nov 4, 2024
83951de
update test docs to note confusing local server issue
ceesem Nov 4, 2024
0a89893
generate_bulk_skeletons_async() now reports an upper bound estimate o…
kebwi Nov 5, 2024
581141d
Documentation
kebwi Nov 12, 2024
1053f53
Cleanup
kebwi Nov 12, 2024
95f1c8e
Versions endpoint
kebwi Nov 12, 2024
3ed80d5
Update changelog
ceesem Nov 4, 2024
df213c0
merging
kebwi Nov 12, 2024
5dd723f
SkeletonClient now only accepts 'dict' and 'swc' format requests.
kebwi Nov 12, 2024
3e56070
ruff cleanup
kebwi Nov 12, 2024
7bb6e10
ruff cleanup
kebwi Nov 12, 2024
7d78339
ruff cleanup
kebwi Nov 12, 2024
1575074
Various handling of the new 'flatdict' skeleton format.
kebwi Nov 15, 2024
8159d95
ruff compliance
kebwi Nov 15, 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: 1 addition & 1 deletion caveclient/endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@
"skeleton_info": skeleton_v1 + "/{datastack_name}/precomputed/skeleton/info",
"bulk_skeleton_info": skeleton_v1 + "/{datastack_name}/bulk/skeleton/info",
"skeleton_info_versioned": skeleton_v1
+ "/{datastack_name}/precomputed/skeleton/info/{skvn}",
+ "/{datastack_name}/precomputed/skeleton/{skvn}/info",
"get_cache_contents_via_ridprefixes": skeleton_v1
+ "/{datastack_name}/precomputed/skeleton/query_cache/{root_id_prefixes}/{limit}",
"get_cache_contents_via_skvn_ridprefixes": skeleton_v1
Expand Down
73 changes: 60 additions & 13 deletions caveclient/skeletonservice.py
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,7 @@ def skeletons_exist(
@cached(TTLCache(maxsize=32, ttl=3600))
def get_precomputed_skeleton_info(
self,
skvn: int = 0,
skvn,
datastack_name: Optional[str] = None,
):
"""get's the precomputed skeleton information
Expand All @@ -427,7 +427,7 @@ def get_skeleton(
self,
root_id: int,
datastack_name: Optional[str] = None,
skeleton_version: Optional[int] = 0,
skeleton_version: Optional[int] = None,
output_format: Literal[
"dict",
"swc",
Expand All @@ -444,7 +444,7 @@ def get_skeleton(
datastack_name : str
The name of the datastack to check
skeleton_version : int
The skeleton version to generate and retrieve. Options are documented in SkeletonService. Use 0 for latest.
The skeleton version to generate and retrieve. Options are documented in SkeletonService. Use 0 for Neuroglancer-compatibility. Use -1 for latest.
output_format : string
The format to retrieve. Options are:

Expand All @@ -459,11 +459,33 @@ def get_skeleton(
"""
if not self.fc.l2cache.has_cache():
raise NoL2CacheException("SkeletonClient requires an L2Cache.")

if output_format not in ["dict", "swc"]:
raise ValueError(f"Unknown output format: {output_format}")

if verbose_level >= 1:
logging.info(f"SkeletonService version: {self._server_version}")

if self._server_version < Version("0.6.0"):
logging.warning("SkeletonService version is less than 0.6.0. Please upgrade to the latest version.")

# The output formats were changed in server v0.6.0 and must be handled differently by the client
if output_format == "dict":
endpoint_format = "jsoncompressed"
if self._server_version < Version("0.6.0"):
endpoint_format = "jsoncompressed"
else:
endpoint_format = "flatdict"
elif output_format == "swc":
endpoint_format = "swccompressed"

if skeleton_version is None:
logging.warning("The optional nature of the 'skeleton_version' parameter will be deprecated in the future. Please specify a skeleton version.")
skeleton_version = -1

# -1, to specify the latest version, was only added in server v0.6.1
if self._server_version < Version("0.6.1") and skeleton_version == -1:
skeleton_versions = self.get_versions()
skeleton_version = sorted(skeleton_versions)[-1]

url = self._build_endpoint(
root_id, datastack_name, skeleton_version, endpoint_format
Expand All @@ -478,6 +500,18 @@ def get_skeleton(
)

if endpoint_format == "jsoncompressed":
assert self._server_version < Version("0.6.0")
sk_json = SkeletonClient.decompressBytesToDict(response.content)
if 'vertex_properties' in sk_json.keys():
for key in sk_json['vertex_properties'].keys():
# Radius was redundantly store both as a top-level parameter and in vertex_properties.
# We could either check for it (or any such redundancy key) and skip over it, or we could overwrite it.
# Since they were created as duplicates anyway, it doesn't matter which approach is used.
sk_json[key] = sk_json['vertex_properties'][key]
del sk_json['vertex_properties']
return sk_json
if endpoint_format == "flatdict":
assert self._server_version >= Version("0.6.0")
Copy link
Collaborator

Choose a reason for hiding this comment

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

This should raise a more informative exception telling the user to contact their system administrator to ask them to upgrade their skeleton service to at least 0.6.0

Copy link
Collaborator Author

@kebwi kebwi Nov 18, 2024

Choose a reason for hiding this comment

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

@fcollman But this is a genuine assertion, a verification that the code is performing correctly. The function only receives "dict" and "swc" as inputs (see the function signature). Then on line 475, "dict" is translated to one of two internal formats ("jsoncompressed" or "flatdict") based on the server version. Later on, at the line you indicated in your comment, I am merely confirming (asserting) that the internal format has been assigned correctly based on the server version.

Copy link
Collaborator Author

@kebwi kebwi Nov 18, 2024

Choose a reason for hiding this comment

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

@fcollman To clarify, the API, from the user's perspective outside CAVEclient, doesn't offer "flatdict" as an option. They user asks for "dict" or "swc". Those are their options. These are translated to internal formats that communicate with the server concisely to indicate which format the server should deliver. More to the point, the server really only delivers one kind of dict at at time, but it depends on which version of the server is deployed. There is no "choosing" between dictionary formats from the CAVEclient's perspective (much less from the user's perspective, removed another level of abstraction outside CAVEclient). So, this is an assertion that the code is translating the API format to the correct internal format based on which server version is available.

As for warning the user that their server is out of date, that is handled by other code earlier in the function.

Copy link
Collaborator

Choose a reason for hiding this comment

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

got it! make sense didn't read carefully enough

return SkeletonClient.decompressBytesToDict(response.content)
if endpoint_format == "swccompressed":
file_content = SkeletonClient.decompressBytesToString(response.content)
Expand Down Expand Up @@ -507,11 +541,11 @@ def get_bulk_skeletons(
self,
root_ids: List,
datastack_name: Optional[str] = None,
skeleton_version: Optional[int] = 0,
skeleton_version: Optional[int] = None,
output_format: Literal[
"json",
"dict",
"swc",
] = "json",
] = "dict",
generate_missing_skeletons: bool = False,
log_warning: bool = True,
verbose_level: Optional[int] = 0,
Expand All @@ -525,16 +559,25 @@ def get_bulk_skeletons(
datastack_name : str
The name of the datastack to check
skeleton_version : int
The skeleton version to generate. Use 0 for latest.
The skeleton version to generate. Use 0 for Neuroglancer-compatibility. Use -1 for latest.
"""
if not self.fc.l2cache.has_cache():
raise NoL2CacheException("SkeletonClient requires an L2Cache.")

if output_format == "dict":
endpoint_format = "flatdict"
elif output_format == "swc":
endpoint_format = "swc"

if skeleton_version is None:
logging.warning("The optional nature of the 'skeleton_version' parameter will be deprecated in the future. Please specify a skeleton version.")
skeleton_version = -1

url = self._build_bulk_endpoint(
root_ids,
datastack_name,
skeleton_version,
output_format,
endpoint_format,
generate_missing_skeletons,
)
response = self.session.get(url)
Expand All @@ -545,7 +588,7 @@ def get_bulk_skeletons(
f"Generated skeletons for root_ids {root_ids} (with generate_missing_skeletons={generate_missing_skeletons})"
)

if output_format == "json":
if endpoint_format == "flatdict":
sk_jsons = {}
for rid, swc_bytes in response.json().items():
try:
Expand All @@ -558,7 +601,7 @@ def get_bulk_skeletons(
f"Error decompressing skeleton for root_id {rid}: {e}"
)
return sk_jsons
elif output_format == "swc":
elif endpoint_format == "swc":
sk_dfs = {}
for rid, swc_bytes in response.json().items():
try:
Expand All @@ -583,7 +626,7 @@ def generate_bulk_skeletons_async(
self,
root_ids: List,
datastack_name: Optional[str] = None,
skeleton_version: Optional[int] = 0,
skeleton_version: Optional[int] = None,
log_warning: bool = True,
verbose_level: Optional[int] = 0,
):
Expand All @@ -596,10 +639,14 @@ def generate_bulk_skeletons_async(
datastack_name : str
The name of the datastack to check
skeleton_version : int
The skeleton version to generate. Use 0 for latest.
The skeleton version to generate. Use 0 for Neuroglancer-compatibility. Use -1 for latest.
"""
if not self.fc.l2cache.has_cache():
raise NoL2CacheException("SkeletonClient requires an L2Cache.")

if skeleton_version is None:
logging.warning("The optional nature of the 'skeleton_version' parameter will be deprecated in the future. Please specify a skeleton version.")
skeleton_version = -1

url = self._build_bulk_async_endpoint(
root_ids, datastack_name, skeleton_version
Expand Down
Loading