imagesync.js |
|
---|---|
Copyright 2013 Allen Institute for Brain Science Licensed under the Apache License, Version 2.0 (the “License”); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. |
|
This script primarily builds URLs to imageservice images and demonstrates
how to use the |
|
Contants that point to the imageservice and API, respectively. |
var svcPath = "http://api.brain-map.org/cgi-bin/imageservice";
var apiPath = "http://api.brain-map.org/api/v2/"; |
All adult mouse images have the same maximum resolution (physical pixel size), but but they do not have the same dimensions. For presentation, we have resampled the original images at multiple lower resolutions all the way down to a 256x256 thumbnail. The number of tiers in this image pyramid depends on the original dimensions of the image. When making requests to the imageservice, the |
var downsample = 4;
var w = 285;
var h = 285; |
Specify default image ids to show, and change them as requested in the url parameter string. |
var id1 = 69855739; // adora2a
var id2 = 71920507; // rasd
var atlasId = 2; // p56, sagittal
var urlVars = getUrlVars();
if ('id1' in urlVars)
id1 = urlVars.id1;
if ('id2' in urlVars)
id2 = urlVars.id2;
if ('atlasId' in urlVars)
atlasId = urlVars.atlasId; |
Build the jQuery reload button. When clicked, call |
$('#reloadButton').button().click(reloadImages);
$('#image1Anchor').html(id1).attr("href","http://mouse.brain-map.org/experiment/show/"+id1);
$('#image2Anchor').html(id2).attr("href","http://mouse.brain-map.org/experiment/show/"+id2);
$('#image1').width(w).height(h);
$('#image2').width(w).height(h);
$('#referenceNissl').width(w).height(h);
$('#referenceAnnot').width(w).height(h);
$("#homeButton").button({ icons: { primary: "ui-icon-home" }}); |
Load the images first time the page is loaded. |
reloadImages();
function reloadImages() { |
First load the meta-data related to the first image id |
loadImageInfo(id1, function(dataSet) { |
Results always come back as an array, even if there’s only one result. |
dataSet = dataSet[0];
$('#image1Anchor').html(dataSet.genes[0].acronym); |
Section Data Sets are composed of many section images. For this demo, we’ll just grab a random section image from id1’s section image list. |
var r = Math.floor(Math.random() * dataSet.section_images.length);
var sectionImage1 = dataSet.section_images[r]; |
Get the central coordinate of the image. |
var cx1 = Math.floor(sectionImage1.width*.5);
var cy1 = Math.floor(sectionImage1.height*.5);
var img1Url = makeCenteredImageUrl(downsample,
sectionImage1.path,
sectionImage1.y + cy1,
sectionImage1.x + cx1,
w, h); |
Add the img to the relevant div. |
$('#image1').css('background','no-repeat center url('+img1Url+')');
|
Take the center pixel index from our cropped image region and make
an |
imageToImage(cx1, cy1, sectionImage1.id, id2, function(coords) {
coords = coords[0].image_sync;
var cx2 = coords.x;
var cy2 = coords.y;
var sectionNum = coords.section_number;
|
Load the meta data for the second image. |
loadImageInfo(id2, function(dataSet) {
|
Results always come back as an array, if if there’s only one result. |
dataSet = dataSet[0];
$('#image2Anchor').html(dataSet.genes[0].acronym); |
The |
var sectionImage2 = null;
for (var i=0; i<dataSet.section_images.length; i++) {
var s = dataSet.section_images[i];
if (s.section_number == sectionNum)
sectionImage2 = s;
} |
Figure out the best downsample, comparing source/target resolutions. |
var targetDownsample = computeDownsample(sectionImage1.resolution,
sectionImage2.resolution,
downsample); |
Build the imageservice url for the new image, add it to the div. |
var img2Url = makeCenteredImageUrl(targetDownsample,
sectionImage2.path,
sectionImage2.y + cy2,
sectionImage2.x + cx2,
w, h);
$('#image2').css('background','no-repeat center url('+img2Url+')');
});
}); |
Take that same center pixel coordinate from the first image and figure
out what pixel it corresponds to the in the ABA reference atlas using
the |
imageToAtlas(cx1, cy1, sectionImage1.id, atlasId, function(coords) {
coords = coords.image_sync;
var cx2 = coords.x;
var cy2 = coords.y;
var referenceImageId = coords.section_image_id; |
Load the atlas image meta data. |
loadAtlasImageInfo(coords.section_image_id, function(atlasImage) { |
Results always come back as an array, even if there’s only one result. |
atlasImage = atlasImage[0]; |
Build a URL to the atlas Nissl. |
var nisslUrl = makeCenteredImageUrl(downsample,
atlasImage.path,
atlasImage.y + cy2,
atlasImage.x + cx2,
w, h);
$('#referenceNissl').css('background','no-repeat center url('+nisslUrl+')'); |
Annotated Nissl images are also available in the
|
var atlasPath = "";
for (var i=0; i<atlasImage.alternate_images.length; i++) {
var altImage = atlasImage.alternate_images[i];
if (altImage.image_type.indexOf("Atlas") == 0)
atlasPath = altImage.path;
}
if (atlasPath) { |
Figure out the best downsample, comparing source/target resolutions. |
var targetDownsample = computeDownsample(sectionImage1.resolution,
atlasImage.resolution,
downsample);
var annotUrl = makeCenteredImageUrl(targetDownsample,
atlasPath,
atlasImage.y + cy2,
atlasImage.x + cx2,
w, h);
$('#referenceAnnot').css("background","no-repeat center url("+annotUrl+")");
}
});
});
});
} |
Load the meta data for a image based on its SectionDataSetId. |
function loadImageInfo(id,onsuccess) {
var url = apiPath + 'data/SectionDataSet/'+id+'.json?include=section_images,genes';
apiQuery(url, onsuccess);
} |
Find the pixel and section index in one SectionDataSet corresponding to a pixel location in a section image. |
function imageToImage(x, y, fromSectionImageId, toSectionDataSetId, onsuccess) {
var url = apiPath + 'image_to_image/' + fromSectionImageId + '.json' +
'?x=' + x +
'&y=' + y +
'§ion_data_set_ids=' + toSectionDataSetId;
apiQuery(url, onsuccess);
} |
This is very similar to |
function loadAtlasImageInfo(sectionId, onsuccess) {
var url = apiPath + 'data/AtlasImage/'+sectionId+'.json' +
'?include=alternate_images';
apiQuery(url, onsuccess);
} |
Find the pixel and section index in an atlas corresponding to a pixel location in a section image. |
function imageToAtlas(x, y, sectionImageId, atlasId, onsuccess) {
var url = apiPath + 'image_to_atlas/' + sectionImageId + '.json' +
'?x=' + x +
'&y=' + y +
'&atlas_id=' + atlasId;
apiQuery(url, onsuccess);
} |
Helper function to build imageservice urls. For this type of query, you supply the upper left pixel index in full resolution image coordinates and width and height in the coordinates at your desired downsampled tier. |
function makeImageUrl(downsample, path, top, left, width, height) {
return svcPath + '?' +
'downsample=' + downsample +
'&path=' + path +
'&top=' + top +
'&left=' + left +
"&width=" + width +
"&height=" + height;
} |
This method wraps |
function makeCenteredImageUrl(downsample, path, cy, cx, width, height) {
var scale = Math.pow(2,downsample);
var left = cx - width * 0.5 * scale;
var top = cy - height * 0.5 * scale;
return makeImageUrl(downsample, path, top, left, width, height);
} |
Sections have pixel resolution (in microns). The source section was
downsampled by the value of the |
function computeDownsample(sourceResolution, targetResolution, sourceDownsample) {
var r = sourceResolution / targetResolution;
return Math.round( sourceDownsample + (Math.log(r)/Math.log(2)) );
} |
Make a simple apiQuery, no handling of pages. |
function apiQuery(url, onsuccess) {
$.ajax(url, {
dataType: 'json',
success: function(response) {
if (response.success)
onsuccess(response.msg);
else
apiError(response.msg, url);
},
error: function(response) { apiError(response.statusText, url); }
});
} |
A simple catch-all error reporting function. |
function apiError(response, url) {
var errorHtml =
"<p>There was an error with the following query:</p>" +
"<p>" + url + "</p>" +
"<p>Error message:</p>" +
"<p>" + response + "</p>";
var dialog = $( "#errorDialog" );
var existingErrors = dialog.html();
$( "#errorDialog" )
.html(existingErrors + errorHtml)
.dialog({
width: 500,
height: 200,
modal: true
});
} |
This function splits the URL parameter string into a javascript hash. |
function getUrlVars()
{
var vars = [], hash;
var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
for(var i = 0; i < hashes.length; i++)
{
hash = hashes[i].split('=');
vars.push(hash[0]);
vars[hash[0]] = hash[1];
}
return vars;
} |