Commit 5f102e8b authored by Ariane Mora's avatar Ariane Mora

Using crossfilter for the data processing and to group and filter on elements to make it fast.

parent e7cecc37
/**
* Processes the data using crossfilter.
* help:
* top sorts descending (text or num) on the field
* returns the top x amount. Can sort in terms of top infinity --> to get a sorted list.
* bottom sorts ascending (but same same).
*
* to remove dimesnion = dispose
* Can have max 32 (> 8 dimensions cause it to be very slow).
* Can make an array to have several elements in a dimensions (i.e. start and end).
* .all() on the grouped data exposes the data to be able to use it in Javascrippt
*
* filterRangd([>=min, <max]); Can also do on strings
* there is also a filter for a function.
*/
/**
* Helps with debugging. Native cross filter objects can't be viewed properly in
* console.log.
*/
function print_filter(filter) {
var f = eval(filter);
if (typeof (f.length) != "undefined") {
} else {
}
if (typeof (f.top) != "undefined") {
f = f.top(Infinity);
} else {
}
if (typeof (f.dimension) != "undefined") {
f = f.dimension(function (d) {
return "";
}).top(Infinity);
} else {
}
console.log(filter + "(" + f.length + ") = " + JSON.stringify(f).replace("[", "[\n\t").replace(/}\,/g, "},\n\t").replace("]", "\n]"));
}
/**
* ----------------------------------------------------------------------------
* Setup the data
* ----------------------------------------------------------------------------
*/
var processed_data = {};
var set_up_genome_data = function (data) {
// Set up the crossfilter facts. --> use a JSON object i.e. data
// that contains elements (array) these get translated to facts.
// Data contains the following:
// 1.chrom 2.start 3.end 4.gene or network
var genome_facts = crossfilter(data);
// Store globally
processed_data["genome_facts"] = genome_facts;
}
var add_network_data = function(network_data) {
// Add the network data to the genome data
processed_data.genome_facts.add(network_data);
}
/**
* ----------------------------------------------------------------------------
* Create dimensions
* ----------------------------------------------------------------------------
*/
var create_type_dimension = function () {
// Create a dimension that allows easy filtering on the networks or gene
var type_dimension = processed_data.genome_facts.dimension(function (d) {
return d.type;
});
// Store globally
processed_data["type_dimension"] = type_dimension;
}
var create_start_dimension = function () {
// Dimensions are stateful.
// Create a dimesnsion on the start of either the gene or network
var start_dimension = processed_data.genome_facts.dimension(function (d) {
return d.start;
});
// Store globally
processed_data["start_dimension"] = start_dimension;
}
var create_end_dimension = function () {
// Dimensions are stateful.
// Create a dimesnsion on the end of either the gene or network
var end_dimension = processed_data.genome_facts.dimension(function (d) {
return d.end;
});
// Store Globally
processed_data["end_dimension"] = end_dimension;
}
var create_chrom_dimension = function () {
// Create a dimesnsion on the chromosone of the gene or network
var chrom_dimension = processed_data.genome_facts.dimension(function (d) {
return d.chrom;
});
// Store Globally
processed_data["chrom_dimension"] = chrom_dimension;
}
/**
* ----------------------------------------------------------------------------
* Sort functions called during vis interaction
* ----------------------------------------------------------------------------
*/
var clear_filters = function() {
processed_data.start_dimension.filterAll();
processed_data.end_dimension.filterAll();
processed_data.chrom_dimension.filterAll();
processed_data.type_dimension.filterAll();
}
var filter_on_position = function(start, end) {
// Clear the associated filters.
processed_data.start_dimension.filterAll();
processed_data.end_dimension.filterAll();
// Filters the data based on the start and end positions
// filterRange([>=min, <max]); Can also do on strings
processed_data.start_dimension.filterRange([start, end]);
processed_data.end_dimension.filterRange([start, end]);
// Now the underlying data has changed (will need to redraw)
return processed_data.end_dimension.top(Infinity);
}
var filter_on_chrom = function(chrom) {
// Clear associated filter
processed_data.chrom_dimension.filterAll();
// Use an exact filter as we only want that specific chromosone.
processed_data.chrom_dimension.filterExact(chrom);
// Now the underlying data has changed (will need to redraw)
}
var filter_on_networks = function() {
// Clear associated filter
processed_data.type_dimension.filterAll();
// Allows us to only look at networks (the genes will have the gene ID in
// that collumn).
processed_data.type_dimension.filterExact("network");
// Now the underlying data has changed (will need to redraw)
}
var filter_on_gene = function(gene) {
// Clear associated filter.
processed_data.type_dimension.filterAll();
// Here we filter using the type dimension as that will either have "network"
// or the gene ID.
processed_data.type_dimension.exactFilter(gene);
// Now the underlying data has changed (will need to redraw)
}
/**
* Draws the human genome.
* Draws the human genome.
* Enables users to orientate themselves and click into a chromosone.
*
*
* Adapted from: https://bl.ocks.org/mbostock/4349545
*/
var genome_attr = {
......@@ -36,47 +36,88 @@ var network_tooltip = d3.select("body").append("div")
.style("opacity", 0);
d3.tsv("../../../data/vis/" + genome_attr.data.genes, function (data) {
d3.tsv("../binfkitVis/data/" + genome_attr.data.genes, function (data) {
for (var i = 0; i < data.length/2; i++) {
for (var i = 0; i < data.length / 10; i++) {
var d = data[i];
var tmp = {};
tmp['start'] = +d.start;
tmp['end'] = +d.end;
// For our purposes we save the gene on the type parameter so we
// can reduce the number of columns.
tmp['type'] = d.gene;
// Genes are placed in position 1.
tmp['y'] = 1;
tmp['chrom'] = d.chrom;
// Can add extra info here if necessary.
if (d.start < genome_attr.min) {
genome_attr.min = d.start;
}
if (d.end > genome_attr.max) {
genome_attr.max = d.end;
}
d.y = 1;
genome_attr.data.genome_data.push(d);
genome_attr.data.genome_data.push(tmp);
}
});
var run_networks_in_bed = function(data) {
d3.json("../binfkitVis/data/" + genome_attr.data.networks, function (network_data) {
for (var i = 0; i < network_data.length / 10; i++) {
var d = network_data[i];
if (d.start < genome_attr.min) {
genome_attr.min = d.start;
}
if (d.end > genome_attr.max) {
genome_attr.max = d.end;
}
d.y = 0;
genome_attr.data.network_data.push(d);
}
d3.json("../../../data/vis/" + genome_attr.data.networks, function (network_data) {
for (var i = 0; i < network_data.length/2; i++) {
var d = network_data[i];
if (d.start < genome_attr.min) {
genome_attr.min = d.start;
}
if (d.end > genome_attr.max) {
genome_attr.max = d.end;
}
d.y = 0;
genome_attr.data.network_data.push(d);
}
init_genome_vis();
init_genome_vis();
});
});
}
});
//d3.tsv("../../../data/vis/" + genome_attr.data.genes, function (data) {
//
// for (var i = 0; i < data.length/2; i++) {
// var d = data[i];
// if (d.start < genome_attr.min) {
// genome_attr.min = d.start;
// }
// if (d.end > genome_attr.max) {
// genome_attr.max = d.end;
// }
// d.y = 1;
// genome_attr.data.genome_data.push(d);
// }
// });
//
//var run_networks_in_bed = function(data) {
//
// d3.json("../../../data/vis/" + genome_attr.data.networks, function (network_data) {
// for (var i = 0; i < network_data.length/2; i++) {
// var d = network_data[i];
// if (d.start < genome_attr.min) {
// genome_attr.min = d.start;
// }
// if (d.end > genome_attr.max) {
// genome_attr.max = d.end;
// }
// d.y = 0;
// genome_attr.data.network_data.push(d);
// }
// init_genome_vis();
//
// });
//
//}
/**
* A function that draws on the view.
* elements = genome_attr.data.genome_data
*/
var draw_rects_on_genome_large = function (elements, network, y_pos) {
var draw_rects_on_genome_large = function (elements) {
// append genes as small bars to main chart area
var genes = genome_attr.vis.focus.append("g");
......@@ -96,7 +137,7 @@ var draw_rects_on_genome_large = function (elements, network, y_pos) {
return genome_attr.vis.scale.y(d.y);
})
.attr("width", function (d) {
if (network === false) {
if (d.type != "network") {
return genome_attr.vis.rect.width_lrg;
} else {
return genome_attr.vis.scale.x(d.end) - genome_attr.vis.scale.x(d.start);
......@@ -135,9 +176,9 @@ var draw_rects_on_genome_small = function (elements) {
var genes = genome_attr.vis.context.append("g");
genes.attr("clip-path", "url(#clip)");
genes.selectAll("gene")
.data(elements)
.data(elements.filter(element => element.y == 1))
.enter().append("rect")
.attr('class', 'geneContext')
.attr('class', 'gene')
.attr("fill", function (d) {
return genome_attr.vis.colour(d.chrom);
})
......@@ -223,14 +264,6 @@ var setup_genome_brush_zoom = function () {
.extent([[0, 0], [genome_attr.vis.width, genome_attr.vis.height2]])
.on("brush", brushed);
// var zoom = d3.zoom()
// .scaleExtent([1, Infinity])
// .translateExtent([[0, 0], [genome_attr.vis.width,
// genome_attr.vis.height]])
// .extent([[0, 0], [genome_attr.vis.width,
// genome_attr.vis.height]])
// .on("zoom", zoomed);
genome_attr.vis.focus.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
......@@ -238,26 +271,16 @@ var setup_genome_brush_zoom = function () {
.attr("height", genome_attr.vis.height2);
genome_attr.vis.brush = brush;
// genome_attr.vis.zoom = zoom;
}
var draw_genome_brush_element = function () {
genome_attr.vis.focus.append("g")
.attr("class", "axis x-axis")
.attr("transform", "translate(0," + genome_attr.vis.height + ")")
.call(genome_attr.vis.xAxis);
// genome_attr.vis.svg.append("rect")
// .attr("class", "zoom")
// .attr("width", genome_attr.vis.width)
// .attr("height", genome_attr.vis.height)
// .attr("transform", "translate(" + genome_attr.vis.margin.left +
// "," + genome_attr.vis.margin.top + ")")
// .call(genome_attr.vis.zoom);
genome_attr.vis.context.append("g")
.attr("class", "axis x-axis")
.attr("transform", "translate(0," + genome_attr.vis.height2 +
......@@ -271,7 +294,7 @@ var draw_genome_brush_element = function () {
}
//create brush function redraw scatterplot with selection
//create brush function redraw with selection
function brushed() {
var x = genome_attr.vis.scale.x;
var x2 = genome_attr.vis.scale.x2;
......@@ -282,66 +305,42 @@ function brushed() {
var svg = genome_attr.vis.svg;
if (d3.event.sourceEvent && d3.event.sourceEvent.type === "zoom")
return; // ignore brush-by-zoom
var ex = genome_attr.vis.brush.extent();
var s = d3.event.selection || x2.range();
x.domain(s.map(x2.invert, x2));
focus.selectAll(".gene")
.attr("x", function (d) {
return x(d.start);
})
.attr("y", function (d) {
return y(d.y);
})
.attr("width", function (d) {
// if (network === false) {
// return genome_attr.vis.rect.width_lrg;
// } else {
return genome_attr.vis.scale.x(d.end) - genome_attr.vis.scale.x(d.start);
// }
});
var dom = s.map(x2.invert, x2);
focus.selectAll(".gene").remove();
draw_rects_on_genome_large(filter_on_position(dom[0], dom[1]));
focus.select(".x-axis").call(xAxis);
// svg.select(".zoom").call(genome_attr.vis.zoom.transform, d3.zoomIdentity
// .scale(genome_attr.width / (s[1] - s[0]))
// .translate(-s[0], 0));
}
function zoomed() {
var x = genome_attr.vis.scale.x;
var x2 = genome_attr.vis.scale.x2;
var y = genome_attr.vis.scale.y;
var focus = genome_attr.vis.focus;
var context = genome_attr.vis.context;
var xAxis = genome_attr.vis.xAxis;
if (d3.event.sourceEvent && d3.event.sourceEvent.type === "brush")
return; // ignore zoom-by-brush
var t = d3.event.transform;
x.domain(t.rescaleX(x2).domain());
focus.selectAll(".gene")
.attr("x", function (d) {
return x(d.start);
})
.attr("y", function (d) {
return y(d.y);
})
.attr("width", function (d) {
return genome_attr.vis.scale.x(d.end) - genome_attr.vis.scale.x(d.start);
});
focus.select(".x-axis").call(xAxis);
context.select(".brush").call(genome_attr.vis.brush.move, x.range().map(t.invertX, t));
}
var init_genome_vis = function () {
// Options for rect vis
var vis = genome_attr.vis;
// Here the first thing we want to do is set up the data using cross filter.
set_up_genome_data(genome_attr.data.genome_data);
add_network_data(genome_attr.data.network_data);
// Set up the dimensions that will be acting on the data (enabling filtering)
create_type_dimension();
create_start_dimension();
create_end_dimension();
create_chrom_dimension();
// Set up the visualisation elements
setup_genome_svg();
setup_genome_scales();
setup_genome_axis();
setup_genome_brush_zoom();
// Draw the graphical elements
draw_genome_brush_element();
draw_rects_on_genome_large(genome_attr.data.genome_data, false);
draw_rects_on_genome_large(genome_attr.data.network_data, true);
draw_rects_on_genome_small(genome_attr.data.genome_data);
draw_rects_on_genome_large(processed_data.type_dimension.top(Infinity));
draw_rects_on_genome_small(processed_data.type_dimension.top(Infinity));
}
/**
* The main file that renders a visualisation of circuits in DNA.
* The main file that renders a visualisation of circuits in DNA.
*/
var data = {
......@@ -18,7 +18,7 @@ var dna_attr = {
node_points: [],
colour_outer: "black",
colour_inner: "green",
width: 3,
width: 3,
height: 5,
},
semi_circle: {
......@@ -40,8 +40,8 @@ var dna_attr = {
};
/**
*
* Parses the main json file containing information
*
* Parses the main json file containing information
* regarding the nodes and edges of the file.
*/
var parse_json_file = function (data_input) {
......@@ -53,7 +53,7 @@ var parse_json_file = function (data_input) {
divide_edge_dict(edges);
var ordered_nodes = order_nodes(nodes);
data['ordered_nodes'] = ordered_nodes;
dna_attr.rect.colour_inner = d3.scaleLinear().domain([1,ordered_nodes.length])
.interpolate(d3.interpolateHcl)
.range([d3.rgb("#007AFF"), d3.rgb('#FFF500')]);
......@@ -141,8 +141,8 @@ var make_into_fdg_format = function (nodes, edges, to_edges) {
}
/**
*
* Helper that changes the JSON object from being an array
*
* Helper that changes the JSON object from being an array
* to a string or int (i.e. makes the first element of the object
* the only element.)
*/
......@@ -190,7 +190,7 @@ var order_nodes = function (nodes) {
ordered_nodes[n]['actual_id'] = 'n' + n;
nodes[ordered_nodes[n].label]['actual_id'] = 'n' + n;
/**
*
*
* Below is for drawing the DNA strand
*/
var start_angle = (n * region_len);
......@@ -215,10 +215,10 @@ var order_nodes = function (nodes) {
}
/**
*
*
* Sorts edges into two dictionaries.
* One has: to -> and
* the other: from ->
* One has: to -> and
* the other: from ->
* nodes as the keys.
*/
var divide_edge_dict = function (edges, nodes) {
......@@ -239,7 +239,7 @@ var divide_edge_dict = function (edges, nodes) {
}
/**
*
*
* Gets the max and min of the position.
*/
var get_max_min = function (nodes, edges) {
......@@ -413,7 +413,7 @@ var setup_strand_svg = function () {
svg = svg.append("g")
.attr("transform", "translate(" + margin.left +
"," + margin.top + ")");
dna_attr.svg = svg;
dna_attr.width = width;
dna_attr.height = height;
......@@ -421,7 +421,7 @@ var setup_strand_svg = function () {
}
/**
*
*
* Draws the underlying path.
* i.e. the main semi circle and the tails.
*/
......@@ -503,7 +503,7 @@ var draw_nodes_accurate = function (nodes) {
///**
// *
// *
// * Draws the positions on the semi circle. These are signified by rectangular sections.
// */
//var draw_node_rect = function (start_angle, end_angle, colour) {
......@@ -533,11 +533,11 @@ var draw_gene_rect = function(x, y, node) {
.attr("x", x)
.attr("y", y)
.attr("width", dna_attr.gene.rect_width)
.attr("height", dna_attr.gene.rect_height);
.attr("height", dna_attr.gene.rect_height);
}
var draw_interaction_points = function() {
dna_attr.svg.selectAll("interaction-pts")
.data(dna_attr.rect.node_points)
.enter().append("circle")
......@@ -564,13 +564,13 @@ var draw_strand = function (nodes) {
line_data = [];
var n = nodes[node].label;
x1_y1 = nodes[n].x_y;
x1_y1 = nodes[n].x_y;
line_data.push(x1_y1);
// May not have a node going to it
for (var e_from in from_edges[node]) {
var to_node = nodes[from_edges[node][e_from].to]
x2_y2 = to_node.x_y;
x2_y2 = to_node.x_y;
line_data.push(x2_y2);
}
......@@ -598,7 +598,7 @@ var draw_dna_len = function (nodes) {
dna_attr.rect.node_points.push({x: inner_rad * Math.cos(last_node_angle), y: inner_rad * Math.sin(last_node_angle), id: nodes.length - 1});
draw_line(line_data, dna_attr.dna_strand.dist_stroke_colour);
}
......@@ -613,7 +613,7 @@ var calc_loop_interpolation_points = function (angle1, angle2, inner_rad, mid_ra
var end_mid = (angle2 + mid_angle) /2;
inner_pt_1 = {x: inner_rad * Math.cos(angle1), y: inner_rad * Math.sin(angle1)};
inner_pt_2 = {x: inner_rad * Math.cos(angle2), y: inner_rad * Math.sin(angle2)};
small_pt_1 = {x: small_rad * Math.cos(angle1), y: small_rad * Math.sin(angle1)};
small_pt_1 = {x: small_rad * Math.cos(angle1), y: small_rad * Math.sin(angle1)};
small_pt_2 = {x: small_rad * Math.cos(angle2), y: small_rad * Math.sin(angle2)};
mid_pt_1 = {x: mid_rad * Math.cos(start_mid), y: mid_rad * Math.sin(start_mid)};
mid_pt_2 = {x: mid_rad * Math.cos(end_mid), y: mid_rad * Math.sin(end_mid)};
......@@ -639,7 +639,7 @@ var calc_loop_interpolation_points = function (angle1, angle2, inner_rad, mid_ra
/**
*
*
* Simple line function that determins the interpolation.
*/
var line_function = d3.line()
......@@ -653,7 +653,7 @@ var line_function = d3.line()
/**
*
*
* Draw the DNA strand based on the points added above.
*/
var draw_line = function (line_data, colour) {
......
......@@ -39,6 +39,8 @@
<script type="text/javascript" th:src="@{/js/vis/lib/crossfilter.min.js}"></script>
<script type="text/javascript" th:src="@{/js/vis/lib/d3.min.js}"></script>
<script type="text/javascript" th:src="@{/js/vis/dataProcessing.js}"> </script>
<script type="text/javascript" th:src="@{/js/vis/threeDVis.js}"> </script>
<script type="text/javascript" th:src="@{/js/vis/ajaxCalls.js}"> </script>
<script type="text/javascript" th:src="@{/js/vis/genome.js}"> </script>
......
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