Cytoscape inconsistent spacing in a grid layout - cytoscape.js

I'm using cytoscape to represent a DAG where nodes are grouped under compound nodes. The number of compound nodes is fixed (4). I want to make this graph entirely visible even for many nodes. This is possible in theory as the total width isn't large (4 cols) and the nodes inside the parents can be positioned vertically in rows.
For that I have been using a grid layout like that:
{
name: 'grid',
fit: false,
nodeDimensionsIncludeLabels: true,
condense: false,
avoidOverlap: true,
cols: 4,
position: function(node) {
let col, row;
if (node.classes().includes('a')) {
col = 0;
row = aRow++;
} else if (node.classes().includes('b')) {
col = 1;
row = bRow++;
} else if (node.classes().includes('c')) {
col = 2;
row = cRow++;
} else if (node.classes().includes('d')) {
col = 3;
row = 0;
}
return {row: row, col: col};
},
sort: function(l, r) {
return l.data('id').localeCompare(r.data('id'));
}
}
I set these attributes for the node css:
'height': 'label'
'width': 'label'
I'd expect the horizontal spacing between the parent components and the vertical spacing between nodes inside the same parent to be the same for different graphs. Unfortunately it doesn't seem to be the case.
The produced spacing for this larger graph looks ok:
However for this smaller graph I don't understand why those two parents nodes end up so close and why there is so much padding between the nodes:
Am I doing something wrong or the grid layout isn't suited for this?

Related

Insert column at the first position in grid

I am trying to insert row selection at the first position of grid but it always ends up among hidden columns. I did the same thing with delete button column and it worked just fine.
protected getColumns(): Slick.Column[] {
var cols = super.getColumns();
cols.unshift({
field: 'Delete Row',
name: '',
format: ctx => '<a class="inline-action delete-row" title="delete">' +
'<i class="fa fa-trash-o text-red"></i></a>',
width: 24,
minWidth: 24,
maxWidth: 24,
visible: true
});
cols.unshift(Serenity.GridRowSelectionMixin.createSelectColumn(() => this.rowSelection));
return cols;
The problem is not incorrect implementation of selection row. I know that because I tried it with different columns with same results. I also tried to set "visible" to true
Any ideas? Thanks
This code will make your selection column stay at first position
protected getPersistedSettings() {
let setting = super.getPersistedSettings();
let idCol = Q.tryFirst(setting.columns, x => x.id == "__select__");
if (idCol) {
setting.columns.splice(setting.columns.indexOf(idCol), 1);
setting.columns.splice(0, 0, idCol);
}
return setting;
}
But make sure that the selection is not in hidden list
The problem was that persistence of data was turned on with this function
protected getPersistanceStorage(): Serenity.SettingStorage {
return new Common.UserPreferenceStorage();
}

Dse Graph loader duplicate edges

I have the following csv files:
one is with the person and the other one is with the addresses and one with person address connection (one row on each file plus header). For testing purpose at first run I have:
config create_schema: true, load_new: true, load_threads: 3
The import is a success with the vertices and edges. (two vertices and one edge between them)
Now when I run the same script(same data, same input script) but with different config
config create_schema: false, load_new: false, load_threads: 3
It seems that the nodes didn’t change but I have a duplicate edge for the nodes. (two vertices and two edges between the same nodes)
this is the code that i run:
inputfiledir = 'data/'
personInput = File.csv(inputfiledir + 'sna_person_test.csv').delimiter(',')
addressInput = File.csv(inputfiledir + 'sna_address_test.csv').delimiter(',')
personAddressInput = File.csv(inputfiledir + 'san_person_address_test.csv').delimiter(',')
load(personInput).asVertices {
label "person"
key "id"
}
load(addressInput).asVertices {
label "address"
key "id"
}
load(personAddressInput).asEdges {
label "has_address"
outV "person_id", {
label "person"
key "id"
}
inV "address_id", {
label "address"
key "id"
}
}
Is there a way to avoid this ?
Thanks
This is due to edges not having an Id, which leads to Graph Loader not having a way to determine if an edge is in fact a duplicate. This will cause subsequent loads to duplicate the edges, but not the vertices.

How to adjust the position of several axes in one chart?

I create a line chart using dojo. Recently, I have been applying multiple axis on the chart. But there was a problem here. It is applied to multiple axes in one place I have raised the issue of overlapping tick value. and do not change the properties of leftBottom, is there a way to adjust the shaft position? For example, x: 10, y: 20?
my code
var axisXRef = {labels : labelsample, titleOrientation : "away", stroke : {}, natural : true};
var axisYRef = {vertical : true, stroke : {}};
var chart = new Chart("chartNode");
chart.addPlot("lines", { type: Lines, tension: 3 ,min:0});
chart.addPlot("stacklines", { type: StackedLines, tension: 3 ,hAxis:"x",vAxis:"y1"});
chart.addPlot("areas", { type: Areas, tension: 3,hAxis:"x",vAxis:"y2" });
chart.custom.axisX = lang.clone(axisXRef);
chart.custom.axisY = lang.clone(axisYRef);
chart.addAxis("x", chart.custom.axisX);
chart.addAxis("y", chart.custom.axisY);
chart.addAxis("y1", {
vertical: true,
min : 50,
max:70,
leftBottom:true,
majorLabels: true, majorTicks: true, majorTick: {color:"red",length:50},
minorLabels: true, minorTicks:true, minorTick:{color:"red",length:50},
microTicks: true, microTick:{color:"red",length:50},
fixUpper: "major",
fixLower:"minor"
});
chart.addAxis("y2", {
vertical: true,
min : 0,
max:49,
leftBottom:true,
majorLabels: true, majorTicks: true, majorTick: {color:"blue",length:25},
minorLabels: true, minorTicks:true, minorTick:{color:"blue",length:25},
microTicks: true, microTick:{color:"blue",length:25},
fixUpper: "major",
fixLower:"minor"
});
Unfortunately Dojo charting only supports two axis per direction both axis being on different side of the chart. In other words you can't have two axis both on the left side of the chart. You have to have one right side using leftBottom: false property.

jQuery Datatables highlighting row

I'm using datatables version 1.9.4 and am having a problem with adding a class to certain rows.
I have multiple datatables, all with class 'display'. I'm using jQuery tabs to display each datatable on a separate tab.
All is working well, except I want to add a class to a table row depending on the column values; if column 6 is less than column 14, I want to add myClass.
I've found suggestions to use fnRowCallback, but I'm getting random results, such as sometimes if column 6 is less than column 14, myClass gets added correctly, but other times if column 14 is less than column 6 myClass still gets added!
This doesn't happen for all rows though, so it's pretty random.
Here's the code I'm using
$(document).ready(function() {
$('.display').dataTable({
"bJQueryUI": true,
"sPaginationType": "full_numbers",
"bProcessing": true,
"bServerSide": true,
"bScrollCollapse": true,
"sScrollY": "300px",
"sAjaxSource": "ajax.php",
"sDom": '<"H"lfr>t<"F"ipS>',
"oScroller": {
"loadingIndicator": true
},
"fnRowCallback": function( nRow, aData ) {
var $nRow = $(nRow);
if (aData[6] < aData[14]) {
$nRow.addClass("myClass");
}
return nRow
}
});
});
Is there something wrong with what I've done, or is it because I'm using multiple tables?
I think I have this working, but there is probably a cleaner way, so if anyone knows of a better way of doing this, please let me know!
I'm looping through all the rows for each table once the table has been drawn.....
"fnDrawCallback": function( oSettings ) {
for (var i = 0, row; row = oSettings.nTable.rows[i]; i++) {
price = Number(row.cells[4].innerHTML.replace(/[^0-9\.]+/g,""));
average = Number(row.cells[6].innerHTML.replace(/[^0-9\.]+/g,""));
if (price < average) {
row.className = row.className + " myClass";
}
}
}

Create a combined bar/line chart with dimplejs and use self-defined colors

I'm trying to create a combined bar/line chart based on a simple data set (columns: countries, index1, index2, index3, ...) using dimplejs. Index1 will be the bar chart and index2 upwards should be dynamically (=adding and removing indices per user interaction) displayed as line charts on top.
I found out that I seemingly needed to create a hidden 2nd x-axis for the line graphics. Is there any other way?
I was also unable to add more than one index as line chart. Is there a way to add more lines where each one is based on a column (index2, index3, ...)?
Defining colors was another problem: The bars are all in one color which is good but if I want to assign a color myself I have to give the data a tag which is displayed in the tooltip (not good)?
Assigning colors to the line charts didn't work at all for me. I would need some advice here.
My code so far:
var svg = dimple.newSvg("#graphic", 550, 700);
// Get data for one year
var filteredData = dimple.filterData(data, 'year', '2010');
var myChart = new dimple.chart(svg, filteredData);
myChart.setBounds(50, 30, 480, 630);
var xAxis = myChart.addMeasureAxis('x', 'index1');
xAxis.title = 'Index Value';
xAxis.overrideMax = 1;
var yAxis = myChart.addCategoryAxis('y', 'countries');
yAxis.title = 'Country';
var xAxis2 = myChart.addMeasureAxis('x', 'index2');
xAxis2.title = null;
xAxis2.overrideMax = 1;
xAxis2.hidden = true;
var bars = myChart.addSeries('bars', dimple.plot.bar, [xAxis,yAxis]);
myChart.assignColor('bars', '#D3D3D3', '#D3D3D3');
var lines = myChart.addSeries('index2', dimple.plot.line, [xAxis2,yAxis]);
yAxis.addOrderRule('index1', false);
myChart.draw();
That data structure is not ideal for your data requirement within dimple. The way dimple would like that data is with your index names as dimension values:
var data = [
{ "Index" : "Index 1", "Country" : "UK", "Index Value": 0.2 },
{ "Index" : "Index 1", "Country" : "Spain", "Index Value": 0.7 },
{ "Index" : "Index 2", "Country" : "UK", "Index Value": 0.5 },
{ "Index" : "Index 2", "Country" : "Spain", "Index Value": 0.6 },
{ "Index" : "Index 3", "Country" : "UK", "Index Value": 0.4 },
{ "Index" : "Index 3", "Country" : "Spain", "Index Value": 0.3 },
...
];
Then in order to draw index 1 as a bar and the rest as lines you would need to split your data set into 2:
var barData = [],
lineData = [],
i,
keyIndex = "Index 1";
for (i = 0; i < data.length; i += 1) {
if (data[i]["Index"] === keyIndex) {
barData.push(data[i]);
} else {
lineData.push(data[i]);
}
}
You could then just define your chart as follows:
var chart = new dimple.chart(svg),
bars,
lines;
chart.addMeasureAxis("x", "Index Value");
chart.addCategoryAxis("y", "Country");
bars = chart.addSeries("Index", dimple.plot.bar);
bars.data = barData;
lines = chart.addSeries("Index", dimple.plot.line);
lines.data = lineData;
chart.draw();
I haven't tested this code but it ought to do what you want (minus the formatting etc).
If you want to continue on the road you have started in your code above (which is still possible) you will find composite axes very helpful to avoid hidden secondary axes and potential problems with differing max/min values. See the relevant section in the version 2 release notes for an example of these.
I don't understand why you don't want to tag the indices with something which appears in the tooltip, there must be some difference between them which you can communicate, but if you want to remove the index name from the tooltip you can define custom tooltips as shown here.
Edit: I should add if you just want to change the set of colours which dimple will arbitrarily ascribe to your data points you can override the default colours in the chart object as discussed here.