@gmod/jbrowse
Version:
JBrowse - client-side genome browser
136 lines (115 loc) • 4.23 kB
JavaScript
define(
[
'dojo/_base/declare',
'dojo/_base/Deferred',
'JBrowse/Store',
'JBrowse/Store/DeferredStatsMixin',
'JBrowse/Util'
],
function( declare, Deferred, Store, DeferredStatsMixin, Util ) {
return declare( [ Store, DeferredStatsMixin ],
/**
* Implements a store for image tiles that are only available at a
* fixed set of sizes and zoom levels. Most often used with
* pre-generated image tiles served statically.
* @lends JBrowse.Store.TiledImage.Fixed
* @class
* @extends Store
*/
{
constructor: function(args) {
this.tileToImage = {};
this.zoomCache = {};
this.baseUrl = args.baseUrl;
this.url = this.resolveUrl( args.urlTemplate );
this._deferred.images = new Deferred();
dojo.xhrGet({ url: this.url,
handleAs: "json",
failOk: true,
load: dojo.hitch( this, function(o) {
this.loadSuccess(o);
}),
error: dojo.hitch( this, '_failAllDeferred' )
});
},
loadSuccess: function(o) {
this.globalStats = o.stats || {};
//backcompat
if( ! ('scoreMin' in this.globalStats ) )
this.globalStats.scoreMin = this.globalStats.global_min;
if( ! ('scoreMax' in this.globalStats ) )
this.globalStats.scoreMax = this.globalStats.global_max;
//tileWidth: width, in pixels, of the tiles
this.tileWidth = o.tileWidth;
this.align = o.align;
//zoomLevels: array of {basesPerTile, urlPrefix} hashes
this.zoomLevels = o.zoomLevels;
this._deferred.stats.resolve({success: true});
this._deferred.images.resolve({success: true});
},
/**
* @private
*/
_getZoom: function(scale) {
var result = this.zoomCache[scale];
if (result) return result;
result = this.zoomLevels[0];
var desiredBases = this.tileWidth / scale;
for (var i = 1; i < this.zoomLevels.length; i++) {
if (Math.abs(this.zoomLevels[i].basesPerTile - desiredBases)
< Math.abs(result.basesPerTile - desiredBases))
result = this.zoomLevels[i];
}
this.zoomCache[scale] = result;
return result;
},
getImages: function( query, callback, errorCallback ) {
var thisB = this;
this._deferred.images.then(
function( result ) {
if( result.success )
thisB._getImages( query, callback, errorCallback );
else {
thisB.error = result.error;
errorCallback( result.error || result );
}
},
errorCallback
);
},
/**
* Fetch an array of <code><img></code> elements for the image
* tiles that should be displayed for a certain magnification scale
* and section of the reference.
*/
_getImages: function( query, callback, errorCallback ) {
var scale = query.scale || 1;
var startBase = query.start;
var endBase = query.end;
var zoom = this._getZoom( scale );
var startTile = Math.max( startBase / zoom.basesPerTile, 0 ) | 0;
var endTile = endBase / zoom.basesPerTile | 0;
var result = [];
var im;
for (var i = startTile; i <= endTile; i++) {
im = document.createElement("img");
dojo.connect(im, "onerror", this.handleImageError );
im.src = this._imageSource( zoom, i );
//TODO: need image coord systems that don't start at 0?
im.startBase = (i * zoom.basesPerTile); // + this.refSeq.start;
im.baseWidth = zoom.basesPerTile;
im.tileNum = i;
result.push(im);
}
callback( result );
},
/**
* Gives the image source for a given zoom (as returned by _getZoom())
* and tileIndex.
* @private
*/
_imageSource: function( zoom, tileIndex ) {
return Util.resolveUrl(this.url, zoom.urlPrefix + tileIndex + ".png");
}
});
});