Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
740eae3
Basic viewer to check for archived and ext_info
will-moore Jan 7, 2026
5a19f1c
Load image parents to get idrname
will-moore Jan 7, 2026
0bc6060
Add initial download_urls table with links checked on the fly
will-moore Mar 3, 2026
a35a8ed
flake8 fixes
will-moore Mar 3, 2026
00481e7
Study pages load download_urls.tsv and update download_url
will-moore Mar 5, 2026
16acc03
Fix typo in empty_study_container - not a tuple
will-moore Mar 5, 2026
b3e7da7
Only show iviewer for externalInfo images. Otherwise show Fileset dow…
will-moore Mar 5, 2026
48e56d8
Improve archived_image page
will-moore Mar 5, 2026
c2470fe
Update search video on the idr home page
will-moore Mar 11, 2026
5d51629
Merge branch 'download_urls' into archived_image_handling
will-moore Mar 11, 2026
c6aec54
Tweak 'image not viewable' wording on archived page
will-moore Mar 11, 2026
d8b2ecc
download_urls page creates link to client_path file
will-moore Mar 11, 2026
4a7a2a7
download_links and archived_image pages load download_urls.tsv and ca…
will-moore Mar 12, 2026
f2f3e7e
download_urls table checks 1 link at a time
will-moore Mar 12, 2026
2419820
For 'Github' repos, clientPathLink links to companion or pattern file…
will-moore Apr 20, 2026
bc4d6e8
Last fixes to download_urls.html logic for clientPathUrl
will-moore Apr 20, 2026
66653be
Update archived_image.html page to handle download links
will-moore Apr 23, 2026
0b52b23
Fix JS update of download links
will-moore Apr 23, 2026
55c9d44
Allow all .zarr images to be viewable in iviewer
will-moore Apr 23, 2026
4af868f
Hide debug section, nicer styles for download links
will-moore Apr 24, 2026
15c3396
Update download_urls.tsv url to load from master branch
will-moore Apr 27, 2026
0c3a478
Fix logos on iviewer placeholder page via base_url
will-moore Apr 27, 2026
9df2ae5
Fix css ul on iviewer placeholder page
will-moore Apr 27, 2026
3546b3b
Use get_settings_as_context() instead of just base_url for iviewer pl…
will-moore Apr 27, 2026
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
4 changes: 2 additions & 2 deletions idr_gallery/data/tabs.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
"text": "Find a specific IDR study from a publication. View images and Regions of Interest (ROIs) in IDR. Explore study metadata.",
},
{
"id": "JboK6Kds28U",
"id": "sxgfFXgpJ7U",
"title": "From gene to phenotypes",
"text": "Query images by gene. Explore retrieved images and metadata, including associated phenotypes. View images in context of a plate.",
"text": "Query images by gene. Explore retrieved images and metadata, including associated phenotypes. View images in BioFile Finder.",
},
{
"id": "stF4Q4m5GZg",
Expand Down
185 changes: 185 additions & 0 deletions idr_gallery/templates/idr_gallery/archived_image.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
{% extends "idr_gallery/base.html" %} {% block content %}

<style>
article {
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
.download_list {
list-style: none;
background: white;
margin: 0;
padding: 15px;
margin-bottom: 20px;
border-radius: 5px;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
border: solid 1px lightgrey;
}
a.file_download {
color: #03A9F4;
text-decoration: none;
font-weight: normal;
font-size: 14px;
}
a.file_download:hover {
text-decoration: underline;
}
</style>

<article>
<div style="display: flex; gap: 20px; flex-direction: row;">
<div style="flex: 0 0 96px;">
<img src="{% url 'render_thumbnail' image.id %}" alt="Thumbnail for {{ image.name }}" border: 1px solid #ccc; border-radius: 5px;">
</div>
<div style="flex: 1 1 auto">

<h2>Image Name: {{ image.name }}</h2>
<strong>ID: {{ image.id }}</strong><br />
<strong>Study: {{ idr_study }}</strong>
<p>
This image is not viewable online. <br/>
The IDR only supports the viewing of OME-Zarr images.
</p>
</div>
</div>

{% if fileset %}
<h3>Download Image Files</h3>
{% if data_location == "Github" %}
<p>
This image is defined by a {% if is_pattern %}.pattern{% else %}companion.ome{% endif %} file
and sibling .tiff files which are on GitHub (links below).
Each .tiff file is a symbolic link to the actual image file in
<!-- link is updated from download_urls.tsv info -->
<a id="download_url_tsv" target="_blank" class="file_download" href="{{ download_url }}">{{ download_url }}</a>.
</p>
{% elif fileset.file_urls|length == 1 %}
<p>There is 1 file associated with this image. Click to download:</p>
{% else %}
<p>
There are {{ fileset.file_urls|length }} files associated with this image
which can be downloaded from the links below. For more download options,
including bulk download using Globus or FTP clients, see the
<a href="/about/download.html">IDR Data download page</a>.
</p>
{% endif %}

<ul class="download_list">
{% for file in fileset.file_urls %}
<li>
{% if file.url %}
<a class="file_download" target="_blank" href="{{ file.url }}">{{ file.path }}</a>
{% else %} {{ file.path }} {% endif %}
</li>
{% endfor %}
</ul>
{% else %}
<!-- Only expected for some OME-Zarr images (this page won't show for them) -->
<p>No associated fileset.</p>
{% endif %}

<!-- <details><summary>Extra info (debug)</summary>
<ul style="background: white">
<li>Image Path: {{ img_path }}</li>
<li>Data Location: {{ data_location }}</li>
<li>Is Zarr?: {{ is_zarr }}</li>
<li>Download URL from IDR: <a href="{{ download_url }}">{{ download_url }}</a></li>
<li>BIA NGFF ID: {{ bia_ngff_id }}</li>
</ul>
</details> -->
</article>

<script>
const IDR_ID_NAME = "{{ idr_study }}";
let IDR_ID = IDR_ID_NAME.split("-")[0];
let DOWNLOAD_URL = "{{ download_url }}";

function checkLinks() {
let links = Array.from(document.querySelectorAll("a"));
// links = links.slice(0,50)
links.forEach((link) => {
// ignore image viewer links
if (!link.href || link.href.includes("img_detail")) return;
// no cors-origin check for now, just check if the link is valid
fetch(link.href, { method: "HEAD" })
.then((response) => {
link.style.color = response.ok ? "green" : "orange";
link.title = response.ok ? "Link is valid" : "Link is broken";
})
.catch((error) => {
// show "pink" and re-try with server-side check, to avoid CORS issues
console.error("Error checking link:", error);
link.style.color = "pink";
link.title = "Error checking link";

fetch(`/link_check/?url=${encodeURIComponent(link.href)}`)
.then((res) => res.json())
.then((data) => {
console.log("Link check data:", data);
if (data.is_valid) {
link.style.color = "green";
link.title = "Link is valid (checked with server)";
} else {
link.style.color = "red";
link.title = `Link is broken: ${data.error}`;
}
});
});
});
}

document.addEventListener("DOMContentLoaded", function () {
// Load download URLs from TSV file in GitHub to fix the download URL for this image
fetch(
"https://raw.githubusercontent.com/IDR/idr.openmicroscopy.org/refs/heads/master/_data/download_urls.tsv",
)
.then((response) => response.text())
.then((data) => {
const lines = data.split("\n");

// Use first line as header to find column names...
const headers = lines[0].split("\t");

const idrIndex = headers.indexOf("idrid");

// Find the line for this IDR ID
const studyLine = lines.find(
(line) => line.split("\t")[idrIndex] === IDR_ID,
);
console.log(`Found line for ${IDR_ID}:`, studyLine);
if (studyLine) {
const cells = studyLine.split("\t");
const downloadUrlIndex = headers.indexOf("download_url");
// downloadUrl e.g. https://ftp.ebi.ac.uk/pub/databases/IDR/idr0047-neuert-yeastmrna/
const downloadUrl = cells[downloadUrlIndex];
let link = document.getElementById("download_url_tsv");
if (link) {
link.textContent = downloadUrl;
link.href = downloadUrl;
}
const baseUrl = downloadUrl.split(IDR_ID)[0]; // e.g. https://ftp.ebi.ac.uk/pub/databases/IDR/
console.log(`Download URL for ${IDR_ID}:`, downloadUrl);
if (downloadUrl && downloadUrl !== DOWNLOAD_URL) {
console.log(`Updating download URLs from ${DOWNLOAD_URL} to ${downloadUrl}`);
// update all ".file_download" links to this download URL
const fileDownloadLinks =
document.querySelectorAll(".file_download");
fileDownloadLinks.forEach((link) => {
link.href = link.href.replace(DOWNLOAD_URL, downloadUrl);
});
}
} else {
console.warn(`No download URL found for ${IDR_ID} in TSV file`);
}

// After updating links, check them if ?check_links=1 is in the URL
const urlParams = new URLSearchParams(window.location.search);
if (urlParams.get("check_links")) {
checkLinks();
}
});
});
</script>

{% endblock %}
178 changes: 178 additions & 0 deletions idr_gallery/templates/idr_gallery/download_urls.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
{% extends "idr_gallery/base.html" %}

{% block content %}


<style>
body {
background-color: #f6f6f9;
}

table {
width: 100%;
border-collapse: collapse;
font-size: 12px;
}

</style>

<h1>Download URLs</h1>

<div id="table-container">
<p>Loading download URLs...</p>
</div>

<script>

async function checkLinks() {
let links = Array.from(document.querySelectorAll('a'));
// links = links.slice(0,50)
for (let link of links) {
// links.forEach(async link => {
// ignore image viewer links
if (!link.href || link.href.includes("img_detail")) {
continue;
};
// no cors-origin check for now, just check if the link is valid
let ok = await fetch(link.href, { method: 'HEAD'})
.then(response => {
link.style.color = response.ok ? 'green' : 'orange';
link.title = response.ok ? 'Link is valid' : 'Link is broken';
return true;
})
.catch(error => {
console.error('Error checking link:', error);
return false;
});
if (!ok) {
// show "pink" and re-try with server-side check, to avoid CORS issues
link.style.color = 'pink';
link.title = 'Error checking link';

await fetch(`/link_check/?url=${encodeURIComponent(link.href)}`)
.then(res => res.json())
.then(data => {
if (data.is_valid) {
link.style.color = 'green';
link.title = 'Link is valid (checked with server)';
} else {
link.style.color = 'red';
link.title = `Link is broken: ${data.error}`;
}
});
}
};
}

// Fetch the TSV file and display it in a table
fetch('https://raw.githubusercontent.com/IDR/idr.openmicroscopy.org/refs/heads/master/_data/download_urls.tsv')
.then(response => response.text())
.then(data => {
const lines = data.split('\n');
const table = document.createElement('table');
table.style.width = '100%';
table.style.borderCollapse = 'collapse';

// Create table header
const header = table.createTHead();
const headerRow = header.insertRow();
const headers = lines[0].split('\t');
headers.forEach(headerText => {
const th = document.createElement('th');
th.textContent = headerText;
th.style.border = '1px solid #ddd';
th.style.padding = '2px';
th.style.backgroundColor = '#f2f2f2';
headerRow.appendChild(th);
});

let clientPathIndex = headers.indexOf('client_path');
let downloadUrlIndex = headers.indexOf('download_url');
let idrIdIndex = headers.indexOf('idrid');
let imageIdIndex = headers.indexOf('image_id');
let dataLocationIndex = headers.indexOf('data_location');

// Create table body - update client_path to URL, based on the download_url column...
const tbody = table.createTBody();
lines.slice(1).forEach(line => {
if (line.trim() === '') return; // Skip empty lines
const row = tbody.insertRow();
const cells = line.split('\t');

let idrId = cells[idrIdIndex];
let clientPath = cells[clientPathIndex];
let downloadUrl = cells[downloadUrlIndex];
let dataLocation = cells[dataLocationIndex];
let clientPathUrl;
if (dataLocation == "Github") {
let branch = "main";
// e.g. data/idr-metadata/idr0106-kubota-lunglightsheet/experimentA/companions/Mosaic_Image.companion.ome
// links to https://github.com/IDR/idr0106-kubota-lunglightsheet/blob/main/experimentA/companions/Mosaic_Image.companion.ome
// uod/idr/metadata/idr0052-walther-condensinmap/experimentA/companions/160719_NCAPD2gfpc272c78_MitoSys2/conc/cell0005_R0001.companion.ome
// links to https://github.com/IDR/idr0052-walther-condensinmap/blob/master/experimentA/companions/160719_NCAPD2gfpc272c78_MitoSys2/conc/cell0005_R0001.companion.ome
// uod/idr/metadata/idr0079-hartmann-lateralline/companions/experimentA/056F63395C/056F63395C.companion.ome
// https://github.com/IDR/idr0079-hartmann-lateralline/blob/master/companions/experimentA/056F63395C/056F63395C.companion.ome
let relativePath = clientPath.split("metadata/idr")[1];
let githubRepo = "idr" + relativePath.split("/")[0];
// some repos use "master" branch, so check for those...
if ("idr0079,idr0052,idr0065,idr0075,idr0100".includes(githubRepo.split("-")[0])) {
branch = "master";
}
relativePath = relativePath.split("/").slice(1).join("/");
clientPathUrl = `https://github.com/IDR/${githubRepo}/blob/${branch}/${relativePath}`;

} else if (downloadUrl.includes(idrId) && clientPath.includes(idrId)) {
// e.g. https://ftp.ebi.ac.uk/pub/databases/IDR/idr0001-graml-sysgro
let urlBase = downloadUrl.split(idrId)[0];
let urlPath = clientPath.split(idrId)[1];
clientPathUrl = urlBase + idrId + urlPath;
}
if (clientPathUrl) {
// client_path needs patching for /idr0045-reichmann-zygotespindle/
clientPathUrl = clientPathUrl.replace("/idr0045-reichmann/", "/idr0045-reichmann-zygotespindle/");
}

cells.forEach((cellText, colIndex) => {
const td = document.createElement('td');
td.style.border = '1px solid #ddd';
td.style.padding = '2px';
// handle links or 'client_path' column...
if (cellText.startsWith('http') || (headers[colIndex] === 'client_path' && clientPathUrl)) {
const link = document.createElement('a');
// escape the URL to avoid issues with special characters in the client_path
link.href = encodeURI(cellText.startsWith('http') ? cellText : clientPathUrl).replace("#", "%23");
// fix idr0045 as above
cellText = cellText.replace("/idr0045-reichmann/", "/idr0045-reichmann-zygotespindle/");
link.textContent = cellText;
link.target = '_blank';
td.textContent = '';
td.appendChild(link);
} else if (colIndex == imageIdIndex) {
// Add link to image viewer at /webclient/img_detail/1884807/
const link = document.createElement('a');
link.href = encodeURI(`/webclient/img_detail/${cellText}/?check_links=true`).replace("#", "%23");
link.textContent = cellText;
link.target = '_blank';
td.textContent = '';
td.appendChild(link);
} else {
td.textContent = cellText;
}
row.appendChild(td);
});
});
const tableContainer = document.getElementById('table-container');
tableContainer.innerHTML = '';
tableContainer.appendChild(table);

checkLinks();
})
.catch(error => {
console.error('Error fetching TSV file:', error);
const tableContainer = document.getElementById('table-container');
tableContainer.innerHTML = '<p>Error loading download URLs.</p>';
});

</script>

{% endblock %}
Loading
Loading