Commit d96335b0 authored by jhoogenboom's avatar jhoogenboom
Browse files

Adding premature version of Allelevis

Will complete this when updating to Vega 2.2.5 or newer, which
contains a new feature that I contributed specifically for this.
parent 4eee1a33
{
"width": 500,
"height": 500,
"data": [
{
"name": "raw",
"values": "VALUES HERE",
"format": {
"type": "tsv"
},
"transform": [
{
"type": "formula",
"field": "samplemarker",
"expr": "datum.sample + datum.marker"
},
{
"type": "formula",
"field": "markerallele",
"expr": "datum.marker + datum.allele"
},
{
"type": "formula",
"field": "samplemarkerallele",
"expr": "datum.samplemarker + datum.allele"
}
]
},
{
"name": "homozygotes",
"source": "raw",
"transform": [
{
"type": "aggregate",
"groupby": ["samplemarker"],
"summarize": {"allele": "distinct"}
},
{
"type": "filter",
"test": "datum.distinct_allele == 1"
},
{
"type": "lookup",
"on": "raw",
"onKey": "samplemarker",
"keys": ["samplemarker"],
"as": ["alleleobj"]
},
{
"type": "formula",
"field": "markerallele",
"expr": "datum.alleleobj.markerallele"
},
{
"type": "aggregate",
"groupby": ["markerallele"],
"summarize": {"*": "count"}
}
]
},
{
"name": "nodes",
"source": "raw",
"transform": [
{
"type": "aggregate",
"groupby": ["marker", "allele"],
"summarize": {"*": "count"}
},
{
"type": "formula",
"field": "markerallele",
"expr": "datum.marker + datum.allele"
},
{
"type": "lookup",
"on": "homozygotes",
"onKey": "markerallele",
"keys": ["markerallele"],
"as": ["homcountobj"],
"default": {"count": 0}
},
{
"type": "formula",
"field": "homCount",
"expr": "datum.homcountobj.count"
}
]
},
{
"name": "edges",
"source": "nodes",
"transform": [
{
"type": "cross",
"with": "raw",
"output": {"left": "source", "right": "samples"}
},
{
"type": "filter",
"test": "datum.source.markerallele == datum.samples.markerallele"
},
{
"type": "cross",
"with": "nodes",
"output": {"left": "a", "right": "target"}
},
{
"type": "filter",
"test": "datum.a.source.marker == datum.target.marker && datum.a.source.allele < datum.target.allele"
},
{
"type": "formula",
"field": "samplemarkerallele",
"expr": "datum.a.samples.sample + datum.target.marker + datum.target.allele"
},
{
"type": "lookup",
"on": "raw",
"onKey": "samplemarkerallele",
"keys": ["samplemarkerallele"],
"as": ["targetsample"],
"default": {"sample": "NOTFOUND"}
},
{
"type": "filter",
"test": "datum.targetsample.sample != 'NOTFOUND'"
},
{
"type": "formula",
"field": "source",
"expr": "datum.a.source._id"
},
{
"type": "formula",
"field": "target",
"expr": "datum.target._id"
},
{
"type": "formula",
"field": "sampletag",
"expr": "datum.targetsample.sample"
},
{
"type": "aggregate",
"groupby": ["source", "target"],
"summarize": {"*": "count"}
}
]
}
]
}
{
"width": 500,
"height": 500,
"data": [
{
"name": "raw",
"values": "VALUES HERE",
"format": {
"type": "tsv"
},
"transform": [
{
"type": "aggregate",
"groupby": ["marker", "allele"],
"summarize": {"*": "count"}
}
]
},
{
"name": "edges",
"values": "EDGES_VALUES_HERE",
"format": {
"type": "tsv"
}
},
{
"name": "nodes",
"values": "NODES_VALUES_HERE",
"format": {
"type": "tsv"
},
"transform": [
{
"type": "formula",
"field": "charge",
"expr":
"-20*pow(0.05*d.data.count, 1/2)"
},
{
"type": "force",
"links": "edges",
"linkDistance": 30,
"linkStrength": 0.1,
"charge": "charge",
"iterations": 1000
}
]
}
],
"scales": [
{
"name": "c",
"type": "ordinal",
"range": "category20"
},
{
"name": "legend_sizes",
"type": "ordinal",
"range": [1, 5, 10, 20, 50]
}
],
"legends": [
{
"fill": "c",
"stroke": "c",
"properties": {
"symbols": {
"size": {"value": 75}
}
}
},
{
"size": "legend_sizes",
"values": [1, 5, 10, 20, 50]
}
],
"marks": [
{
"type": "path",
"from": {
"data": "edges",
"transform": [
{
"type": "sort",
"by": "source.data.marker"
},
{
"type": "link",
"shape": "line"
}
]
},
"properties": {
"update": {
"path": {"field": "path"},
"stroke": {"scale": "c", "field": "source.data.marker"},
"strokeWidth": {"field": "data.count", "mult": 0.5},
"strokeOpacity": {"value": 0.3}
}
}
},
{
"type": "symbol",
"from": {
"data": "nodes"
},
"properties": {
"enter": {
"size": {"field": "data.count"}
},
"update": {
"x": {"field": "x"},
"y": {"field": "y"},
"fill": {"scale": "c", "field": "data.marker"},
"stroke": {"scale": "c", "field": "data.marker"}
}
}
},
{
"type": "symbol",
"from": {
"data": "nodes"
},
"properties": {
"enter": {
"size": {"field": "data.homCount"}
},
"update": {
"y": {"field": "y"},
"y": {"field": "y"},
"fill": {"value": "black"},
"stroke": {"value": "black"}
}
}
}
]
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Allele Visualisation - FDSTools</title/>
<!-- BEGIN_LIBRARIES -->
<script src="http://vega.github.io/vega-editor/vendor/d3.min.js"></script>
<script src="http://vega.github.io/vega/vega.min.js"></script>
<!-- END_LIBRARIES -->
<style>
* {
font-family: Helvetica Neue, Helvetica, Arial, sans-serif;
}
body {
margin: 0px
}
div.options {
position: absolute;
margin: 5px;
background-color: rgba(128, 128, 255, 0.5);
z-index: 10;
}
#optionsheader{
cursor: pointer;
}
#optionsheader:hover{
border-bottom: 1px dashed black;
}
div#vis {
position: absolute;
overflow: auto;
bottom: 0px;
top: 0px;
right: 0px;
left: 0px;
text-align: right;
}
</style>
</head>
<body>
<div class="options">
<strong id="optionsheader">Options</strong><br>
<div id="options">
<span id="fileselectspan" style="display: none">
Open sample data file (or drag a file onto this page): <input id="fileselect" type="file"><br>
</span>
Display options: graph width <input type="text" value="600" id="graphwidth" size="3">px;
bar width <input type="text" value="15" id="barwidth" size="2">px;
marker spacing <input type="text" value="70" id="subgraphoffset" size="3">px<br>
Filtering: require at least <input type="text" value="15" id="minN" size="3"> reads and at least <input type="text" value="0.5" id="minP" size="3">% of highest allele per marker<br>
Filtering: marker <input type="text" id="markerFilter" size="10" title="Supports regular expression syntax: e.g., use '.*' to match anything."><br>
Axis scale: <input type="radio" name="scale" value="linear" id="scaleLinear" checked> Linear
<input type="radio" name="scale" value="sqrt" id="scaleLog"> Square root<br>
Render as: <input type="radio" name="renderer" value="canvas" id="renderCanvas"> Canvas
<input type="radio" name="renderer" value="svg" id="renderSVG" checked> SVG<br>
<a id="saveLink" href="javascript:void(saveImage())" style="display: none">Save image</a>
</div>
</div>
<div id="vis"></div>
<script type="text/javascript">
var graph = false;
function parse(){
vg.parse.spec(graph_spec, function(chart){
var rendererName = "canvas";
if(document.getElementById("renderSVG").checked)
rendererName="svg";
graph = chart({el: "#vis", renderer: rendererName});
graph.update();
document.getElementById("saveLink").style.display = "inline";
//Scroll to the right; the graph is more interesting than the long labels.
var visdiv = document.getElementById("vis");
visdiv.scrollLeft = visdiv.scrollWidth;
});
}
function setScale(value){
if(!graph_spec)
return;
for(i in graph_spec["marks"])
if(graph_spec["marks"][i]["scales"])
for(j in graph_spec["marks"][i]["scales"])
if(graph_spec["marks"][i]["scales"][j]["name"] == "x")
graph_spec["marks"][i]["scales"][j]["type"] = value;
if(graph)
parse();
}
function setDataFormulaTransformValue(dataname, fieldname, value){
if(!graph_spec)
return false;
for(i in graph_spec["data"]){
if(graph_spec["data"][i]["name"] == dataname){
for(j in graph_spec["data"][i]["transform"]){
if(graph_spec["data"][i]["transform"][j]["type"] == "formula" && graph_spec["data"][i]["transform"][j]["field"] == fieldname){
graph_spec["data"][i]["transform"][j]["expr"] = "" + value;
return true;
}
}
}
}
return false;
}
function getDataFormulaTransformValue(dataname, fieldname){
if(!graph_spec)
return false;
for(i in graph_spec["data"]){
if(graph_spec["data"][i]["name"] == dataname){
for(j in graph_spec["data"][i]["transform"]){
if(graph_spec["data"][i]["transform"][j]["type"] == "formula" && graph_spec["data"][i]["transform"][j]["field"] == fieldname){
return graph_spec["data"][i]["transform"][j]["expr"];
}
}
}
}
return false;
}
function setRenderer(value){
if(graph)
graph.renderer(value);
}
//Load the data (input is a fileList object; only the first file is loaded).
function loadDataset(fileList){
if(!graph_spec || !fileList || !fileList.length)
return;
var reader = new FileReader();
reader.onload = function(theFile){
graph_spec["data"][0]["values"] = reader.result;
parse();
};
reader.readAsText(fileList[0]);
}
//Save image function.
function saveImage(){
var link = document.getElementById("saveLink");
if(document.getElementById("renderSVG").checked){
var svg = document.querySelector("svg.marks");
svg.setAttribute("xmlns", "http://www.w3.org/2000/svg"); //Vega does not set this for us
link.setAttribute("href", "data:image/svg+xml," + encodeURIComponent(svg.outerHTML));
link.setAttribute("download", "graph.svg");
}
else{
link.setAttribute("href", document.getElementsByClassName('marks')[0].toDataURL());
link.setAttribute("download", "graph.png");
}
link.click();
link.setAttribute("href", "javascript:void(saveImage())");
return false;
}
function onLoadSpec(has_data){
if(!has_data){
//Allow files to be dragged onto the page.
document.addEventListener('dragover', function(evt){
evt.stopPropagation();
evt.preventDefault();
}, false);
document.addEventListener('drop', function(evt){
evt.stopPropagation();
evt.preventDefault();
loadDataset(evt.dataTransfer.files);
}, false);
//Handle files from the file input.
document.getElementById("fileselect").addEventListener('change', function(){
loadDataset(document.getElementById("fileselect").files);
}, false);
document.getElementById("fileselectspan").style.display = "inline";
}
//Update graph when rendering mode or axis scale is changed.
document.getElementById("renderCanvas").addEventListener('change', function(){
setRenderer(this.value);
}, false);
document.getElementById("renderSVG").addEventListener('change', function(){
setRenderer(this.value);
}, false);
/*
document.getElementById("scaleLinear").addEventListener('change', function(){
setScale(this.value);
}, false);
document.getElementById("scaleLog").addEventListener('change', function(){
setScale(this.value);
}, false);
document.getElementById("graphwidth").addEventListener('change', function(){
var value = parseFloat(this.value);
if(isNaN(value))
return;
graph_spec["width"] = value;
if(graph)
parse();
}, false);
document.getElementById("barwidth").addEventListener('change', function(){
var value = parseFloat(this.value);
if(isNaN(value))
return;
if(setDataFormulaTransformValue("yscale", "barwidth", value) && graph)
parse();
}, false);
document.getElementById("subgraphoffset").addEventListener('change', function(){
var value = parseFloat(this.value);
if(isNaN(value))
return;
if(setDataFormulaTransformValue("yscale", "subgraphoffset", value) && graph)
parse();
}, false);
document.getElementById("minN").addEventListener('change', function(){
var value = parseFloat(this.value);
if(isNaN(value))
return;
if(setDataFormulaTransformValue("table", "amplitude_threshold", value) && graph)
parse();
}, false);
document.getElementById("minP").addEventListener('change', function(){
var value = parseFloat(this.value);
if(isNaN(value))
return;
if(setDataFormulaTransformValue("table", "amplitude_pct_threshold", value) && graph)
parse();
}, false);
document.getElementById("markerFilter").addEventListener('change', function(){
if(setDataFormulaTransformValue("table", "filter_marker", "'" + this.value + "'") && graph)
parse();
}, false);
*/
//Toggle options visibility.
document.getElementById("optionsheader").addEventListener('click', function(){
var opts = document.getElementById("options");
if(opts.style.display == "none")
document.getElementById("options").style.display = "block";
else
document.getElementById("options").style.display = "none";
}, false);
//Sync graph_spec and display.
/*
if(document.getElementById("scaleLinear").checked)
setScale(document.getElementById("scaleLinear").value);
else
setScale(document.getElementById("scaleLog").value);
document.getElementById("markerFilter").value = getDataFormulaTransformValue("table", "filter_marker").replace(/^(['"]?)(.*(?=\1$))\1$/, '$2');
document.getElementById("graphwidth").value = graph_spec["width"];
document.getElementById("barwidth").value = getDataFormulaTransformValue("yscale", "barwidth");
document.getElementById("subgraphoffset").value = getDataFormulaTransformValue("yscale", "subgraphoffset");
document.getElementById("minN").value = getDataFormulaTransformValue("table", "amplitude_threshold");
document.getElementById("minP").value = getDataFormulaTransformValue("table", "amplitude_pct_threshold");
*/
if(has_data){
document.getElementById("options").style.display = "none";
parse();
}
}
</script>
<!-- BEGIN_LOAD_SCRIPT -->
<script type="text/javascript">
var graph_spec = false;
vg.util.load({url: "allelevis.json"}, function(err, result){
graph_spec = JSON.parse(result);
onLoadSpec(false);
});
</script>
<!-- END_LOAD_SCRIPT -->
</body>
</html>
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment