Commit 300549e0 authored by jhoogenboom's avatar jhoogenboom
Browse files

Introducing Samplevis

* New visualisation Samplevis visualises sample data files.
  (Note: visualisations are currently stored in the package, but
  are not available via FDSTools commands yet. A new tool is going
  to be introduced later, which will copy the visualisation files
  to a user-selected folder.)
* Including the current versions of Vega and D3 for completeness.
* Fixed missing numpy dependency in setup.py.
* Clarified some option help texts in Allelefinder based on
  feedback by Rick and Kris.
parent 6207d485
......@@ -5,7 +5,7 @@ contaminations.
In each sample, the sequences with the highest read counts of each
marker are called alleles, with a user-defined maximum number of alleles
par marker. The allele balance is kept within given bounds. If the
per marker. The allele balance is kept within given bounds. If the
highest non-allelic sequence exceeds a given limit, no alleles are
called for this marker. If this happens for multiple markers in one
sample, no alleles are called for this sample at all.
......@@ -156,16 +156,17 @@ def add_arguments(parser):
filtergroup.add_argument('-m', '--min-allele-pct', metavar="PCT",
type=float, default=_DEF_MIN_ALLELE_PCT,
help="call heterozygous if the second allele is at least this "
"percentage of the highest allele (default: %(default)s)")
"percentage of the highest allele of a marker "
"(default: %(default)s)")
filtergroup.add_argument('-M', '--max-noise-pct', metavar="PCT",
type=float, default=_DEF_MAX_NOISE_PCT,
help="a sample is considered contaminated/unsuitable for a marker if "
"the highest non-allelic sequence is at least this percentage of "
"the highest allele (default: %(default)s)")
"the highest allele of that marker (default: %(default)s)")
filtergroup.add_argument('-n', '--min-reads', metavar="N",
type=pos_int_arg, default=_DEF_MIN_READS,
help="require at least this number of reads for the highest allele "
"(default: %(default)s)")
"of each marker (default: %(default)s)")
filtergroup.add_argument('-a', '--max-alleles', metavar="N",
type=pos_int_arg, default=_DEF_MAX_ALLELES,
help="allow no more than this number of alleles per marker (default: "
......
This diff is collapsed.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Sample Visualisation</title/>
<!-- BEGIN_EXTERNAL_SCRIPTS -->
<script src="http://vega.github.io/vega-editor/vendor/d3.min.js"></script>
<script src="http://vega.github.io/vega/vega.min.js"></script>
<script type="text/javascript">
var graph_spec = false;
vg.util.load({url: "samplevis.json"}, function(err, result){
graph_spec = JSON.parse(result);
})
</script>
<!-- END_EXTERNAL_SCRIPTS -->
<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;
}
div.view {
position: absolute;
overflow: auto;
bottom: 0px;
top: 0px;
padding-top: 150px;
left: 0px;
right: 0px;
text-align: right;
}
</style>
</head>
<body>
<div class="options">
<strong>Options</strong><br>
Open sample data file: <input id="fileselect" type="file"> (or drag a file onto this page)<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 id="vis" class="view"></div>
</body>
<script type="text/javascript">
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]["name"] == "xpct"){
graph_spec["marks"][i]["scales"][j]["type"] = value;
}
if(graph)
parse();
return;
}
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)
return;
var reader = new FileReader();
reader.onload = function(theFile){
graph_spec["data"][0]["values"] = reader.result;
parse();
};
reader.readAsText(fileList[0]);
}
//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);
//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);
//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;
}
//Apply current values to graph_spec.
if(graph_spec){
if(document.getElementById("scaleLinear").checked)
setScale(document.getElementById("scaleLinear").value);
else
setScale(document.getElementById("scaleLog").value);
}
</script>
</html>
{
"width": 600,
"height": 10,
"data": [
{
"name": "table",
"values": "sample_data_file_contents_here",
"format": {
"type": "tsv",
"parse": {
"forward": "number",
"total": "number",
"total_noise": "number",
"total_add": "number"
}
},
"transform": [
{
"type": "formula",
"field": "total_corr",
"expr": "datum.total_noise? datum.total-datum.total_noise : datum.total"
},
{
"type": "formula",
"field": "total_add",
"expr": "datum.total_add? datum.total_corr+datum.total_add : datum.total_corr"
},
{
"type": "filter",
"test": "max(datum.total, datum.total_add) > 15"
},
{
"type": "formula",
"field": "shared",
"expr": "max(0, datum.total_corr)"
},
{
"type": "formula",
"field": "corr_shared",
"expr": "min(datum.total, datum.total_add)"
},
{
"type": "formula",
"field": "corr_decreased",
"expr": "max(datum.total, datum.corr_shared)"
},
{
"type": "formula",
"field": "corr_increased",
"expr": "max(datum.corr_shared, datum.total_add)"
},
{
"type": "formula",
"field": "forwardpct",
"expr": "100.0 / datum.total * datum.forward"
},
{
"type": "sort",
"by": ["name", "allele", "-total_add", "-total_corr", "-total"]
}
]
},
{
"name": "markercounts",
"source": "table",
"transform": [
{
"type": "aggregate",
"groupby": ["name"],
"summarize": {"*": "count"}
}
]
},
{
"name": "markerpadding",
"source": "markercounts",
"transform": [
{
"type": "cross",
"with": "markercounts"
},
{
"type": "filter",
"test": "datum.b.name < datum.a.name"
},
{
"type": "aggregate",
"groupby": ["a.name"],
"summarize": [{"field": "*", "ops": ["count"], "as": ["cumulpadding"]}]
},
{
"type": "formula",
"field": "name",
"expr": "datum['a.name']"
}
]
},
{
"name": "markeroffsets",
"source": "markercounts",
"transform": [
{
"type": "cross",
"with": "table"
},
{
"type": "filter",
"test": "datum.b.name < datum.a.name"
},
{
"type": "aggregate",
"groupby": ["a.name"],
"summarize": [{"field": "*", "ops": ["count"], "as": ["cumulcount"]}]
},
{
"type": "formula",
"field": "name",
"expr": "datum['a.name']"
}
]
},
{
"name": "yscale",
"source": "markercounts",
"transform": [
{
"type": "zip",
"with": "markerpadding",
"as": "paddingobj",
"key": "name",
"withKey": "name",
"default": {"cumulpadding": 0}
},
{
"type": "zip",
"with": "markeroffsets",
"as": "offsetobj",
"key": "name",
"withKey": "name",
"default": {"cumulcount": 0}
},
{
"type": "formula",
"field": "barheight",
"expr": "15"
},
{
"type": "formula",
"field": "markeroffset",
"expr": "70"
},
{
"type": "formula",
"field": "offset",
"expr": "datum.barheight*datum.offsetobj.cumulcount + datum.markeroffset*datum.paddingobj.cumulpadding"
},
{
"type": "formula",
"field": "end",
"expr": "datum.offset + datum.barheight*datum.count"
}
]
}
],
"scales": [
{
"name": "c",
"type": "ordinal",
"range": ["#5e3c99", "#b2abd2", "#fdb863", "#e66101"],
"domain": ["Shared base", "Correction removed", "Correction shared", "Correction added"]
}
],
"marks": [
{
"type": "text",
"from": {
"data": "yscale"
},
"properties": {
"enter": {
"x": {"field": {"group": "width"}, "mult": 0.5},
"y": {"field": "offset"},
"fontWeight": {"value": "bold"},
"text": {"field": "name"},
"align": {"value": "center"},
"baseline": {"value": "bottom"},
"fill": {"value": "black"}
}
}
},
{
"type": "group",
"from": {
"data": "table",
"transform": [
{
"type": "facet",
"groupby": ["name"]
},
{
"type": "zip",
"with": "yscale",
"as": "markerscale",
"key": "name",
"withKey": "name"
}
]
},
"properties": {
"enter": {
"x": {"value": 0},
"width": {"field": {"group": "width"}},
"y": {"field": "markerscale.offset"},
"y2": {"field": "markerscale.end"},
"stroke": {"value": "#dddddd"}
}
},
"scales": [
{
"name": "x",
"range": "width",
"domain": {"field": ["total", "total_corr", "total_add"]}
},
{
"name": "y",
"type": "ordinal",
"range": "height",
"domain": {"field": "allele"}
}
],
"axes": [
{
"type": "x",
"scale": "x",
"grid": true,
"layer": "back",
"title": "Number of reads",
"properties": {
"labels": {
"align": {"value": "right"},
"baseline": {"value": "middle"},
"dy": {"value": 3},
"angle": {"value": -25}
},
"title": {
"dy": {"value": 5}
}
}
},
{
"type": "y",
"scale": "y"
}
],
"legends": [
{
"fill": "c",
"properties": {
"symbols": {
"size": {"value": 100},
"stroke": {"value": "transparent"},
"fillOpacity": {"value": 0.8}
}
}
}
],
"marks": [
{
"type": "rect",
"properties": {
"enter": {
"x": {"scale": "x", "value": 0},
"x2": {"scale": "x", "field": "shared"},
"y": {"scale": "y", "field": "allele", "offset": 1},
"height": {"scale": "y", "band": true, "offset": -2},
"fill": {"scale": "c", "value": "Shared base"},
"fillOpacity": {"value": 0.8}
}
}
},
{
"type": "rect",
"properties": {
"enter": {
"x": {"scale": "x", "field": "corr_shared"},
"x2": {"scale": "x", "field": "corr_decreased"},
"y": {"scale": "y", "field": "allele", "offset": 1},
"height": {"scale": "y", "band": true, "offset": -2},
"fill": {"scale": "c", "value": "Correction removed"},
"fillOpacity": {"value": 0.8}
}
}
},
{
"type": "rect",
"properties": {
"enter": {
"x": {"scale": "x", "field": "total_corr"},
"x2": {"scale": "x", "field": "corr_shared"},
"y": {"scale": "y", "field": "allele", "offset": 1},
"height": {"scale": "y", "band": true, "offset": -2},
"fill": {"scale": "c", "value": "Correction shared"},
"fillOpacity": {"value": 0.8}
}
}
},
{
"type": "rect",
"properties": {
"enter": {
"x": {"scale": "x", "field": "corr_shared"},
"x2": {"scale": "x", "field": "corr_increased"},
"y": {"scale": "y", "field": "allele", "offset": 1},
"height": {"scale": "y", "band": true, "offset": -2},
"fill": {"scale": "c", "value": "Correction added"},
"fillOpacity": {"value": 0.8}
}
}
},
{
"type": "group",
"from": {
"transform": [{"type": "facet", "groupby": ["allele"]}]
},
"properties": {
"enter": {
"x": {"value": 0},
"width": {"field": {"group": "width"}},
"y": {"scale": "y", "field": "key", "offset": 1},
"height": {"scale": "y", "band": true, "offset": -2}
}
},
"scales": [
{
"name": "balance",
"range": "height",
"nice": false,
"domain": [0, 100]
}
],
"marks": [
{
"type": "rect",
"properties": {
"enter": {
"x": {"scale": "x", "value": 0},
"x2": {"scale": "x", "field": "total"},
"y": {"scale": "balance", "field": "forwardpct", "offset": -0.5},
"y2": {"scale": "balance", "field": "forwardpct", "offset": 0.5},
"fill": {"value": "black"}
}
}
}
]
}
]
}
]
}
This source diff could not be displayed because it is too large. You can view the blob instead.
from setuptools import setup, find_packages
requires = []
requires = ["numpy"]
# Python 2.6 does not include the argparse module.
try:
......@@ -21,6 +21,9 @@ import fdstools as distmeta
x = setup(
name="fdstools",
packages=find_packages(),
package_data={
"fdstools": ["vis/*", "vis/*/*"]
},
version=distmeta.__version__,
install_requires=requires,
description="Forensic DNA Sequencing Tools",
......
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