<commit_before>function SimpleFeatureTrack(trackMeta, refSeq, changeCallback) {
    //className: CSS class for the features
    //padding: min pixels between each feature horizontally

    Track.call(this, trackMeta.label, trackMeta.key, false, changeCallback);
    //this.count = trackInfo.featureCount;
    this.fields = {};
    //for (var i = 0; i < trackInfo.map.length; i++) {
    //	this.fields[trackInfo.map[i]] = i;
    //}
    this.features = new NCList();
    //this.features.importExisting(trackInfo.featureNCList, trackInfo.sublistIndex);
    this.className = trackMeta.className;
    this.refSeq = refSeq;
    //this.histScale = histScale;
    //this.labelScale = labelScale;
    //number of histogram bins per block
    this.numBins = 25;
    this.histLabel = false;
    this.padding = 5;

    this.trackMeta = trackMeta;
    var curTrack = this;
    var trackSuccess = function(o) {
	curTrack.loadSuccess(o);
    }
    YAHOO.util.Connect.asyncRequest("GET", trackMeta.url, {success: trackSuccess});
}

SimpleFeatureTrack.prototype = new Track("");

SimpleFeatureTrack.prototype.loadSuccess = function(o) {
    var startTime = new Date().getTime();
    var trackInfo = eval(o.responseText);
    this.count = trackInfo.featureCount;
    for (var i = 0; i < trackInfo.map.length; i++) {
	this.fields[trackInfo.map[i]] = i;
    }
    this.features.importExisting(trackInfo.featureNCList, trackInfo.sublistIndex);
    this.histScale = 4 * (trackInfo.featureCount / this.refSeq.length());
    this.labelScale = 50 * (trackInfo.featureCount / this.refSeq.length());
    
    YAHOO.log((new Date().getTime() - startTime) / 1000);

    this.setLoaded();
}

SimpleFeatureTrack.prototype.setViewInfo = function(numBlocks, trackDiv,
                                                    labelDiv, widthPct,
                                                    widthPx) {
    Track.prototype.setViewInfo.apply(this, [numBlocks, trackDiv, labelDiv,
                                             widthPct, widthPx]);
    this.setLabel(this.key);
}

SimpleFeatureTrack.prototype.fillHist = function(block, leftBase, rightBase,
						 stripeWidth) {
    var hist = this.features.histogram(leftBase, rightBase, this.numBins);
    //console.log(hist);
    var maxBin = 0;
    for (var bin = 0; bin < this.numBins; bin++)
	maxBin = Math.max(maxBin, hist[bin]);
    var binDiv;
    for (var bin = 0; bin < this.numBins; bin++) {
        binDiv = document.createElement("div");
	binDiv.className = this.className + "-hist";;
        binDiv.style.cssText = 
            "left: " + ((bin / this.numBins) * 100) + "%; "
            + "height: " + (2 * hist[bin]) + "px;"
	    + "bottom: 0px;"
            + "width: " + (((1 / this.numBins) * 100) - (100 / stripeWidth)) + "%;";
        if (Util.is_ie6) binDiv.appendChild(document.createComment());
        block.appendChild(binDiv);
    }
    //TODO: come up with a better method for scaling than 2 px per count
    return 2 * maxBin;
}

SimpleFeatureTrack.prototype.endZoom = function(destScale, destBlockBases) {
    if (destScale < this.histScale) {
        this.setLabel(this.key + "<br>per " + Math.round(destBlockBases / this.numBins) + "bp");
    } else {
        this.setLabel(this.key);
    }
    this.clear();
}

SimpleFeatureTrack.prototype.fillBlock = function(block, leftBlock, rightBlock, leftBase, rightBase, scale, stripeWidth) {
    //console.log("scale: %d, histScale: %d", scale, this.histScale);
    if (scale < this.histScale) {
	return this.fillHist(block, leftBase, rightBase, stripeWidth);
    } else {
	return this.fillFeatures(block, leftBlock, rightBlock, 
				 leftBase, rightBase, scale);
    }
}

SimpleFeatureTrack.prototype.transfer = function(sourceBlock, destBlock) {
    //transfer(sourceBlock, destBlock) is called when sourceBlock gets deleted.
    //Any child features of sourceBlock that extend onto destBlock should get
    //moved onto destBlock.

    if (!(sourceBlock && destBlock)) return;

    var sourceSlots;
    if (sourceBlock.startBase < destBlock.startBase)
	sourceSlots = sourceBlock.rightSlots;
    else
	sourceSlots = sourceBlock.leftSlots;

    if (sourceSlots === undefined) return;

    var destLeft = destBlock.startBase;
    var destRight = destBlock.endBase;
    var blockWidth = destRight - destLeft;
    var sourceSlot;

    for (var i = 0; i < sourceSlots.length; i++) {
	//if the feature div in this slot is a child of sourceBlock,
	//and if the feature overlaps destBlock,
	//move to destBlock & re-position
	sourceSlot = sourceSlots[i];
	if (sourceSlot && (sourceSlot.parentNode === sourceBlock)) {
	    if ((sourceSlot.feature[1] > destLeft)
		&& (sourceSlot.feature[0] < destRight)) {
		var featLeft = (100 * (sourceSlot.feature[0] - destLeft) / blockWidth);
		sourceSlot.style.left = featLeft + "%";
		destBlock.appendChild(sourceSlot);
		if ("label" in sourceSlot) {
		    sourceSlot.label.style.left = featLeft + "%";
		    destBlock.appendChild(sourceSlot.label);
		}
	    }
	}
    }	    
}

SimpleFeatureTrack.prototype.fillFeatures = function(block, 
						     leftBlock, rightBlock,
						     leftBase, rightBase,
						     scale) {
    //arguments:
    //block: div to be filled with info
    //leftBlock: div to the left of the block to be filled
    //rightBlock: div to the right of the block to be filled
    //leftBase: starting base of the block
    //rightBase: ending base of the block
    //scale: pixels per base at the current zoom level
    //0-based
    //returns: height of the block, in pixels

    var start = this.fields["start"];
    var end = this.fields["end"];
    var strand = this.fields["strand"];
    var name = this.fields["name"];
    var phase = this.fields["phase"];

    var slots = [];

    //are we filling right-to-left (true) or left-to-right (false)?
    //this affects how we do layout
    var goLeft = false;

    //determine dimensions of labels (height, per-character width)
    if (!("nameHeight" in this)) {
	var heightTest = document.createElement("div");
	heightTest.className = "feature-label";
	heightTest.style.height = "auto";
	heightTest.style.visibility = "hidden";
	heightTest.appendChild(document.createTextNode("1234567890"));
	document.body.appendChild(heightTest);
	this.nameHeight = heightTest.clientHeight;
	this.nameWidth = heightTest.clientWidth / 10;
	document.body.removeChild(heightTest);
    }

    //determine the height of the glyph
    if (!("glyphHeight" in this)) {
	var heightTest = document.createElement("div");
	//cover all the bases: stranded or not, phase or not
	heightTest.className = this.className + " plus-" + this.className + " plus-" + this.className + "1";
	heightTest.style.visibility = "hidden";
	heightTest.appendChild(document.createComment("foo"));;
	document.body.appendChild(heightTest);
	this.glyphHeight = Math.round(heightTest.offsetHeight + 2);
	this.padding += heightTest.offsetWidth;
	document.body.removeChild(heightTest);
    }	

    startSlots = new Array();
    if (leftBlock !== undefined) {
        slots = leftBlock.rightSlots.concat();
        block.leftSlots = startSlots;
    } else if (rightBlock !== undefined) {
        slots = rightBlock.leftSlots.concat();
        block.rightSlots = startSlots;
        goLeft = true;
    } else {
	block.leftSlots = startSlots;
    }

    var levelUnits = "px";
    var blockWidth = rightBase - leftBase;
    var maxLevel = 0;

    var callback = function(event) {<commit_msg>blocks don't always have slots<commit_after>function SimpleFeatureTrack(trackMeta, refSeq, changeCallback) {
    //className: CSS class for the features
    //padding: min pixels between each feature horizontally

    Track.call(this, trackMeta.label, trackMeta.key, false, changeCallback);
    //this.count = trackInfo.featureCount;
    this.fields = {};
    //for (var i = 0; i < trackInfo.map.length; i++) {
    //	this.fields[trackInfo.map[i]] = i;
    //}
    this.features = new NCList();
    //this.features.importExisting(trackInfo.featureNCList, trackInfo.sublistIndex);
    this.className = trackMeta.className;
    this.refSeq = refSeq;
    //this.histScale = histScale;
    //this.labelScale = labelScale;
    //number of histogram bins per block
    this.numBins = 25;
    this.histLabel = false;
    this.padding = 5;

    this.trackMeta = trackMeta;
    var curTrack = this;
    var trackSuccess = function(o) {
	curTrack.loadSuccess(o);
    }
    YAHOO.util.Connect.asyncRequest("GET", trackMeta.url, {success: trackSuccess});
}

SimpleFeatureTrack.prototype = new Track("");

SimpleFeatureTrack.prototype.loadSuccess = function(o) {
    var startTime = new Date().getTime();
    var trackInfo = eval(o.responseText);
    this.count = trackInfo.featureCount;
    for (var i = 0; i < trackInfo.map.length; i++) {
	this.fields[trackInfo.map[i]] = i;
    }
    this.features.importExisting(trackInfo.featureNCList, trackInfo.sublistIndex);
    this.histScale = 4 * (trackInfo.featureCount / this.refSeq.length());
    this.labelScale = 50 * (trackInfo.featureCount / this.refSeq.length());
    
    YAHOO.log((new Date().getTime() - startTime) / 1000);

    this.setLoaded();
}

SimpleFeatureTrack.prototype.setViewInfo = function(numBlocks, trackDiv,
                                                    labelDiv, widthPct,
                                                    widthPx) {
    Track.prototype.setViewInfo.apply(this, [numBlocks, trackDiv, labelDiv,
                                             widthPct, widthPx]);
    this.setLabel(this.key);
}

SimpleFeatureTrack.prototype.fillHist = function(block, leftBase, rightBase,
						 stripeWidth) {
    var hist = this.features.histogram(leftBase, rightBase, this.numBins);
    //console.log(hist);
    var maxBin = 0;
    for (var bin = 0; bin < this.numBins; bin++)
	maxBin = Math.max(maxBin, hist[bin]);
    var binDiv;
    for (var bin = 0; bin < this.numBins; bin++) {
        binDiv = document.createElement("div");
	binDiv.className = this.className + "-hist";;
        binDiv.style.cssText = 
            "left: " + ((bin / this.numBins) * 100) + "%; "
            + "height: " + (2 * hist[bin]) + "px;"
	    + "bottom: 0px;"
            + "width: " + (((1 / this.numBins) * 100) - (100 / stripeWidth)) + "%;";
        if (Util.is_ie6) binDiv.appendChild(document.createComment());
        block.appendChild(binDiv);
    }
    //TODO: come up with a better method for scaling than 2 px per count
    return 2 * maxBin;
}

SimpleFeatureTrack.prototype.endZoom = function(destScale, destBlockBases) {
    if (destScale < this.histScale) {
        this.setLabel(this.key + "<br>per " + Math.round(destBlockBases / this.numBins) + "bp");
    } else {
        this.setLabel(this.key);
    }
    this.clear();
}

SimpleFeatureTrack.prototype.fillBlock = function(block, leftBlock, rightBlock, leftBase, rightBase, scale, stripeWidth) {
    //console.log("scale: %d, histScale: %d", scale, this.histScale);
    if (scale < this.histScale) {
	return this.fillHist(block, leftBase, rightBase, stripeWidth);
    } else {
	return this.fillFeatures(block, leftBlock, rightBlock, 
				 leftBase, rightBase, scale);
    }
}

SimpleFeatureTrack.prototype.transfer = function(sourceBlock, destBlock) {
    //transfer(sourceBlock, destBlock) is called when sourceBlock gets deleted.
    //Any child features of sourceBlock that extend onto destBlock should get
    //moved onto destBlock.

    if (!(sourceBlock && destBlock)) return;

    var sourceSlots;
    if (sourceBlock.startBase < destBlock.startBase)
	sourceSlots = sourceBlock.rightSlots;
    else
	sourceSlots = sourceBlock.leftSlots;

    if (sourceSlots === undefined) return;

    var destLeft = destBlock.startBase;
    var destRight = destBlock.endBase;
    var blockWidth = destRight - destLeft;
    var sourceSlot;

    for (var i = 0; i < sourceSlots.length; i++) {
	//if the feature div in this slot is a child of sourceBlock,
	//and if the feature overlaps destBlock,
	//move to destBlock & re-position
	sourceSlot = sourceSlots[i];
	if (sourceSlot && (sourceSlot.parentNode === sourceBlock)) {
	    if ((sourceSlot.feature[1] > destLeft)
		&& (sourceSlot.feature[0] < destRight)) {
		var featLeft = (100 * (sourceSlot.feature[0] - destLeft) / blockWidth);
		sourceSlot.style.left = featLeft + "%";
		destBlock.appendChild(sourceSlot);
		if ("label" in sourceSlot) {
		    sourceSlot.label.style.left = featLeft + "%";
		    destBlock.appendChild(sourceSlot.label);
		}
	    }
	}
    }	    
}

SimpleFeatureTrack.prototype.fillFeatures = function(block, 
						     leftBlock, rightBlock,
						     leftBase, rightBase,
						     scale) {
    //arguments:
    //block: div to be filled with info
    //leftBlock: div to the left of the block to be filled
    //rightBlock: div to the right of the block to be filled
    //leftBase: starting base of the block
    //rightBase: ending base of the block
    //scale: pixels per base at the current zoom level
    //0-based
    //returns: height of the block, in pixels

    var start = this.fields["start"];
    var end = this.fields["end"];
    var strand = this.fields["strand"];
    var name = this.fields["name"];
    var phase = this.fields["phase"];

    var slots = [];

    //are we filling right-to-left (true) or left-to-right (false)?
    //this affects how we do layout
    var goLeft = false;

    //determine dimensions of labels (height, per-character width)
    if (!("nameHeight" in this)) {
	var heightTest = document.createElement("div");
	heightTest.className = "feature-label";
	heightTest.style.height = "auto";
	heightTest.style.visibility = "hidden";
	heightTest.appendChild(document.createTextNode("1234567890"));
	document.body.appendChild(heightTest);
	this.nameHeight = heightTest.clientHeight;
	this.nameWidth = heightTest.clientWidth / 10;
	document.body.removeChild(heightTest);
    }

    //determine the height of the glyph
    if (!("glyphHeight" in this)) {
	var heightTest = document.createElement("div");
	//cover all the bases: stranded or not, phase or not
	heightTest.className = this.className + " plus-" + this.className + " plus-" + this.className + "1";
	heightTest.style.visibility = "hidden";
	heightTest.appendChild(document.createComment("foo"));;
	document.body.appendChild(heightTest);
	this.glyphHeight = Math.round(heightTest.offsetHeight + 2);
	this.padding += heightTest.offsetWidth;
	document.body.removeChild(heightTest);
    }	

    startSlots = new Array();
    if (leftBlock && leftBlock.rightSlots) {
        slots = leftBlock.rightSlots.concat();
        block.leftSlots = startSlots;
    } else if (rightBlock && rightBlock.leftSlots) {
        slots = rightBlock.leftSlots.concat();
        block.rightSlots = startSlots;
        goLeft = true;
    } else {
	block.leftSlots = startSlots;
    }

    var levelUnits = "px";
    var blockWidth = rightBase - leftBase;
    var maxLevel = 0;

    var callback = function(event) {
{'fraction_non_alphanumeric': 0.1291166409551278, 'fraction_numerical': 0.007109799449996647, 'mean_word_length': 3.0373679935012183, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4689582', 'n_tokens_mistral': 4719, 'n_tokens_neox': 4495, 'n_words': 1120}