Multiple networks integrated into one network in Cytoscape - cytoscape

I have a list of genes (let’s call it L), and I want to see how they work differently in 3 different species (human, zebrafish and cod). Of course, the 3 species don’t have all the genes in the list, besides, the interactions between genes are different across 3 species. Firstly, I search the genes in this list against the genomes of 3 species, to get 3 gene lists for 3 species (let’s call them l1, l2, l3). Then I put the 3 gene lists into STRING respectively. So now I have 3 networks (let’s call them n1, n2, n3), each network for each species.
With those 3 networks and 4 lists, I come to Cytoscape. What I want to visualise is to show 3 networks together. So the background is the all the nodes from L. When I say, let’s look at human, the network n1 (including both the nodes from l1 and the edges between them) will be hi-lighted (the other genes from the other two species stay there without moving, but faded out as a background). Then you also do the same for zebrafish and cod. By doing this, one can see how the genes work differently across 3 species.
So is that possible to be done in Cytoscape? Thank you in advance.

You could start with initializin cytoscape with L:
// Initialize cytoscape
cy = window.cy = cytoscape({
container: $('#diagram'),
boxSelectionEnabled: false,
autounselectify: true,
layout: {
name: 'random'
},
elements: L,
style: [
{
selector: 'node',
style: {
'shape': 'data(faveShape)',
'content': 'data(DisplayName)',
'height': 'data(faveHeight)',
'width': 'data(faveWidth)',
'background-color': 'data(faveColor)',
'line-color': '#a8eae5',
'font-family': 'Segoe UI,Helvetica Neue,Helvetica,Arial, Verdana',
'font-size': '15px',
}
},
{
selector: 'edge',
style: {
'label': 'data(myLabel)',
'curve-style': 'bezier',
'width': 5,
'opacity': 0.5,
'line-color': '#a8eae5',
'font-size': '12px',
'target-arrow-shape': 'triangle',
'target-arrow-color': '#a8eae5'
}
},
{
selector: '.autorotate',
style: {
'edge-text-rotation': 'autorotate'
}
},
{
selector: 'edge.deactivate',
style: {
'opacity': 0.1,
}
},
{
selector: 'node.deactivated',
style: {
'opacity': 0.1,
}
}
],
});
After that you could add all the edges, but you have to add a property to tell which species the edges. Additionally you have to give the deactivated property to all nodes.
cy.nodes().addClass('deactivated');
cy.add('All the edges you have'); // Write somthing like species : 1 for first species and so on
cy.ready(function () {
cy.edges().addClass('deactivate');
});
This way all your nodes are on the graph, they are faded and you have all the edges there. You now could define a button or something and select the right groups and edges and remove the classes with:
cy.nodes("[species = '" + num + "']").removeClass(deactivated);
cy.edges("[species = '" + num + "']").removeClass(deactivate);
When you select another group, you can always say:
cy.nodes().addClass(deactivated);
cy.edges().addClass(deactivate);
and then select the right ones.

Related

In a deck.gl GeojsonLayer, how can I hide individual polygons?

I have a polygon GeoJSON layer in my deck.gl map. To avoid having to reload many polygons in many user interactions, I would like to pre-load all polygons and then change their visibility. I tried to achieve this by setting the fill color (and also line color and line width, but there it's hidden in the functions) to null depending on the polygon properties.
new deck.GeoJsonLayer({
id: 'polygon-layer',
data: family,
pickable: true,
getPosition: d => d.geometry.coordinates,
filled: true,
getFillColor: d => show(d) ? hexToIntColor(d.properties.color) : null,
lineWidthUnits: "pixels",
getLineWidth: highlighted,
getLineColor: highlighedColor,
lineWidthMinPixels: 1,
visible: true,
onClick: displayProperties,
updateTriggers: {
getLineWidth: [highlightedMap, highlightedCode],
getLineColor: [highlightedMap, highlightedCode],
getFillColor: [highlightedMap, highlightedCode]
}
})
The result is very much not what I expected
How do I set individual polgons to not be displayed? (And where do these strange black gradients come from which I see instead of just seeing the pink and coastline from the background map?)
Try using DataFilterExtension, setting filterRange to [1, 1] means that only entities that meet the condition (1) will be rendered, and not (0):
new deck.GeoJsonLayer({
...
getFilterValue: (d) => Number(show(d)),
filterRange: [1, 1],
extensions: [new DataFilterExtension({ filterSize: 1 })],
updateTriggers: {
getFilterValue: [yourTrigger]
}
});

Highcharts unevenly spaced x-axis with category labels

I'm trying to plot some sparse values over a few hundred x-axis category labels. The labels represent points along a geographical entity, so it is necessary to space them according to the actual distance between each point.
I can easily make x-axis categories and plot the values against them, but each category is evenly spaced. If I change to using a complex marker with {x, y, name} properties, the categories are only displayed if they match the tick interval. If a category doesn't match the tick interval, then a number is displayed.
I can produce the following:
with this small fake sample of data, JSFiddle:
...
xAxis: {
type: 'category'
},
series: [{
name: 'Series 1',
data: [
{x:1, y:null, name: 'AB1.1'},
{x:4, y:1, name: 'AB1.2'},
{x:5, y:null, name: 'AB1.3'},
{x:11, y:1, name: 'AB1.4'},
{x:14, y:null, name: 'AB1.5'},
{x:14, y:null, name: 'AB1.6'},
{x:19, y:1, name: 'AB1.7'},
{x:27, y:1, name: 'AB1.8'},
{x:28, y:null, name: 'AB1.9'},
{x:30, y:1, name: 'AB2'},
{x:37, y:1, name: 'AB2.1'},
{x:37, y:1, name: 'AB2.2'},
{x:38, y:1, name: 'AB2.3'},
]
}]
...
As you can see, the x-axis at this zoom level shows:
0, 3, 6, 9, 12, 15, 18, 21, 24, AB1.8, AB2, 33, 36, 39
What I want is for the x-axis to show any of the actual labels (so long as the markers are placed relative to their distance, just like the x-values of the plot); but no generated numbers.
In reality, I have multiple series with around 1,000 points each, but they will all be on the same geographical entity so they all share the same categories. (JSFiddle with much more fake data). I can also guarantee that x-values are whole numbers.
I have already tried specifying various x-axis options around ticks, minimum ticks etc. but highcharts still wants to extrapolate evenly spaced labels.
Thanks!
I have got the results I want (JSFiddle) by setting xAxis.tickPositions dynamically on zoom. To begin with, I pick about 35 x-Axis positions to display my markers (an arbitrary number but I picked something that worked for my fixed-width chart size).
Then, on zoom, I update the chart to display about 30 markers that are within the new zoom level.
This way I always have a good number of markers displayed, and they are unevenly spaced because that's what my actual data is like.
Zoomed out (L) and zoomed in (R):
this is an array of all x-axis points that have a marker-a few thousand
allTicks = [1, 6, 9, 9, ...]
a function to select 30 points from the given array
function selectTickPositions(tickPositions) {
const maxTicks = 30;
if (tickPositions.length <= maxTicks) return tickPositions; // return all
let mod = Math.round(tickPositions.length / maxTicks);
// always select the first and the last, and then up to 30 more
return tickPositions.filter((val, idx) => idx == 0 || idx == tickPositions.length - 1 || idx % mod == 0);
}
setup the chart options:
let theChart = Highcharts.chart('container', {
chart: {
...
events: {
// the selection event is fired when a zoom selection is made
selection: (event) => {
let ticks;
if (event.xAxis) {
let min = event.xAxis[0].min;
let max = event.xAxis[0].max;
ticks = selectTickPositions(allTicks.filter(t => t >= min && t <= max));
} else {
ticks = selectTickPositions(allTicks);
}
theChart.update({
xAxis: {
tickPositions: ticks
}
});
return true;
}
}
},
...
xAxis: {
type: 'category',
tickPositions: selectTickPositions(allTicks)
},
});
I am not sure if I understand your requirement very well, but here is my attempt of showing just a xAxis.labels if the label is a category string.
Demo: https://jsfiddle.net/BlackLabel/4xdjw5L7/
xAxis: {
type: 'category',
endOnTick: true,
startOnTick: true,
labels: {
formatter() {
if (typeof this.value !== 'number') {
return this.value
}
}
}
},
API: https://api.highcharts.com/highcharts/xAxis.labels.formatter
Let me know if this is an expected output.

Missing series name as label in highcharts heatmaps

I created a calendar using a heatmap, like this:
calendar screen:
The axis types are categories, so the months are placed as blocks with the respective offset in the matrix. Every month is defined as a series with names.
Now my problem is, I want to show the month name above the block. However, I found no way to display the serial name. He is simply ignored.
The x-axis displays only the index of the category. I can not use this. The data label contains the color value for the heatmap.
My workaround currently is that I insert the month names as PlotLine. But that's not the way to go. Especially since the positioning is independent of the monthly block and thus error-prone.
series: [{
name: 'January',
keys: ['x', 'y', 'value'],
data: [...]
}, ...next month...]
jsFiddle example
You can use Highcharts.SVGRenderer to add series name as text in calculated position:
events: {
load: function() {
var series = this.series,
bbox;
series.forEach(function(s) {
bbox = s.group.getBBox(true);
this.renderer.text(
s.name,
bbox.x + this.plotLeft + bbox.width/2,
bbox.y + this.plotTop - 10
)
.attr({
align: 'center'
})
.css({
color: 'black',
fontSize: '12px'
})
.add();
}, this);
}
}
Live demo: https://jsfiddle.net/BlackLabel/zypnwq50/
API Reference: https://api.highcharts.com/class-reference/Highcharts.SVGRenderer#text

How to plot horizontal lines over the some columns of columnrange chart in Highcharts

I am working on a columnrange graph in Highcharts where I plot different measurements and confidence intervals in the same plot:
The first few columns inside a group (e.g. Januar) represent measurements for different cities, while the last column represent confidence intervals. I would like to add horizontal lines to the confidence intervals representing the data means. That is, each orange column would get its own line at a specific heigh going from the left to the right side of the orange rectangle. How do I plot such lines?
I know how to add lines as a separate series of type line. However, doing so, I'm not sure how to guess the exact location of orange column and also I do not know how to handle cases when some columns are hidden through the legend.
This question is related to this question though I am not able to get any of that solutions to work in my case.
Here is the fiddle: https://jsfiddle.net/nikicc/rqxqm4hm/
You can use renderer.path to draw proper lines.
function drawDataMeans() {
const intervalSeries = this.get('conf-interval'),
series = this.series.filter(series => intervalSeries !== series)
let lines = this.dataMeansLines
if (!lines) {
lines = this.dataMeansLines = series[0].data.map(series => this.renderer.path().attr({
'stroke-width': 2,
stroke: 'black'
}).add(intervalSeries.group))
}
const visibleSeries = series.filter(series => series.visible)
if (intervalSeries.visible && visibleSeries.length) {
intervalSeries.data.forEach((point, i) => {
const mean = visibleSeries.reduce((sum, series) => sum + series.data[i].high, 0) / visibleSeries.length
const {x, width} = point.shapeArgs
const y = this.yAxis[0].toPixels(mean, true)
lines[i].attr({
d: `M ${x} ${y} L ${x + width} ${y}`,
visibility: 'visible'
})
})
} else {
lines.forEach(line => line.attr({visibility: 'hidden'}))
}
}
Hook on load/redraw events
chart: {
type: 'columnrange',
inverted: false,
events: {
load: drawDataMeans,
redraw: drawDataMeans
}
},
example: https://jsfiddle.net/dq48sq3w/

Multiple different chart types stacked, column type with y value as color

What is the best way to achieve a chart with multiple types when it should include a type that has the following kind of visual presentation.
| yellow |blue| gray | yellow | gray |
i.e. a type which is one dimensional (but visually has height), and the color indicates 'y' (which here consists of categories: yellow, blue, gray)
You should also be able to stack those:
| radical | senseless | high tension |
| yellow |blue| gray | yellow | gray |
I can achieve this with having a chart typed column with a series for each category:
http://jsfiddle.net/RCnYV/
But how can I also add another chart type above that, like:
yAxis (only for the line)
^ ___
|------- ___________________________ ____/
| \__________/ \/
| radical | senseless | high tension |
| yellow |blue| gray | yellow | gray |
-----------------------------------------------------------> xAxis (shared)
So the line series should be above (not hovering over) the others. Note that the xAxis is shared between all of the series, i.e. all of the series have exactly as many data points. It is just that some of the series are presented as type 'line', and others with the new type (that I don't know good name for, ribbon?).
Also what other ways are there to create a similar chart? One problem with the above is that I need to create one series for each catalog, that is 2 * series in total, and not just two as would be the case with basic chart.
Are you looking for something like this # http://jsfiddle.net/jugal/cABfL/ ?
You can stack the charts by specifying heights for your yAxis, and manipulating its top so that they stack one over the other
yAxis: [{
top: 300,
lineWidth: 2,
offset: 0,
height: 200,
tooltip: {
enabled: true,
formatter: function() {
return this.series.name + ": " + $wnd.Highcharts.numberFormat(this.y, 2);
}
}
},
{
height: 200,
lineWidth: 2,
offset: 0,
tooltip: {
enabled: true,
formatter: function() {
return this.value + 50;
}
}
}],
Similar stacking example is available # http://www.highcharts.com/stock/demo/candlestick-and-volume
EDIT
To answer to the second part of the question (Also what other ways are there to create a similar chart?). There isn't anything out of the box that highchart seems to bring to the table for such a visualization, so you would need to work yourself around the existing lines and columns to get this visualization.
This is how I went about it.
I tried using the stacked bar chart for each ribbon, hence would need 2 series, 1 for the line and 1 each for both the ribbons. But after giving it a try, turned out the bar chart is nothing but a rotated column chart (at least a sort of), it seems to have the vertical axis as the X and horizontal one as Y, hence it messes up any other chart, i.e. the line chart gets messed up as it wants the horizontal to be the X.
Basically using a bar chart didn't take me much far. I went ahead using the line chart (With a very thick line lineWidth:50) and drew a horizontal (Constant Y for each point) line chart with one series for each section of the ribbon, hence being able to give each section different color. Each ribbon would need a separate Y-axis, with different offset as mentioned above. Also removed all the tooltip, Y-axis labels and grid lines, to make it look as different from a line chart and more like the ribbon. Tooltip may be needed, but line charts give tooltip for points, in our case we want tooltip on section between two points, hence wrote a mouseOver event handler and calculated the length of the section in there. The only part that was hurting now was creating a series for each section of the ribbon, so went ahead and wrote the following utility function that accepted a list of values, basically the x intercepts for each section (you can improvise it to take section length instead) and returned an array of series.
// usage: createSeries([0, 3, 4, 6], 1)
// Creates 4 series and assigns them all to yAxis 1
// you can extend this to take colors etc too, as per requirement
function createSeries(data, yAxisIndex) {
var i;
var series = [];
for (i = 0; i < data.length - 1; i++) { // Node lenghth-1
var start = data[i];
var end = data[i + 1];
series.push({
yAxis: yAxisIndex,
animation: false,
stack: 0,
data: [[start, 0], [end, 0]],
lineWidth: 50,
marker: {
enabled: false
},
tooltip: {
pointFormat: function() {
return "";
}
},
events: {
mouseOver: function() {
alert(this.data[1].x - this.data[0].x);
}
},
showInLegend: false
});
}
return series;
}
All that was needed was to push these series into the existing series and then feed it to the highchart constructor.
Final jsFiddle: http://jsfiddle.net/jugal/cABfL/

Resources