Commit de3593a8 authored by Hoogenboom, Jerry's avatar Hoogenboom, Jerry
Browse files

FDSTools v1.0.0 Release Candidate 1

* General changes in v1.0.0rc1:
  * Fixed bug that caused variant descriptions in allele names of
    non-STR markers to be prepended with plus signs similar to suffix variants
    in STR markers.  When attempting to convert these allele names back to raw
    sequences, FDSTools would crash with an 'Invalid allele name' error.
* Allelevis v2.0.1 (additionally):
  * In the tooltip in HTML visualisations, a line break may now only be
    inserted in allele names after an underscore character (_) or after a
    repeat block in STR allele names.  If the input file contains raw
    sequences, line breaks may now be introduced anywhere in the sequence.
* Samplevis v2.1.1:
  * Added tooltip support to HTML visualisations.  Moving the mouse pointer
    over one of the alleles in the graph now displays a tooltip giving
    per-strand read counts of that allele.  The tooltip may include a
    'new allele' note if the input sample was analysed with FindNewAlleles.
  * The allele tables in HTML visualisations will now grow much wider than
    before if the screen (or window) is very narrow.
  * In the tables in HTML visualisations, a line break may now only be inserted
    in allele names after an underscore character (_) or after a repeat block
    in STR allele names.  If the input file contains raw sequences, line breaks
    may now be introduced anywhere in the sequence.
  * Improved determination of column widths of the allele tables when printing
    an HTML visualisation.
  * When printing an HTML visualisation, the graph and the corresponding table
    of a marker will be kept on the same page in all browsers now.
  * Fixed glitch that caused 'Infinity%' or 'NaN%' to be written in some cells
    in the allele tables in HTML visualisations for sequences that had zero
    reads (before or after correction).  These cells will remain empty now.
* Pipeline v1.0.1 (additionally):
  * The Pipeline tool will now only write the command lines of the tools it
    runs if the -d/--debug option was specified.
* Library v1.0.1 (additionally):
  * Added proper examples for non-STR markers and aliases.
* Stuttermodel v1.1.1:
  * Minor change to internal variant representation.
parent 70a3ea3b
......@@ -29,6 +29,22 @@ Alternatively, FDSTools can be installed by running:
FDSTools Changelog
------------------
v1.0.0rc1
- Fixed bug that caused variant descriptions in allele names of non-STR
markers to be prepended with plus signs similar to suffix variants
in STR markers; when attempting to convert these allele names back to raw
sequences, FDSTools would crash with an 'Invalid allele name' error
- Tools that take a list of files as their argument (through the -i option
or as positionals) now explicitly support '*' and '?' wildcards
- Includes BGEstimate v1.1.1
- Includes BGMerge v1.0.2
- Includes Library v1.0.1
- Includes Pipeline v1.0.1
- Includes Stuttermodel v1.1.1
- Includes Allelevis v2.0.1
- Includes Samplevis v2.1.1
- Includes Stuttermodelvis v2.0.1
v0.0.5
- The Blame tool was removed in favour of BGAnalyse
- Includes BGAnalyse v1.0.0
......@@ -42,7 +58,7 @@ v0.0.5
- Includes BGAnalysevis v1.0.0
- Includes BGRawvis v2.0.0
- Includes Profilevis v2.0.0
- Includes Samplevis v1.1.0
- Includes Samplevis v2.1.0
- Includes Stuttermodelvis v2.0.0
v0.0.4
......@@ -129,6 +145,11 @@ v1.0.0
BGEstimate
~~~~~~~~~~
v1.1.1
- Added option -p/--profiles which can be used to provide a previously
created background noise profiles file, from which starting values will
be read instead of assuming zero noise
v1.1.0
- Added a new option -g/--min-genotypes (default: 3). Only alleles that
occur in at least this number of unique heterozygous genotypes will be
......@@ -159,6 +180,9 @@ v1.0.0
BGMerge
~~~~~~~
v1.0.2
- Minor changes to facilitate explicit filename wildcard support
v1.0.1
- Reduced memory usage
......@@ -211,12 +235,22 @@ v1.0.0
Library
~~~~~~~
v1.0.1
- Updated some of the comments describing the sections
- Added proper examples for non-STR markers and aliases
v1.0.0
- Initial version
Pipeline
~~~~~~~~
v1.0.1
- Removed checking of the existence of the files specified for the
-S/--in-samples option; instead, this is left to the downstream tools to
find out, consistent with how this works with other input file options
- Only output the running commands if the -d/--debug option was specified
v1.0.0
- Initial version
......@@ -294,6 +328,9 @@ v1.0.0
Stuttermodel
~~~~~~~~~~~~
v1.1.1
- Minor change to internal variant representation
v1.1.0
- Stuttermodel will now only output a fit for one strand if it could also
obtain a fit for the other strand (for the same marker, unit, and stutter
......@@ -343,6 +380,9 @@ v1.0.0
Allelevis
~~~~~~~~~
v2.0.1
- Added tooltip support to HTML visualisations
v2.0.0
- Replaced the simple Options overlay with responsive design options panels
in HTML visualisations
......@@ -414,6 +454,20 @@ v1.0.0
Samplevis
~~~~~~~~~
v2.1.1
- Added tooltip support to HTML visualisations
- The tooltip may include a 'new allele' note if the input sample was
analysed with FindNewAlleles
- The allele tables in HTML visualisations will now grow much wider than
before if the screen (or window) is very narrow
- Improved line breaking behaviour in the tables in HTML visualisations
- Improved determination of column widths of the allele tables when
printing an HTML visualisation
- When printing an HTML visualisation, the graph and the corresponding
table of a marker will be kept on the same page in all browsers now
- Fixed glitch that caused 'Infinity%' or 'NaN%' to be written in some
cells in the allele tables in HTML visualisations
v2.1.0
- Changed default minimum number of reads for graph filtering from 15 to 5
- Changed default table filtering options:
......@@ -444,6 +498,9 @@ v2.0.0
Stuttermodelvis
~~~~~~~~~~~~~~~
v2.0.1
- Changed the unit in the horizontal axis title from 'bp' to 'nt'
v2.0.0
- Replaced the simple Options overlay with responsive design options panels
in HTML visualisations
......
......@@ -24,7 +24,7 @@ including tools for characterisation and filtering of PCR stutter artefacts and
other systemic noise, and for automatic detection of the alleles in a sample.
"""
__version_info__ = ('0', '0', '6', 'dev1')
__version_info__ = ('1', '0', '0', 'rc1')
__version__ = '.'.join(__version_info__)
usage = __doc__.split("\n\n\n")
......
......@@ -132,27 +132,27 @@ def get_genome_pos(location, x, invert=False):
#get_genome_pos
def call_variants(template, sequence, location="suffix", cache=True,
def call_variants(template, sequence, location=("?", 1), cache=True,
debug=False):
"""
Perform a global alignment of sequence to template and return a
list of variants detected. The format (nomenclature) of the
returned variants depends on the location argument.
If location is "suffix" (the default), all variants are given as
substitutions in the form posX>Y, where the first base in the
template is pos=1. With location set to "prefix", bases are counted
from right to left instead. Insertions and deletions are written as
pos.1->Y and posX>-, respectively.
If location is a tuple ("chromosome name", position), with any
integer for the position, all variants are given as substitutions in
the form posX>Y. Insertions and deletions are written as pos.1->Y
and posX>-, respectively. The given position is that of the first
base in the template. With the location set to "suffix", a plus
sign is prepended to position numbers and the first base in the
template is pos=1. With location set to "prefix", a minus sign is
prepended and bases are counted from right to left instead.
If location is a tuple ("M", position) with any integer for the
position, variants are written following the mtDNA nomenclature
guidelines. The given position is that of the first base in the
template.
If location is a tuple ("chromosome name", position), a
NotImplementedError is raised.
By default, the results of this function are cached. Set cache to
False to suppress caching the result and reduce memory usage.
......@@ -1131,7 +1131,7 @@ def convert_sequence_raw_allelename(seq, library, marker):
return "REF"
return " ".join(
call_variants(library["nostr_reference"][marker], blocks[0][0],
library["genome_position"].get(marker, "suffix")))
library["genome_position"].get(marker, ("?", 1))))
# Find prefix and suffix.
prefix = suffix = this_prefix = this_suffix = ""
......
......@@ -70,7 +70,6 @@ def make_empty_library_ini(type, aliases=False):
ini = RawConfigParser(allow_no_value=True)
ini.optionxform = str
ini.add_comment = MethodType(ini_add_comment, ini)
# TODO: Add good examples for aliases and non-STR markers
# Create sections and add comments to explain how to use them.
if aliases:
......@@ -86,17 +85,26 @@ def make_empty_library_ini(type, aliases=False):
" You cannot specify a repeat structure for an alias."
if type != "non-str" else ""))
ini.set("aliases",
";MyAlias = MyMarker, AGCTAGC, MySpecialAlleleName")#TODO
";AmelX = Amel, TCAGCTATGAGGTAATTTTTCTCTTTACTAATTTTGACCATTGTTTGCGT"
"TAACAATGCCCTGGGCTCTGTAAAGAATAGTGTGTTGATTCTTTATCCCAGATGTTTCTCAAGTG"
"GTCCTGATTTTACAGTTCCTACCACCAGCTTCCCA, X")
ini.set("aliases",
";AmelY = Amel, TCAGCTATGAGGTAATTTTTCTCTTTACTAATTTTGATCACTGTTTGCAT"
"TAGCAGTCCCCTGGGCTCTGTAAAGAATAGTGGGTGGATTCTTCATCCCAAATAAAGTGGTTTCT"
"CAAGTGGTCCCAATTTTACAGTTCCTACCATCAGCTTCCCA, Y")
ini.add_section("flanks")
ini.add_comment("flanks",
"The flanking sequences (e.g., primer sequences) of each marker. "
"Specify two comma-separated values: left flank and right flank, "
"in the same sequence orientation (strand).")
ini.set("flanks",
";MyMarker = CTGTTTCTGAGTTTCAAGTATGTCTG, TTACATGCTCGTGCACCTTATGGAGG"
if type == "non-str" else
";CSF1P0 = CCTGTGTCAGACCCTGTT, GTTGGAACACTGCCCTGG")
if type == "str" or type == "full":
if type != "non-str":
ini.set("flanks", ";CSF1P0 = CCTGTGTCAGACCCTGTT, GTTGGAACACTGCCCTGG")
if type != "str":
ini.set("flanks",
";MitoFrag = ATTATTTATCGCACCTACGT, TGGCGGTATGCACTTTTAACAG")
if aliases:
ini.set("flanks", ";Amel = ACCCTGGTTATATCAACT, GTTTAAGCTCTGATGGTT")
if type != "non-str":
ini.add_section("prefix")
ini.add_comment("prefix",
"Specify all known prefix sequences of each STR marker, "
......@@ -127,13 +135,20 @@ def make_empty_library_ini(type, aliases=False):
"and maximum number of repeats.")
ini.set("repeat",
";CSF1P0 = CTAT 0 19 CTAC 0 1 TTAT 0 1 CAT 0 1 CTAT 0 19")
if type == "non-str" or type == "full":
if aliases or type != "str":
ini.add_section("no_repeat")
ini.add_comment("no_repeat",
"Specify the reference sequence for each non-STR marker.")
ini.set("no_repeat",
";MySNPMarker = TTTTAACACAAAAAATTTAAAATAAGAAGAATAAATAGTGCTTGCTT")#TODO
ini.set("no_repeat", ";MyMtMarker = AACCCCCCCT")#TODO
if type != "str":
ini.set("no_repeat", ";MitoFrag = TCAATATTACAGGCGAACATACTTACTAAAGT"
"GTGTTAATTAATTAATGCTTGTAGGACATAATAATAACAATTGAATGTCTGCACAGCCACTTTCC"
"ACACAGACATCATAACAAAAAATTTCCACCAAACCCCCCCTCCCCCGCTTCTGGCCACAGCACTT"
"AAACACATCTCTGCCAAACCCCAAAAACAAAGAACCCTAACACCAGCCTAACCAGATTTCAAATT"
"TTATCTTT")
if aliases:
ini.set("no_repeat", ";Amel = TCAGCTATGAGGTAATTTTTCTCTTTACTAATTTTG"
"ACCATTGTTTGCGTTAACAATGCCCTGGGCTCTGTAAAGAATAGTGTGTTGATTCTTTATCCCAG"
"ATGTTTCTCAAGTGGTCCTGATTTTACAGTTCCTACCACCAGCTTCCCA")
ini.add_section("genome_position")
ini.add_comment("genome_position",
"Specify the chromosome number and position of the first base after "
......@@ -148,16 +163,19 @@ def make_empty_library_ini(type, aliases=False):
"(starting position), 16569, 1, (ending position)\". This tells "
"FDSTools that the marker is a concatenation of two fragments, "
"where the first fragment ends at position 16569 and the second "
"fragment starts at position 1." if type != "str" else ""))
"fragment starts at position 1. Similarly, for a fragment that "
"spans position 3107 in the rCRS (which is nonexistent), you may "
"specify \"M, (starting position), 3106, 3108, (ending "
"position)\"." if type != "str" else ""))
ini.add_comment("genome_position",
"Using human genome build GRCh38%s." % (
" and rCRS for human mtDNA" if type != "str" else ""))
if type != "non-str":
ini.set("genome_position", ";CSF1P0 = 5, 150076311, 150076487")
if type != "str":
ini.set("genome_position", ";MyMarker = 9, 36834400")#TODO
ini.set("genome_position", ";MySNPMarker = X, 21214600")#TODO
ini.set("genome_position", ";MyMtMarker = M, 301")#TODO
ini.set("genome_position", ";MitoFrag = M, 173, 407")
if aliases:
ini.set("genome_position", ";Amel = X, 11296816, 11296965")
if type == "str" or type == "full":
ini.add_section("length_adjust")
ini.add_comment("length_adjust",
......@@ -181,9 +199,9 @@ def make_empty_library_ini(type, aliases=False):
if type != "non-str":
ini.set("max_expected_copies", ";CSF1P0 = 2")
if type != "str":
ini.set("max_expected_copies", ";MyMarker = 2")#TODO
ini.set("max_expected_copies", ";MySNPMarker = 2")#TODO
ini.set("max_expected_copies", ";MyMtMarker = 1")#TODO
ini.set("max_expected_copies", ";MitoFrag = 1")
if aliases:
ini.set("max_expected_copies", ";Amel = 2")
ini.add_section("expected_allele_length")
ini.add_comment("expected_allele_length",
"Specify one or two values for each marker. The first value gives the "
......@@ -194,6 +212,10 @@ def make_empty_library_ini(type, aliases=False):
("including prefix and suffix, " if type != "non-str" else ""))
if type != "non-str":
ini.set("expected_allele_length", ";CSF1P0 = 100")
if type != "str":
ini.set("expected_allele_length", ";MitoFrag = 150")
if aliases:
ini.set("expected_allele_length", ";Amel = 100")
return ini
#make_empty_library_ini
......
......@@ -53,7 +53,7 @@ import pkgutil, sys, os, tempfile, re, argparse
import fdstools.tools
from ..lib import split_quoted_string, DEF_TAG_EXPR, DEF_TAG_FORMAT, get_tag, \
regex_arg, INI_COMMENT, glob_path
regex_arg, INI_COMMENT, glob_path, print_db
from ConfigParser import RawConfigParser, NoSectionError, NoOptionError
......@@ -268,7 +268,7 @@ def get_argv(toolname, arg_defs, config):
arglist[0].extend(value)
else:
arglist[1].extend(value)
print(("%r" % (arglist[0]+arglist[1]))[:200])
print_db(("%r" % (arglist[0]+arglist[1]))[:200], debug)
return arglist[0] + arglist[1]
#get_argv
......@@ -886,6 +886,10 @@ def run(args):
else:
import subprocess
# Export debug flag to the global scope.
global debug
debug = args.debug
if args.config == "-":
raise ValueError("The pipeline configuration file cannot be named '-'")
if os.path.exists(args.config):
......
......@@ -37,7 +37,7 @@ from ..lib import pos_int_arg, add_input_output_args, get_input_output_files,\
add_random_subsampling_args, reverse_complement,\
get_repeat_pattern
__version__ = "1.1.0"
__version__ = "1.1.1"
# Default values for parameters are specified below.
......@@ -305,16 +305,16 @@ def fit_stutter_model(outfile, raw_outfile, data, library, seq, patterns,
# Go via variants to allow variant combinations.
# NOTE: Beware variant clashes. When looking for
# e.g., "+13AGAT>-" with allele "AGATAGACAGATAGAT",
# e.g., "13AGAT>-" with allele "AGATAGACAGATAGAT",
# to go from this allele to AGATAGATAGAT could be
# "+8C>T_+13AGAT>-" but optimal is "+8CAGA>-". It
# "8C>T_+13AGAT>-" but optimal is "8CAGA>-". It
# should be included in the analysis but it is not.
if stutter_fold > 0:
variant = "%+i.1->%s" % (
variant = "%i.1->%s" % (
end - len(flanks[0]),
full_allele[position:end])
else:
variant = "%+i%s>-" % (
variant = "%i%s>-" % (
position + 1 - len(flanks[0]),
full_allele[position:end])
for sample in data["alleles"][marker][allele]:
......
......@@ -171,6 +171,9 @@
border-radius: .5em;
padding: 0em .25em;
}
#vis-tooltip td {
vertical-align: top;
}
td.num {
text-align: right;
}
......@@ -436,6 +439,8 @@
</div>
<div id="vis-tooltip"></div>
<script type="text/javascript">
var PAT_SEQ_RAW = /^[ACGT]*$/;
var PAT_ALLELENAME_SPLIT = /[\]\)_]/g;
var graph = false;
var fileName = "alleles";
var stamp = 0;
......@@ -481,10 +486,10 @@ function parse(){
var table = document.createElement("table");
var row = table.insertRow();
row.insertCell().appendChild(document.createTextNode("Allele 1"));
row.insertCell().appendChild(document.createTextNode(a[0]));
appendChunkedAllelename(row.insertCell(), a[0]);
var row = table.insertRow();
row.insertCell().appendChild(document.createTextNode("Allele 2"));
row.insertCell().appendChild(document.createTextNode(a[1]));
appendChunkedAllelename(row.insertCell(), a[1]);
row = table.insertRow();
row.insertCell().appendChild(document.createTextNode("Samples"));
row.insertCell().appendChild(document.createTextNode(datum.count));
......@@ -494,7 +499,8 @@ function parse(){
//Node.
var b = document.createElement("b");
b.appendChild(document.createTextNode(datum.marker + " " + datum.allele));
b.appendChild(document.createTextNode(datum.marker + " "));
appendChunkedAllelename(b, datum.allele);
tt.appendChild(b);
var table = document.createElement("table");
var row = table.insertRow();
......@@ -519,6 +525,35 @@ function parse(){
});
}
function appendChunkedAllelename(parent, allele){
var span;
if(PAT_SEQ_RAW.test(allele)){
span = document.createElement("span");
span.style.display = "inline-block";
span.style.wordBreak = "break-all";
span.appendChild(document.createTextNode(allele));
parent.appendChild(span);
return;
}
var match;
var pos = 0;
while((match = PAT_ALLELENAME_SPLIT.exec(allele)) !== null){
span = document.createElement("span");
span.style.display = "inline-block";
span.style.whiteSpace = "nowrap";
span.appendChild(document.createTextNode(allele.substring(pos, match.index+1)));
parent.appendChild(span);
pos = match.index+1;
}
if(pos < allele.length){
span = document.createElement("span");
span.style.display = "inline-block";
span.style.whiteSpace = "nowrap";
span.appendChild(document.createTextNode(allele.substring(pos)));
parent.appendChild(span);
}
}
function updateViewBox(svg){
//Setting the viewBox enables shrink-to-fit behaviour when printing.
svg.setAttribute("viewBox",
......
......@@ -24,7 +24,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="UTF-8">
<title>Sample Visualisation - FDSTools</title>
<!-- VERSION 2.1.0 -->
<!-- VERSION 2.1.1 -->
<!-- BEGIN_LIBRARIES -->
<script src="https://vega.github.io/vega-editor/vendor/d3.min.js"></script>
<script src="https://vega.github.io/vega/vega.min.js"></script>
......@@ -166,14 +166,23 @@
#vis div {
direction: ltr;
}
#vis div:nth-child(2n+3) {
#vis > div:not(:first-child) {
border-top: 1px solid hsl(220, 20%, 3%);
padding-top: .8rem;
margin-top: .8rem;
}
#vis div:last-child {
#vis > div:last-child {
padding-bottom: .8rem;
}
#vis-tooltip {
display: none;
position: fixed;
z-index: 999999;
background-color: hsla(220, 20%, 77%, 0.75);
border: 1px solid hsl(220, 20%, 3%);
border-radius: .5em;
padding: 0em .25em .25em;
}
.markertable {
display: inline-table;
text-align: left;
......@@ -181,31 +190,39 @@
max-width: 55vw;
margin-right: 12rem;
}
.markertable td {
.tooltiptable {
border-collapse: collapse;
margin-top: .25em;
width: 100%;
max-width: 30em;
}
.markertable td, .tooltiptable td {
border: 1px solid hsl(220, 20%, 57%);
padding: .4rem;
font-size: 0.8em;
white-space: nowrap;
width: .1rem;
}
.markertable tr:first-child td {
.markertable tr:first-child td, .tooltiptable tr:first-child td, .tooltiptable td:first-child {
background-color: hsl(220, 20%, 77%);
font-weight: bold;
}
.markertable td:nth-child(2) {
.markertable td:nth-child(2), .tooltiptable td:first-child {
width: auto;
}
.markertable tr:first-child {
background-color: hsl(220, 20%, 77%);
}
.markertable tr:nth-child(1n+2) {
.markertable tr:nth-child(1n+2), .tooltiptable tr:nth-child(1n+2) {
background-color: hsl(220, 20%, 97%);
}
.markertable tr:nth-child(2n) {
.markertable tr:nth-child(2n), .tooltiptable tr:nth-child(2n) {
background-color: hsl(220, 20%, 90%);
}
.markertable tr.removed td:not(:last-child) {
.markertable tr.removed td:not(:last-child), .markertable tr.removed td:not(:last-child) * {
text-decoration: line-through;
}
.tooltiptable tr:first-child td:first-child {
background-color: transparent;
border: none;
}
td.num {
text-align: right;
}
......@@ -219,7 +236,6 @@
border-left: none;
padding-left: 0px;
margin-left: 0px;
width: 1em !important;
}
td.wrap {
white-space: normal !important;
......@@ -274,6 +290,9 @@
flex: 1 0 auto;
padding: .2rem 1rem .2rem .2rem;
}
.markertable {
max-width: 90vw;
}
}
@media only screen and (max-aspect-ratio: 40000/30000) and (max-height: 55em), only screen and (max-width: 60em) {
/* Portrait or near-portrait combined with very limited height, or rather narrow: collapse menu */
......@@ -375,15 +394,11 @@
#vis > div > * {
direction: ltr;
}
#vis > :nth-child(2n+0){
break-before: avoid;
page-break-before: avoid;
#vis > div {
page-break-inside: avoid;
}
#vis > :nth-child(2n+1){
break-after: avoid;
page-break-after: avoid;
page-break-inside: avoid;
#vis-tooltip {
display: none;
}
.vega, canvas {
max-width: 100%;
......@@ -404,14 +419,14 @@
box-sizing: border-box;
text-align: left;
border-collapse: collapse;
width: 100%;
min-width: 100% !important;
}
.markertable td {
border: 1pt solid #888888;
padding: 2pt;
font-size: 7pt;
white-space: nowrap;
width: 50pt;
width: 40pt;
}
.markertable tr:first-child td {
font-weight: bold;
......@@ -425,7 +440,7 @@
.markertable tr:nth-child(2n) {
background-color: #eeeeee;
}
.markertable tr.removed td:not(:last-child) {
.markertable tr.removed td:not(:last-child), .markertable tr.removed td:not(:last-child) * {
text-decoration: line-through;
}
.num {
......@@ -441,7 +456,7 @@
border-left: none;
padding-left: 0px;
margin-left: 0px;
width: 1em !important;
width: 1em !important;
}
td.wrap {
white-space: normal !important;
......@@ -628,7 +643,10 @@
Ready
</div>
</div>
<div id="vis-tooltip"></div>
<script type="text/javascript">
var PAT_SEQ_RAW = /^[ACGT]*$/;
var PAT_ALLELENAME_SPLIT = /[\]\)_]/g;
var graphs = false;
var linebreak = "\n";
var data_format = {};
......@@ -701,12 +719,14 @@ function parse(maintainSelection){
var i = graphs.length;
//Add new visualisation and table divs.
var visouter = document.createElement("div");
var newvis = document.createElement("div");
newvis.setAttribute("id", "vis" + i);
visdiv.appendChild(newvis);
visouter.appendChild(newvis);
var newtab = document.createElement("div");
newtab.setAttribute("id", "tab" + i);
visdiv.appendChild(newtab);
visouter.appendChild(newtab);
visdiv.appendChild(visouter);
var graph = chart({el: newvis, renderer: rendererName});
graph.onSignal("clickedAllele", function(name, value){
......@@ -732,6 +752,174 @@ function parse(maintainSelection){
updateTable(i);
});
graph.onSignal("bias_threshold", function(){updateTable(i)});
graph.onSignal("hovered", function(s, datum){