Skip to content

Commit cef6db5

Browse files
committed
Merge remote-tracking branch 'origin/master' into searchengine_container_data_url
2 parents 55e75bb + 72294b3 commit cef6db5

8 files changed

Lines changed: 540 additions & 11 deletions

File tree

.bumpversion.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[bumpversion]
2-
current_version = 3.14.1.dev0
2+
current_version = 3.15.1.dev0
33
commit = True
44
tag = True
55
sign_tags = True

idr_gallery/data/tabs.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@
1111
"text": "Find a specific IDR study from a publication. View images and Regions of Interest (ROIs) in IDR. Explore study metadata.",
1212
},
1313
{
14-
"id": "JboK6Kds28U",
14+
"id": "sxgfFXgpJ7U",
1515
"title": "From gene to phenotypes",
16-
"text": "Query images by gene. Explore retrieved images and metadata, including associated phenotypes. View images in context of a plate.",
16+
"text": "Query images by gene. Explore retrieved images and metadata, including associated phenotypes. View images in BioFile Finder.",
1717
},
1818
{
1919
"id": "stF4Q4m5GZg",
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
{% extends "idr_gallery/base.html" %} {% block content %}
2+
3+
<style>
4+
article {
5+
max-width: 800px;
6+
margin: 0 auto;
7+
padding: 20px;
8+
}
9+
.download_list {
10+
list-style: none;
11+
background: white;
12+
margin: 0;
13+
padding: 15px;
14+
margin-bottom: 20px;
15+
border-radius: 5px;
16+
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
17+
border: solid 1px lightgrey;
18+
}
19+
a.file_download {
20+
color: #03A9F4;
21+
text-decoration: none;
22+
font-weight: normal;
23+
font-size: 14px;
24+
}
25+
a.file_download:hover {
26+
text-decoration: underline;
27+
}
28+
</style>
29+
30+
<article>
31+
<div style="display: flex; gap: 20px; flex-direction: row;">
32+
<div style="flex: 0 0 96px;">
33+
<img src="{% url 'render_thumbnail' image.id %}" alt="Thumbnail for {{ image.name }}" border: 1px solid #ccc; border-radius: 5px;">
34+
</div>
35+
<div style="flex: 1 1 auto">
36+
37+
<h2>Image Name: {{ image.name }}</h2>
38+
<strong>ID: {{ image.id }}</strong><br />
39+
<strong>Study: {{ idr_study }}</strong>
40+
<p>
41+
This image is not viewable online. <br/>
42+
The IDR only supports the viewing of OME-Zarr images.
43+
</p>
44+
</div>
45+
</div>
46+
47+
{% if fileset %}
48+
<h3>Download Image Files</h3>
49+
{% if data_location == "Github" %}
50+
<p>
51+
This image is defined by a {% if is_pattern %}.pattern{% else %}companion.ome{% endif %} file
52+
and sibling .tiff files which are on GitHub (links below).
53+
Each .tiff file is a symbolic link to the actual image file in
54+
<!-- link is updated from download_urls.tsv info -->
55+
<a id="download_url_tsv" target="_blank" class="file_download" href="{{ download_url }}">{{ download_url }}</a>.
56+
</p>
57+
{% elif fileset.file_urls|length == 1 %}
58+
<p>There is 1 file associated with this image. Click to download:</p>
59+
{% else %}
60+
<p>
61+
There are {{ fileset.file_urls|length }} files associated with this image
62+
which can be downloaded from the links below. For more download options,
63+
including bulk download using Globus or FTP clients, see the
64+
<a href="/about/download.html">IDR Data download page</a>.
65+
</p>
66+
{% endif %}
67+
68+
<ul class="download_list">
69+
{% for file in fileset.file_urls %}
70+
<li>
71+
{% if file.url %}
72+
<a class="file_download" target="_blank" href="{{ file.url }}">{{ file.path }}</a>
73+
{% else %} {{ file.path }} {% endif %}
74+
</li>
75+
{% endfor %}
76+
</ul>
77+
{% else %}
78+
<!-- Only expected for some OME-Zarr images (this page won't show for them) -->
79+
<p>No associated fileset.</p>
80+
{% endif %}
81+
82+
<!-- <details><summary>Extra info (debug)</summary>
83+
<ul style="background: white">
84+
<li>Image Path: {{ img_path }}</li>
85+
<li>Data Location: {{ data_location }}</li>
86+
<li>Is Zarr?: {{ is_zarr }}</li>
87+
<li>Download URL from IDR: <a href="{{ download_url }}">{{ download_url }}</a></li>
88+
<li>BIA NGFF ID: {{ bia_ngff_id }}</li>
89+
</ul>
90+
</details> -->
91+
</article>
92+
93+
<script>
94+
const IDR_ID_NAME = "{{ idr_study }}";
95+
let IDR_ID = IDR_ID_NAME.split("-")[0];
96+
let DOWNLOAD_URL = "{{ download_url }}";
97+
98+
function checkLinks() {
99+
let links = Array.from(document.querySelectorAll("a"));
100+
// links = links.slice(0,50)
101+
links.forEach((link) => {
102+
// ignore image viewer links
103+
if (!link.href || link.href.includes("img_detail")) return;
104+
// no cors-origin check for now, just check if the link is valid
105+
fetch(link.href, { method: "HEAD" })
106+
.then((response) => {
107+
link.style.color = response.ok ? "green" : "orange";
108+
link.title = response.ok ? "Link is valid" : "Link is broken";
109+
})
110+
.catch((error) => {
111+
// show "pink" and re-try with server-side check, to avoid CORS issues
112+
console.error("Error checking link:", error);
113+
link.style.color = "pink";
114+
link.title = "Error checking link";
115+
116+
fetch(`/link_check/?url=${encodeURIComponent(link.href)}`)
117+
.then((res) => res.json())
118+
.then((data) => {
119+
console.log("Link check data:", data);
120+
if (data.is_valid) {
121+
link.style.color = "green";
122+
link.title = "Link is valid (checked with server)";
123+
} else {
124+
link.style.color = "red";
125+
link.title = `Link is broken: ${data.error}`;
126+
}
127+
});
128+
});
129+
});
130+
}
131+
132+
document.addEventListener("DOMContentLoaded", function () {
133+
// Load download URLs from TSV file in GitHub to fix the download URL for this image
134+
fetch(
135+
"https://raw.githubusercontent.com/IDR/idr.openmicroscopy.org/refs/heads/master/_data/download_urls.tsv",
136+
)
137+
.then((response) => response.text())
138+
.then((data) => {
139+
const lines = data.split("\n");
140+
141+
// Use first line as header to find column names...
142+
const headers = lines[0].split("\t");
143+
144+
const idrIndex = headers.indexOf("idrid");
145+
146+
// Find the line for this IDR ID
147+
const studyLine = lines.find(
148+
(line) => line.split("\t")[idrIndex] === IDR_ID,
149+
);
150+
console.log(`Found line for ${IDR_ID}:`, studyLine);
151+
if (studyLine) {
152+
const cells = studyLine.split("\t");
153+
const downloadUrlIndex = headers.indexOf("download_url");
154+
// downloadUrl e.g. https://ftp.ebi.ac.uk/pub/databases/IDR/idr0047-neuert-yeastmrna/
155+
const downloadUrl = cells[downloadUrlIndex];
156+
let link = document.getElementById("download_url_tsv");
157+
if (link) {
158+
link.textContent = downloadUrl;
159+
link.href = downloadUrl;
160+
}
161+
const baseUrl = downloadUrl.split(IDR_ID)[0]; // e.g. https://ftp.ebi.ac.uk/pub/databases/IDR/
162+
console.log(`Download URL for ${IDR_ID}:`, downloadUrl);
163+
if (downloadUrl && downloadUrl !== DOWNLOAD_URL) {
164+
console.log(`Updating download URLs from ${DOWNLOAD_URL} to ${downloadUrl}`);
165+
// update all ".file_download" links to this download URL
166+
const fileDownloadLinks =
167+
document.querySelectorAll(".file_download");
168+
fileDownloadLinks.forEach((link) => {
169+
link.href = link.href.replace(DOWNLOAD_URL, downloadUrl);
170+
});
171+
}
172+
} else {
173+
console.warn(`No download URL found for ${IDR_ID} in TSV file`);
174+
}
175+
176+
// After updating links, check them if ?check_links=1 is in the URL
177+
const urlParams = new URLSearchParams(window.location.search);
178+
if (urlParams.get("check_links")) {
179+
checkLinks();
180+
}
181+
});
182+
});
183+
</script>
184+
185+
{% endblock %}
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
{% extends "idr_gallery/base.html" %}
2+
3+
{% block content %}
4+
5+
6+
<style>
7+
body {
8+
background-color: #f6f6f9;
9+
}
10+
11+
table {
12+
width: 100%;
13+
border-collapse: collapse;
14+
font-size: 12px;
15+
}
16+
17+
</style>
18+
19+
<h1>Download URLs</h1>
20+
21+
<div id="table-container">
22+
<p>Loading download URLs...</p>
23+
</div>
24+
25+
<script>
26+
27+
async function checkLinks() {
28+
let links = Array.from(document.querySelectorAll('a'));
29+
// links = links.slice(0,50)
30+
for (let link of links) {
31+
// links.forEach(async link => {
32+
// ignore image viewer links
33+
if (!link.href || link.href.includes("img_detail")) {
34+
continue;
35+
};
36+
// no cors-origin check for now, just check if the link is valid
37+
let ok = await fetch(link.href, { method: 'HEAD'})
38+
.then(response => {
39+
link.style.color = response.ok ? 'green' : 'orange';
40+
link.title = response.ok ? 'Link is valid' : 'Link is broken';
41+
return true;
42+
})
43+
.catch(error => {
44+
console.error('Error checking link:', error);
45+
return false;
46+
});
47+
if (!ok) {
48+
// show "pink" and re-try with server-side check, to avoid CORS issues
49+
link.style.color = 'pink';
50+
link.title = 'Error checking link';
51+
52+
await fetch(`/link_check/?url=${encodeURIComponent(link.href)}`)
53+
.then(res => res.json())
54+
.then(data => {
55+
if (data.is_valid) {
56+
link.style.color = 'green';
57+
link.title = 'Link is valid (checked with server)';
58+
} else {
59+
link.style.color = 'red';
60+
link.title = `Link is broken: ${data.error}`;
61+
}
62+
});
63+
}
64+
};
65+
}
66+
67+
// Fetch the TSV file and display it in a table
68+
fetch('https://raw.githubusercontent.com/IDR/idr.openmicroscopy.org/refs/heads/master/_data/download_urls.tsv')
69+
.then(response => response.text())
70+
.then(data => {
71+
const lines = data.split('\n');
72+
const table = document.createElement('table');
73+
table.style.width = '100%';
74+
table.style.borderCollapse = 'collapse';
75+
76+
// Create table header
77+
const header = table.createTHead();
78+
const headerRow = header.insertRow();
79+
const headers = lines[0].split('\t');
80+
headers.forEach(headerText => {
81+
const th = document.createElement('th');
82+
th.textContent = headerText;
83+
th.style.border = '1px solid #ddd';
84+
th.style.padding = '2px';
85+
th.style.backgroundColor = '#f2f2f2';
86+
headerRow.appendChild(th);
87+
});
88+
89+
let clientPathIndex = headers.indexOf('client_path');
90+
let downloadUrlIndex = headers.indexOf('download_url');
91+
let idrIdIndex = headers.indexOf('idrid');
92+
let imageIdIndex = headers.indexOf('image_id');
93+
let dataLocationIndex = headers.indexOf('data_location');
94+
95+
// Create table body - update client_path to URL, based on the download_url column...
96+
const tbody = table.createTBody();
97+
lines.slice(1).forEach(line => {
98+
if (line.trim() === '') return; // Skip empty lines
99+
const row = tbody.insertRow();
100+
const cells = line.split('\t');
101+
102+
let idrId = cells[idrIdIndex];
103+
let clientPath = cells[clientPathIndex];
104+
let downloadUrl = cells[downloadUrlIndex];
105+
let dataLocation = cells[dataLocationIndex];
106+
let clientPathUrl;
107+
if (dataLocation == "Github") {
108+
let branch = "main";
109+
// e.g. data/idr-metadata/idr0106-kubota-lunglightsheet/experimentA/companions/Mosaic_Image.companion.ome
110+
// links to https://github.com/IDR/idr0106-kubota-lunglightsheet/blob/main/experimentA/companions/Mosaic_Image.companion.ome
111+
// uod/idr/metadata/idr0052-walther-condensinmap/experimentA/companions/160719_NCAPD2gfpc272c78_MitoSys2/conc/cell0005_R0001.companion.ome
112+
// links to https://github.com/IDR/idr0052-walther-condensinmap/blob/master/experimentA/companions/160719_NCAPD2gfpc272c78_MitoSys2/conc/cell0005_R0001.companion.ome
113+
// uod/idr/metadata/idr0079-hartmann-lateralline/companions/experimentA/056F63395C/056F63395C.companion.ome
114+
// https://github.com/IDR/idr0079-hartmann-lateralline/blob/master/companions/experimentA/056F63395C/056F63395C.companion.ome
115+
let relativePath = clientPath.split("metadata/idr")[1];
116+
let githubRepo = "idr" + relativePath.split("/")[0];
117+
// some repos use "master" branch, so check for those...
118+
if ("idr0079,idr0052,idr0065,idr0075,idr0100".includes(githubRepo.split("-")[0])) {
119+
branch = "master";
120+
}
121+
relativePath = relativePath.split("/").slice(1).join("/");
122+
clientPathUrl = `https://github.com/IDR/${githubRepo}/blob/${branch}/${relativePath}`;
123+
124+
} else if (downloadUrl.includes(idrId) && clientPath.includes(idrId)) {
125+
// e.g. https://ftp.ebi.ac.uk/pub/databases/IDR/idr0001-graml-sysgro
126+
let urlBase = downloadUrl.split(idrId)[0];
127+
let urlPath = clientPath.split(idrId)[1];
128+
clientPathUrl = urlBase + idrId + urlPath;
129+
}
130+
if (clientPathUrl) {
131+
// client_path needs patching for /idr0045-reichmann-zygotespindle/
132+
clientPathUrl = clientPathUrl.replace("/idr0045-reichmann/", "/idr0045-reichmann-zygotespindle/");
133+
}
134+
135+
cells.forEach((cellText, colIndex) => {
136+
const td = document.createElement('td');
137+
td.style.border = '1px solid #ddd';
138+
td.style.padding = '2px';
139+
// handle links or 'client_path' column...
140+
if (cellText.startsWith('http') || (headers[colIndex] === 'client_path' && clientPathUrl)) {
141+
const link = document.createElement('a');
142+
// escape the URL to avoid issues with special characters in the client_path
143+
link.href = encodeURI(cellText.startsWith('http') ? cellText : clientPathUrl).replace("#", "%23");
144+
// fix idr0045 as above
145+
cellText = cellText.replace("/idr0045-reichmann/", "/idr0045-reichmann-zygotespindle/");
146+
link.textContent = cellText;
147+
link.target = '_blank';
148+
td.textContent = '';
149+
td.appendChild(link);
150+
} else if (colIndex == imageIdIndex) {
151+
// Add link to image viewer at /webclient/img_detail/1884807/
152+
const link = document.createElement('a');
153+
link.href = encodeURI(`/webclient/img_detail/${cellText}/?check_links=true`).replace("#", "%23");
154+
link.textContent = cellText;
155+
link.target = '_blank';
156+
td.textContent = '';
157+
td.appendChild(link);
158+
} else {
159+
td.textContent = cellText;
160+
}
161+
row.appendChild(td);
162+
});
163+
});
164+
const tableContainer = document.getElementById('table-container');
165+
tableContainer.innerHTML = '';
166+
tableContainer.appendChild(table);
167+
168+
checkLinks();
169+
})
170+
.catch(error => {
171+
console.error('Error fetching TSV file:', error);
172+
const tableContainer = document.getElementById('table-container');
173+
tableContainer.innerHTML = '<p>Error loading download URLs.</p>';
174+
});
175+
176+
</script>
177+
178+
{% endblock %}

0 commit comments

Comments
 (0)