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 neuroglancer as a service for .ome.zarr files #1192

Open
waxlamp opened this issue Jul 13, 2022 · 6 comments
Open

Add neuroglancer as a service for .ome.zarr files #1192

waxlamp opened this issue Jul 13, 2022 · 6 comments
Labels
enhancement New feature or request visualization Integration of data viewers or other vis tools zarr Issues with Zarr hosting/processing/etc.

Comments

@waxlamp
Copy link
Member

waxlamp commented Jul 13, 2022

in addition to #1067, we should still add neuroglancer as a service for the ome.zarr files.

this piece of code is for multiple zarrs, but could be easily adapted i think in javascript for a single s3 url for a zarr when asset is public (i don't know how embargoed zarr assets would be dealt with, but i don't think we have those at this point).

also we can strip some of the parameters of dictionary for now.

from dandi.dandiapi import DandiAPIClient
import json
from urllib.parse import quote, unquote

api = DandiAPIClient("https://api.dandiarchive.org/api")
ds = api.get_dandiset("000108")

ses = "ses-20211212h13m47s11"
sample = "86"
stain = "NN"
assets = list(ds.get_assets_with_path_prefix(f"sub-MITU01/{ses}/micr/sub-MITU01_{ses}_sample-{sample}_stain-{stain}_run-1"))
zarrs = [a for a in assets if a.path.endswith(".ome.zarr")]

cubehelix_template = """
#uicontrol float brightness slider(min=0.0, max=100.0, default=%f)
void main() {
    float x = clamp(toNormalized(getDataValue()) * brightness, 0.0, 1.0);
    float angle = 2.0 * 3.1415926 * (4.0 / 3.0 + x);
    float amp = x * (1.0 - x) / 2.0;
    vec3 result;
    float cosangle = cos(angle);
    float sinangle = sin(angle);
    result.r = -0.14861 * cosangle + 1.78277 * sinangle;
    result.g = -0.29227 * cosangle + -0.90649 * sinangle;
    result.b = 1.97294 * cosangle;
    result = clamp(x + amp * result, 0.0, 1.0);
    emitRGB(result);
}
"""
colormap = {"LEC": 10, "YO": 40, "NN": 80}
layers = []
for val in zarrs:
    layer = dict(
            source=f"zarr://{val.get_content_url(regex='s3')}",
            type="image",
            shader=cubehelix_template % colormap[stain],
            name=val.path.split("_sample-")[1].split(".ome")[0]
        )
    layers.append(layer)

ng_url = "https://neuroglancer-demo.appspot.com/"
ng_str = json.dumps(dict(dimensions={"t":[1,"s"],
                                     "z":[0.000002285,"m"],
                                     "y":[0.0000032309999999999996,"m"],
                                     "x":[0.000002285,"m"]},
                         displayDimensions=["z","y","x"],
                         crossSectionScale=50,
                         projectionScale=500000,
                         layers=layers,
                         showDefaultAnnotations=False,
                         layout="yz"))
url = f"{ng_url}#!%s" % quote(ng_str)

Originally posted by @satra in #906 (comment)

@yarikoptic
Copy link
Member

FWIW - a rough way to implement it I see if this logic is expressed in JS/Vue, although possible show stopper: ATM I think the place where we use these EXTERNAL_SERVICES would not be able to even see all the files in that dandiset folder but only that "page" :-/

We could add regex to match those specific zarrs (with _stain- in the name) within our https://github.com/dandi/dandi-archive/blob/HEAD/web/src/views/FileBrowserView/FileBrowser.vue#L244 to have smth like

  {
    name: 'NeuroGlancer',
    regex: '.*_stain-.*\.zarr$',
    endpoints-generator: produce_neuroglancer_links,
  },

where produce_neuroglancer_link function we add would receive all hits for the regex and produce dict of links to be used in web UI for the NeuroGlancer external service in context menu.

@yarikoptic
Copy link
Member

Another idea with another show stopper: (ab)use assets metadata and populate with some URLs for external services "offline" (cron job), so that then web UI could pick them up if any given asset has that metadata. Show stopper: I don't think that listing of assets requests metadata for them, so that would require requesting metadata for each asset -- to expensive.

No show stopper idea mixed into prior idea of produce_neuroglancer_link: JS code so onclick, given a path send a glob query (replacing _stain-[^_.] with _stain-*) to API server to get all stains for a given path, and then produce needed URL. So the only cons -- it would not be copy-pasteable URL within menu.

@yarikoptic
Copy link
Member

ok -- last idea, I promise, and quick to implement: implement on server side as /dandisets/{versions__dandiset__pk}/versions/{versions__version}/assets/{asset_id}/services/neuroglancer which would provide redirect to that url, doing all needed Python code (glob'ing) on server side.

@satra
Copy link
Member

satra commented Jul 15, 2022

i don't think it's a show stopper, but i don't think it would do what you may have thought it would do. at present it would simply enable the service for any file that matched the regex, since services are tied to assets/files rather than groups of things.

@satra
Copy link
Member

satra commented Jul 15, 2022

the whole grouping and other things is indeed not implemented in anyway and would come up for json+nonjson, nwb+patchednwb, etc.,.

@satra
Copy link
Member

satra commented Jul 15, 2022

@waxlamp waxlamp added visualization Integration of data viewers or other vis tools enhancement New feature or request labels Mar 2, 2023
@yarikoptic yarikoptic added the zarr Issues with Zarr hosting/processing/etc. label Jan 31, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request visualization Integration of data viewers or other vis tools zarr Issues with Zarr hosting/processing/etc.
Projects
None yet
Development

No branches or pull requests

3 participants