diff --git a/README.md b/README.md index 6586a1d..ded647c 100644 --- a/README.md +++ b/README.md @@ -40,3 +40,21 @@ This is a page to list various OME-NGFF sample images from IDR. Deployed at http ### Deployment The site is automatically deployed to GitHub Pages when changes are pushed to the main branch using GitHub's built-in Jekyll build process. + +## Troubleshooting + +### Permission denied errors with pixi on macOS + +If you encounter permission denied errors with your temp directory when running `pixi` commands: + +```bash +mkdir -p ~/tmp +export TMPDIR=~/tmp +``` + +To make this permanent, add to your shell profile: +```bash +echo 'export TMPDIR=~/tmp' >> ~/.zshrc # or ~/.bashrc +``` + +This is particularly common on university/enterprise-managed macOS machines where the default `$TMPDIR` may have restricted permissions. diff --git a/index.md b/index.md index e2d1cec..b83cc27 100644 --- a/index.md +++ b/index.md @@ -50,12 +50,9 @@ layout: default @keyframes seesaw { from { transform: rotate(-0.05turn) } to { transform: rotate(0.05turn); } } -

To download samples, you can use aws CLI. E.g

- - -$ aws s3 sync --endpoint-url https://uk1s3.embassy.ebi.ac.uk --no-sign-request s3://idr/zarr/v0.4/idr0062A/6001240.zarr/ 6001240.zarr - +

Download or Access Data

+

Click the copy button in the table below for download options including URLs and code samples.

@@ -102,7 +99,7 @@ $ aws s3 sync --endpoint-url https://uk1s3.embassy.ebi.ac.uk --no-sign-request s {{ image_name }}
- @@ -166,6 +163,75 @@ $(document).ready( function () { }); } ); +function generatePythonCode(httpsUrl) { + const s3Url = httpsUrl.replace('https://uk1s3.embassy.ebi.ac.uk/', 's3://'); + const endpoint = 'https://uk1s3.embassy.ebi.ac.uk'; + + const code = `import zarr + +zarr_group = zarr.open( + "${s3Url}", + storage_options={ + "anon": True, + "client_kwargs": { + "endpoint_url": "${endpoint}" + } + } +)`; + + const html = `import zarr + +zarr_group = zarr.open( + "${s3Url}", + storage_options={ + "anon": True, + "client_kwargs": { + "endpoint_url": "${endpoint}" + } + } +)`; + + return { code, html }; +} + +function showS3Options(httpsUrl, imageName) { + const s3Url = httpsUrl.replace('https://uk1s3.embassy.ebi.ac.uk/', 's3://'); + const endpoint = 'https://uk1s3.embassy.ebi.ac.uk'; + const awsCommand = `aws s3 sync --endpoint-url ${endpoint} --no-sign-request ${s3Url} ${imageName}`; + const omeZarrCommand = `uvx --with ome-zarr ome_zarr download ${httpsUrl} --output ${imageName}`; + const python = generatePythonCode(httpsUrl); + + const modal = document.getElementById('s3OptionsModal'); + document.getElementById('s3OptionsTitle').textContent = `Download Options: ${imageName}`; + document.getElementById('awsCliCommand').textContent = awsCommand; + document.getElementById('omeZarrCommand').textContent = omeZarrCommand; + document.getElementById('s3Endpoint').textContent = endpoint; + document.getElementById('s3UrlText').textContent = s3Url; + document.getElementById('httpsUrlText').textContent = httpsUrl; + document.getElementById('pythonCodeInOptions').innerHTML = python.html; + + document.getElementById('awsCliCommand').dataset.copyText = awsCommand; + document.getElementById('omeZarrCommand').dataset.copyText = omeZarrCommand; + document.getElementById('s3Endpoint').dataset.copyText = endpoint; + document.getElementById('s3UrlText').dataset.copyText = s3Url; + document.getElementById('httpsUrlText').dataset.copyText = httpsUrl; + document.getElementById('pythonCodeInOptions').dataset.copyText = python.code; + + modal.style.display = 'block'; + + modal.onclick = closeS3Options; +} + +function closeS3Options(event) { + // event is undifined if click comes from x button + if (event == undefined || event?.target.id == "s3OptionsModal") { + document.getElementById('s3OptionsModal').style.display = 'none'; + } +} + +function copyFromDataset(element) { + copyTextToClipboard(element.dataset.copyText); +} function copyTextToClipboard(text) { var textArea = document.createElement("textarea"); @@ -187,16 +253,104 @@ function copyTextToClipboard(text) { document.body.removeChild(textArea); if (successful) { - // show user that copying happened - update text on element (e.g. button) + // Show "Copied!" feedback to the left of button let target = event.target; - let html = target.innerHTML; - target.classList.add("shake"); + let feedback = document.createElement('span'); + feedback.textContent = 'Copied! '; + feedback.style.color = '#28a745'; + feedback.style.fontSize = '12px'; + feedback.style.marginRight = '5px'; + target.parentNode.insertBefore(feedback, target); + setTimeout(() => { - // reset after 1 second - target.classList.remove("shake"); - }, 1000) + feedback.remove(); + }, 1500) } else { console.log("Copying failed") } } + + +