Skip to content
Draft
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
22 changes: 18 additions & 4 deletions src/App.svelte
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
<script>
import Nav from "./Nav.svelte";
import Bioformats2rawLayout from "./Bioformats2rawLayout/index.svelte";
import Collection from "./Collection/index.svelte";
import JsonValidator from "./JsonValidator/index.svelte";
import Title from "./Title.svelte"
import Modal from "svelte-simple-modal";
import SplashScreen from "./SplashScreen.svelte";

import { getZarrGroupAttrs } from "./utils";
import { getZarrGroupAttrs, getJson } from "./utils";
import CheckMark from "./CheckMark.svelte";

const searchParams = new URLSearchParams(window.location.search);
Expand All @@ -25,15 +26,26 @@

let promise;
if (source) {
// load JSON to be validated...
console.log("Loading JSON... " + source);
promise = getZarrGroupAttrs(source);
console.log("Loading Zarr... " + source);
if (source.endsWith(".json")) {
// For collections, load the JSON directly
promise = getJson(source);
} else {
// load JSON to be validated...
promise = getZarrGroupAttrs(source);
}
}

function isBioFormats2Raw(data) {
let omeAttrs = data?.attributes?.ome || data;
return omeAttrs["bioformats2raw.layout"] === 3 && !omeAttrs.plate;
}

function isCollection(data) {
// Only support Zarr v3
let omeAttrs = data?.attributes?.ome || data?.ome;
return omeAttrs?.type === "collection";
}
</script>

<Modal>
Expand All @@ -55,6 +67,8 @@
<div>
{#if isBioFormats2Raw(data)}
<Bioformats2rawLayout rootAttrs={data} {source} />
{:else if isCollection(data)}
<Collection rootAttrs={data} {source} />
{:else}
<JsonValidator rootAttrs={data} {source} />
{/if}
Expand Down
166 changes: 166 additions & 0 deletions src/Collection/Node.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
<script>
import Icon from "svelte-icons-pack/Icon.svelte";
import BsCaretRightFill from "svelte-icons-pack/bs/BsCaretRightFill";
import { slide } from "svelte/transition";

import JsonBrowser from "../JsonBrowser/index.svelte";
import Thumbnail from "../JsonValidator/Thumbnail/index.svelte";

export let name;
export let contents;
export let source;
export let expanded = false;

const url = window.location.origin + window.location.pathname;

// If the Object or list only has a single item, expand to show it
if (contents && contents.path) {
expanded = true;
}

function toggle() {
expanded = !expanded;
}

function getAbsolutePath(path, s) {
if (path.startsWith("http")) {
return path;
} else {
let src = s.endsWith("/") ? s.slice(0, -1) : s;
let pth = path.startsWith(".") ? path.slice(1) : path;
pth = pth.startsWith("/") ? pth.slice(1) : path;
return src + "/" + pth;
}
}
</script>

<div class="folder">
<div class="{expanded ? 'expanded' : ''} caret" on:click={toggle}>
<Icon className="caret-toggle" src={BsCaretRightFill} />
</div>

<div class="content">
<!-- if NOT expanded, show ...] // n items -->
{#if !expanded}
<li>
{#if contents.name}
{contents.name}
{:else}
<span class="warning">Node is missing <code>name</code></span>
{/if}
</li>
{/if}

{#if expanded}
<ul transition:slide={{ duration: 300 }}>
<li>
name:
{#if contents.name}
{contents.name}
{:else}
<span class="warning">Node is missing <code>name</code></span>
{/if}
</li>

{#if contents.attributes}
<div class="json">
<JsonBrowser
name="attributes"
contents={contents.attributes}
expanded={false}
/>
</div>
{/if}

<!-- either "path" or "nodes" -->
{#if contents.path}
<li>
path:
<a
title="Open {contents.type == 'multiscale'
? 'Image'
: 'Collection'}"
href="{url}?source={getAbsolutePath(contents.path, source)}"
>
{contents.path}
</a>
{#if contents.type == "multiscale"}
<br />
<Thumbnail
source={`${contents.path}`}
targetSize="100"
maxCssSize="100"
/>
{/if}
</li>
{:else if contents.nodes}
<li>nodes:</li>
<ul>
{#each contents.nodes as node}
<li>
<svelte:self
name={node.name}
{source}
contents={node}
expanded={false}
/>
</li>
{/each}
</ul>
{/if}
</ul>
{/if}
</div>
</div>

<style>
.folder {
display: flex;
flex-direction: row;
}
.caret {
flex: 0 20px;
opacity: 0.5;
}
.content {
flex: 1;
}
span {
padding: 0;
text-align: left;
}
.warning {
color: red;
}

ul {
padding: 0.2em 0 0 0;
margin: 0;
list-style: none;
text-align: left;
}

li {
padding: 0.2em 0;
}
:global(.caret-toggle) {
cursor: pointer;
}

:global(.expanded .caret-toggle) {
transform: rotate(90deg);
}

.json {
text-align: left;
margin-top: 10px;
color: #faebd7;
background-color: #263749;
padding: 10px;
font-size: 14px;
border-radius: 10px;
font-family: monospace;
width: fit-content;
min-width: 300px;
}
</style>
26 changes: 26 additions & 0 deletions src/Collection/index.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<script>
import Node from "../Collection/Node.svelte";

export let source;
export let rootAttrs;

let omeAttrs = rootAttrs?.attributes?.ome || rootAttrs?.ome;

</script>

<article>
<Node name={"collection"} {source} contents={omeAttrs} expanded />
</article>

<style>
article {
padding: 1rem;
border: 1px solid darkgoldenrod;
}

@media (min-width: 1000px) {
article {
width: 80%;
}
}
</style>
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
{
"ome": {
"version": "0.x",
"type": "collection",
"name": "sample IDR collections",
"attributes": {
"mobie:grid": "true"
},
"nodes": [
{
"name": "idr0157",
"type": "collection",
"nodes": [
{
"name": "IMG_1033-1112 Asterella gracilis (Mannia gracilis) stature.ome.zarr",
"type": "multiscale",
"path": "https://uk1s3.embassy.ebi.ac.uk/idr/zarr/v0.5/idr0157/Asterella gracilis SWE/IMG_1033-1112 Asterella gracilis (Mannia gracilis) stature.ome.zarr"
},
{
"name": "IMG_3849-3898 Riccia gougetiana var. armatissima thallus cross section (5x).ome.zarr",
"type": "multiscale",
"path": "https://uk1s3.embassy.ebi.ac.uk/idr/share/ome2024-ngff-challenge/idr0157/Riccia gougetiana var. armatissima GER/IMG_3849-3898 Riccia gougetiana var. armatissima thallus cross section (5x).ome.zarr"
},
{
"name": "IMG_2136-2220 Asterella gracilis (Mannia gracilis) ventral scales (20x).ome.zarr",
"type": "multiscale",
"path": "https://uk1s3.embassy.ebi.ac.uk/idr/share/ome2024-ngff-challenge/idr0157/Asterella gracilis SWE/IMG_2136-2220 Asterella gracilis (Mannia gracilis) ventral scales (20x).ome.zarr"
}
]
},
{
"name": "idr0035",
"type": "collection",
"nodes": [
{
"name": "Week10_40115.ome.zarr",
"type": "multiscale",
"path": "https://uk1s3.embassy.ebi.ac.uk/idr/share/ome2024-ngff-challenge/idr0035/Week10_40115.ome.zarr/B/2/0/",
"attributes": {
"description": "The images are of MCF-7 breast cancer cells treated for 24 h with a collection of 113 small molecules at eight concentrations. The cells were fixed, labeled for DNA, F-actin, and B-tubulin, and imaged by fluorescent microscopy.",
"idr:origin": "https://idr.openmicroscopy.org/webclient/?show=plate-6252",
"idr:organismId": "NCBI:txid9606"
}
},
{
"name": "Week1_22361.ome.zarr",
"type": "multiscale",
"path": "https://uk1s3.embassy.ebi.ac.uk/idr/share/ome2024-ngff-challenge/idr0035/Week1_22361.ome.zarr/B/2/0/",
"attributes": {
"description": "The images are of MCF-7 breast cancer cells treated for 24 h with a collection of 113 small molecules at eight concentrations. The cells were fixed, labeled for DNA, F-actin, and B-tubulin, and imaged by fluorescent microscopy.",
"idr:origin": "https://idr.openmicroscopy.org/webclient/?show=plate-6273",
"idr:organismId": "NCBI:txid9606"
}
},
{
"type": "collection",
"name": "Week6_32161.ome.zarr",
"attributes": {
"plate": {
"columns": [
"B"
],
"rows": [
"1",
"2"
]
}
},
"nodes": [
{
"type": "multiscale",
"name": "B2",
"path": "https://uk1s3.embassy.ebi.ac.uk/idr/share/ome2024-ngff-challenge/idr0035/Week6_32161.ome.zarr/B/2/0/"
},
{
"type": "multiscale",
"name": "B3",
"path": "https://uk1s3.embassy.ebi.ac.uk/idr/share/ome2024-ngff-challenge/idr0035/Week6_32161.ome.zarr/B/3/0/"
}
]
}
]
}
]
}
}
45 changes: 45 additions & 0 deletions test_samples/collections/simple_collection.zarr/zarr.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"attributes": {
"ome": {
"version": "0.?dev",
"type": "collection",
"name": "jrc_hela-1",
"nodes": [
{
"name": "ExpD_chicken_embryo_MIP.ome.zarr",
"type": "multiscale",
"path": "https://uk1s3.embassy.ebi.ac.uk/idr/zarr/v0.5/idr0066/ExpD_chicken_embryo_MIP.ome.zarr",
"attributes": {
"example-viewer:settings": {
"isDisabled": true
},
"other-viewer:voxelType": "intensities"
}
},
{
"name": "Whole Mouse Brain",
"type": "multiscale",
"path": "https://uk1s3.embassy.ebi.ac.uk/idr/zarr/v0.4/idr0048A/9846152.zarr",
"attributes": {
"omero:keyValuePairs": {
"strain": "SWR/J",
"Reporter": "CAG-Cytbow",
"Genotype": "Tg/+",
"Mouse Age": "P29"
}
}
},
{
"name": "IDR images 2024 NGFF challenge",
"type": "collection",
"path": "./nested_collection.json"
}
],
"attributes": {
"foo": "bar"
}
}
},
"zarr_format": 3,
"node_type": "group"
}