UNPKG

@gmod/jbrowse

Version:

JBrowse - client-side genome browser

184 lines (166 loc) 7.26 kB
define( ['dojo/_base/declare', 'dojo/_base/array', 'dojo/promise/all', 'JBrowse/Util', 'JBrowse/View/Track/HTMLFeatures', 'JBrowse/View/Track/_AlignmentsMixin' ], function( declare, array, all, Util, HTMLFeatures, AlignmentsMixin ) { // return declare( HTMLFeatures, return declare( [ HTMLFeatures, AlignmentsMixin], /** * @lends JBrowse.View.Track.Alignments */ { _defaultConfig: function() { return Util.deepUpdate( dojo.clone( this.inherited(arguments) ), { maxFeatureScreenDensity: 1.5, layoutPitchY: 4, hideDuplicateReads: true, hideQCFailingReads: true, hideSecondary: true, hideSupplementary: true, hideMissingMatepairs: false, hideImproperPairs: false, hideUnmapped: true, hideUnsplicedReads: false, hideForwardStrand: false, hideReverseStrand: false, style: { _defaultLabelScale: 50, className: 'alignment', arrowheadClass: 'arrowhead', centerChildrenVertically: true, showMismatches: true, showSubfeatures: false, showLabels: false } } ); }, renderFeature: function( feature, uniqueId, block, scale, labelScale, descriptionScale, containerStart, containerEnd ) { var featDiv = this.inherited( arguments ); if( ! featDiv ) return null; var displayStart = Math.max( feature.get('start'), containerStart ); var displayEnd = Math.min( feature.get('end'), containerEnd ); if( this.config.style.showMismatches ) { this._drawMismatches( feature, featDiv, scale, displayStart, displayEnd ); } // if this feature is part of a multi-segment read, and not // all of its segments are aligned, add missing_mate to its // class if( feature.get('multi_segment_template') && !feature.get('multi_segment_all_aligned') ) featDiv.className += ' missing_mate'; return featDiv; }, handleSubFeatures: function( feature, featDiv, displayStart, displayEnd, block ) { if( this.config.style.showSubfeatures ) { this.inherited(arguments); } }, /** * draw base-mismatches on the feature */ _drawMismatches: function( feature, featDiv, scale, displayStart, displayEnd ) { var featLength = displayEnd - displayStart; // recall: scale is pixels/basepair if ( featLength*scale > 1 ) { var mismatches = this._getMismatches( feature ); var charSize = this.getCharacterMeasurements(); var drawChars = scale >= charSize.w; array.forEach( mismatches, function( mismatch ) { var start = feature.get('start') + mismatch.start; var end = start + mismatch.length; // if the feature has been truncated to where it doesn't cover // this mismatch anymore, just skip this mismatch if ( end <= displayStart || start >= displayEnd ) return; var base = mismatch.base; var mDisplayStart = Math.max( start, displayStart ); var mDisplayEnd = Math.min( end, displayEnd ); var mDisplayWidth = mDisplayEnd - mDisplayStart; var overall = dojo.create('span', { className: mismatch.type + ' base_'+base.toLowerCase(), style: { position: 'absolute', left: 100 * ( mDisplayStart - displayStart)/featLength + '%', width: scale*mDisplayWidth>1 ? 100 * mDisplayWidth/featLength + '%' : '1px' } }, featDiv ); // give the mismatch a mouseover if not drawing a character with the mismatch base if( ! drawChars ) overall.title = base; if( drawChars && mismatch.length <= 20 ) { for( var i = 0; i<mismatch.length; i++ ) { var basePosition = start + i; if( basePosition >= mDisplayStart && basePosition <= mDisplayEnd ) { dojo.create('span',{ className: 'base base_'+base.toLowerCase(), style: { position: 'absolute', width: scale+'px', left: (basePosition-mDisplayStart)/mDisplayWidth*100 + '%' }, innerHTML: base }, overall ); } } } }, this ); } }, /** * @returns {Object} containing <code>h</code> and <code>w</code>, * in pixels, of the characters being used for sequences */ getCharacterMeasurements: function() { if( !this._measurements ) this._measurements = this._measureSequenceCharacterSize( this.div ); return this._measurements; }, /** * Conducts a test with DOM elements to measure sequence text width * and height. */ _measureSequenceCharacterSize: function( containerElement ) { var widthTest = dojo.create('div', { innerHTML: '<span class="base mismatch">A</span>' +'<span class="base mismatch">C</span>' +'<span class="base mismatch">T</span>' +'<span class="base mismatch">G</span>' +'<span class="base mismatch">N</span>', style: { visibility: 'hidden', position: 'absolute', left: '0px' } }, containerElement ); var result = { w: widthTest.clientWidth / 5, h: widthTest.clientHeight }; containerElement.removeChild(widthTest); return result; }, _trackMenuOptions: function() { return all([ this.inherited(arguments), this._alignmentsFilterTrackMenuOptions() ]) .then( function( options ) { var o = options.shift(); options.unshift({ type: 'dijit/MenuSeparator' } ); return o.concat.apply( o, options ); }); } }); });