Increase separation of edges in graphviz - graphviz

I am creating several UML activity diagrams with dot-graphviz and the edges/arrows (2+) converge in the same point whenever the target shape is a narrowed rectangle (H=0.5, W=0.05). This problem doesn't occur if the target shape is a square (H=0.5, W=0.5).
Here is a reduced dot example:
digraph G {
graph [ ranksep = 0.5, rankdir = LR ]
A4 [ shape = "record", height = 0.5, fontsize = 10, margin = "0.20,0.05", label = "Output\ to\rPreviewer", style = "rounded" ]
A5 [ shape = "rectangle", height = 0.5, width = 0.05, margin = "0,0", style = "filled", label = "" ]
A4 -> A5 [ shape = "edge", dir = "both", style = "solid", arrowtail = "none", arrowhead = "vee", labeldistance = 1, fontsize = 10 ]
A6 [ shape = "diamond", height = 0.5, width = 0.5, margin = "0,0", label = "" ]
A6 -> A5 [ shape = "edge", dir = "both", style = "solid", arrowtail = "none", arrowhead = "vee", labeldistance = 1, fontsize = 10, label = "[generate: false]" ]
A7 [ shape = "record", height = 0.5, fontsize = 10, margin = "0.20,0.05", label = "Output\ to\rFile", style = "rounded" ]
A6 -> A7 [ shape = "edge", dir = "both", style = "solid", arrowtail = "none", arrowhead = "vee", labeldistance = 1, fontsize = 10, label = "[generate: true]" ]
A8 [ shape = "doublecircle", height = 0.3, width = 0.3, margin = "0,0", label = "" ]
A7 -> A5 [ shape = "edge", dir = "both", style = "solid", arrowtail = "none", arrowhead = "vee", labeldistance = 1, fontsize = 10 ]
A5 -> A8 [ shape = "edge", dir = "both", style = "solid", arrowtail = "none", arrowhead = "vee", labeldistance = 1, fontsize = 10 ]
}
The text above generates the following graph in http://webgraphviz.com
The desirable output is the following

I found a tweak that produces a nice output, but requires a lot of processing and edge-count and direction awareness:
digraph G {
graph [ ranksep = 0.5, rankdir = LR ]
A4 [ shape = "record", height = 0.5, fontsize = 10, margin = "0.20,0.05", label = "Output\ to\rPreviewer", style = "rounded" ]
A5 [ shape = "record", height = 0.5, width = 0.05, margin = "0,0", style = "filled", label = "<f0>|<f1>|<f2>", fillcolor="black" ]
A4 -> A5:f0:w [ shape = "edge", dir = "both", style = "solid", arrowtail = "none", arrowhead = "vee", labeldistance = 1, fontsize = 10 ]
A6 [ shape = "diamond", height = 0.5, width = 0.5, margin = "0,0", label = "" ]
A6 -> A5:f1:w [ shape = "edge", dir = "both", style = "solid", arrowtail = "none", arrowhead = "vee", labeldistance = 1, fontsize = 10, label = "[generate: false]" ]
A7 [ shape = "record", height = 0.5, fontsize = 10, margin = "0.20,0.05", label = "Output\ to\rFile", style = "rounded" ]
A6 -> A7 [ shape = "edge", dir = "both", style = "solid", arrowtail = "none", arrowhead = "vee", labeldistance = 1, fontsize = 10, label = "[generate: true]" ]
A8 [ shape = "doublecircle", height = 0.3, width = 0.3, margin = "0,0", label = "" ]
A7 -> A5:f2:w [ shape = "edge", dir = "both", style = "solid", arrowtail = "none", arrowhead = "vee", labeldistance = 1, fontsize = 10 ]
A5 -> A8 [ shape = "edge", dir = "both", style = "solid", arrowtail = "none", arrowhead = "vee", labeldistance = 1, fontsize = 10 ]
}
This is the output:
I still would like to know if there is a simpler solution.

You can specify the output port of all edges to east and get preaty nice result (at least for that case):
digraph G {
graph [ ranksep = 0.5, rankdir = LR ]
edge [tailport=e] # <----- added this line
A4 [ shape = "record", height = 0.5, fontsize = 10, margin = "0.20,0.05", label = "Output\ to\rPreviewer", style = "rounded" ]
A5 [ shape = "rectangle", height = 0.5, width = 0.05, margin = "0,0", style = "filled", label = "" ]
A4 -> A5 [ shape = "edge", dir = "both", style = "solid", arrowtail = "none", arrowhead = "vee", labeldistance = 1, fontsize = 10 ]
A6 [ shape = "diamond", height = 0.5, width = 0.5, margin = "0,0", label = "" ]
A6 -> A5 [ shape = "edge", dir = "both", style = "solid", arrowtail = "none", arrowhead = "vee", labeldistance = 1, fontsize = 10, label = "[generate: false]" ]
A7 [ shape = "record", height = 0.5, fontsize = 10, margin = "0.20,0.05", label = "Output\ to\rFile", style = "rounded" ]
A6 -> A7 [ shape = "edge", dir = "both", style = "solid", arrowtail = "none", arrowhead = "vee", labeldistance = 1, fontsize = 10, label = "[generate: true]" ]
A8 [ shape = "doublecircle", height = 0.3, width = 0.3, margin = "0,0", label = "" ]
A7 -> A5 [ shape = "edge", dir = "both", style = "solid", arrowtail = "none", arrowhead = "vee", labeldistance = 1, fontsize = 10 ]
A5 -> A8 [ shape = "edge", dir = "both", style = "solid", arrowtail = "none", arrowhead = "vee", labeldistance = 1, fontsize = 10 ]
}
produce:

Related

amCharts - XY Charts Tooltip and Bullet

I have an XY Charts in amCharts 4 and I can't set the correct parameter to insert in the tooltip. This is the code that design the chart:
Is possible to show the parameter "desc" in the tooltip?
var chart = am4core.create("chartdiv", am4charts.XYChart);
// Add data
chart.data = [ {
"x": -6,
"y": 0,
"diam": 4,
"desc": "test"
}, {
"x": 0,
"y": -10,
"diam": 4,
"desc": "test"
}, {
"x": 12,
"y": 10,
"diam": 8,
"desc": "special"
} ];
// Create axes
var xAxis = chart.xAxes.push(new am4charts.ValueAxis());
var yAxis = chart.yAxes.push(new am4charts.ValueAxis());
// Create series
var series = chart.series.push(new am4charts.LineSeries());
series.dataFields.valueX = "x";
series.dataFields.valueY = "y";
series.strokeWidth = 2;
series.fillOpacity = 0;
series.stroke = "red";
// Create bullet and tooltip
seriesBullet = series.bullets.push(new am4charts.CircleBullet());
seriesBullet.circle.fill = am4core.color("#fff");
seriesBullet.circle.strokeWidth = 3;
seriesBullet.circle.propertyFields.radius = "diam";
seriesBullet.tooltipText = "desc";
#chartdiv {
width: 100%;
height: 200px;
}
<script src="https://www.amcharts.com/lib/4/core.js"></script>
<script src="https://www.amcharts.com/lib/4/charts.js"></script>
<div id="chartdiv"></div>
You need to wrap the desc in curly braces: {desc}
seriesBullet.tooltipText = "{desc}";
Here is your updated working example:
var chart = am4core.create("chartdiv", am4charts.XYChart);
// Add data
chart.data = [ {
"x": -6,
"y": 0,
"diam": 4,
"desc": "test"
}, {
"x": 0,
"y": -10,
"diam": 4,
"desc": "test"
}, {
"x": 12,
"y": 10,
"diam": 8,
"desc": "special"
} ];
// Create axes
var xAxis = chart.xAxes.push(new am4charts.ValueAxis());
var yAxis = chart.yAxes.push(new am4charts.ValueAxis());
// Create series
var series = chart.series.push(new am4charts.LineSeries());
series.dataFields.valueX = "x";
series.dataFields.valueY = "y";
series.strokeWidth = 2;
series.fillOpacity = 0;
series.stroke = "red";
series.tooltipText = "{desc}";
// Create bullet and tooltip
seriesBullet = series.bullets.push(new am4charts.CircleBullet());
seriesBullet.circle.fill = am4core.color("#fff");
seriesBullet.circle.strokeWidth = 3;
seriesBullet.circle.propertyFields.radius = "diam";
seriesBullet.tooltipText = "{desc}";
#chartdiv {
width: 100%;
height: 200px;
}
<script src="https://www.amcharts.com/lib/4/core.js"></script>
<script src="https://www.amcharts.com/lib/4/charts.js"></script>
<div id="chartdiv"></div>
You need to put your parameter inside a {} curly braces.
E.g :
seriesBullet.tooltipText = "{desc}";

Possible custom axis scale?

Is it possible to set my own scale for numerical results?
I need to set the scales with these values 10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000
AmCharts v4 doesn't provide a way to directly influence the scale outside of setting minGridDistance on the axis. A workaround for this is to disable the axis' own generated labels and create your own using axis ranges. You'll also want to set your own min/max values on the axis.
var valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
valueAxis.renderer.labels.template.disabled = true;
valueAxis.renderer.grid.template.disabled = true;
valueAxis.min = <your min value>;
range = valueAxis.axisRanges.create();
range.value = <axis value>;
range.endValue = range.value;
range.label.text = range.value;
// ... repeat for each axis increment
valueAxis.max = <your max value>;
Here's a basic demo:
// Create chart instance
var chart = am4core.create("chartdiv", am4charts.XYChart);
// Add data
chart.data = [{
"date": new Date(2018, 0, 1),
"value": 450,
"value2": 362,
"value3": 699
}, {
"date": new Date(2018, 0, 2),
"value": 269,
"value2": 450,
"value3": 841
}, {
"date": new Date(2018, 0, 3),
"value": 700,
"value2": 358,
"value3": 699
}, {
"date": new Date(2018, 0, 4),
"value": 490,
"value2": 367,
"value3": 500
}, {
"date": new Date(2018, 0, 5),
"value": 500,
"value2": 485,
"value3": 369
}, {
"date": new Date(2018, 0, 6),
"value": 550,
"value2": 354,
"value3": 250
}, {
"date": new Date(2018, 0, 7),
"value": 420,
"value2": 350,
"value3": 600
}];
// Create axes
var categoryAxis = chart.xAxes.push(new am4charts.DateAxis());
categoryAxis.renderer.grid.template.location = 0;
var valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
valueAxis.renderer.labels.template.disabled = true;
valueAxis.renderer.grid.template.disabled = true;
valueAxis.min = 0;
var rangeValue = 50;
for (var i = 0; i < 8; ++i) {
range = valueAxis.axisRanges.create();
range.value = (rangeValue += ((i + 2) * 25));
range.endValue = range.value;
range.label.text = range.value;
}
valueAxis.max = rangeValue;
// Create series
function createSeries(field, name) {
var series = chart.series.push(new am4charts.LineSeries());
series.dataFields.valueY = field;
series.dataFields.dateX = "date";
series.name = name;
series.tooltipText = "{dateX}: [b]{valueY}[/]";
series.strokeWidth = 2;
var bullet = series.bullets.push(new am4charts.CircleBullet());
bullet.circle.stroke = am4core.color("#fff");
bullet.circle.strokeWidth = 2;
}
createSeries("value", "Series #1");
createSeries("value2", "Series #2");
createSeries("value3", "Series #3");
chart.legend = new am4charts.Legend();
chart.cursor = new am4charts.XYCursor();
<script src="https://www.amcharts.com/lib/4/core.js"></script>
<script src="https://www.amcharts.com/lib/4/charts.js"></script>
<div id="chartdiv" style="width:100%; height: 500px;"></div>

How to include custom value in amcharts series for calculation

How do we include the new custom variable to define the bullet location based on avgTime in chart.data
We are unable to assign the avgTime to openBullet.locationX = avgTime; like this.
If i add the avgTime to locationX it is throwing the error like avgTime is not defined.
Find the below code for your reference
// Themes begin
am4core.useTheme(am4themes_animated);
// Themes end
var chart = am4core.create("chartdiv", am4charts.XYChart);
chart.data = [{
"name": "John",
"startTime": 8,
"endTime": 11,
"avgTime": 0.5,
"color": chart.colors.next()
}, {
"name": "Joe",
"startTime": 10,
"endTime": 13,
"avgTime": 0.8,
"color": chart.colors.next()
}, {
"name": "Susan",
"startTime": 11,
"endTime": 18,
"avgTime": 0.1,
"color": chart.colors.next()
}, {
"name": "Eaton",
"startTime": 15,
"endTime": 19,
"avgTime": 0,
"color": chart.colors.next()
}];
var categoryAxis = chart.yAxes.push(new am4charts.CategoryAxis());
categoryAxis.dataFields.category = "name";
categoryAxis.renderer.inversed = true;
categoryAxis.renderer.grid.template.location = 0;
var valueAxis = chart.xAxes.push(new am4charts.ValueAxis());
//valueAxis.renderer.minGridDistance = 50;
var columnSeries = chart.series.push(new am4charts.ColumnSeries());
columnSeries.dataFields.categoryY = "name";
columnSeries.dataFields.valueX = "endTime";
columnSeries.dataFields.openValueX = "startTime";
columnSeries.columns.template.tooltipText = "[bold]{categoryY}[/]\nstarts at {openValueX}\nends at {valueX}";
var columnTemplate = columnSeries.columns.template;
columnTemplate.strokeOpacity = 0;
columnTemplate.propertyFields.fill = "color";
//columnTemplate.height = am4core.percent(100);
//var openBullet = columnSeries.bullets.create(am4charts.CircleBullet);
//openBullet.locationX = avgTime;
var circleBullet = columnSeries.bullets.push(new am4charts.CircleBullet());
circleBullet.circle.stroke = am4core.color("#fff");
circleBullet.circle.strokeWidth = 2;
circleBullet.locationX = /**
* ---------------------------------------
* This demo was created using amCharts 4.
*
* For more information visit:
* https://www.amcharts.com/
*
* Documentation is available at:
* https://www.amcharts.com/docs/v4/
* ---------------------------------------
*/
// Themes begin
am4core.useTheme(am4themes_animated);
// Themes end
var chart = am4core.create("chartdiv", am4charts.XYChart);
chart.data = [{
"name": "John",
"startTime": 8,
"endTime": 11,
"avgTime": 0.5,
"color": chart.colors.next()
}, {
"name": "Joe",
"startTime": 10,
"endTime": 13,
"avgTime": 0.8,
"color": chart.colors.next()
}, {
"name": "Susan",
"startTime": 11,
"endTime": 18,
"avgTime": 0.1,
"color": chart.colors.next()
}, {
"name": "Eaton",
"startTime": 15,
"endTime": 19,
"avgTime": 0,
"color": chart.colors.next()
}];
var categoryAxis = chart.yAxes.push(new am4charts.CategoryAxis());
categoryAxis.dataFields.category = "name";
categoryAxis.renderer.inversed = true;
categoryAxis.renderer.grid.template.location = 0;
var valueAxis = chart.xAxes.push(new am4charts.ValueAxis());
//valueAxis.renderer.minGridDistance = 50;
var columnSeries = chart.series.push(new am4charts.ColumnSeries());
columnSeries.dataFields.categoryY = "name";
columnSeries.dataFields.valueX = "endTime";
columnSeries.dataFields.openValueX = "startTime";
columnSeries.columns.template.tooltipText = "[bold]{categoryY}[/]\nstarts at {openValueX}\nends at {valueX}";
var columnTemplate = columnSeries.columns.template;
columnTemplate.strokeOpacity = 0;
columnTemplate.propertyFields.fill = "color";
//columnTemplate.height = am4core.percent(100);
//var openBullet = columnSeries.bullets.create(am4charts.CircleBullet);
//openBullet.locationX = avgTime;
var circleBullet = columnSeries.bullets.push(new am4charts.CircleBullet());
circleBullet.circle.stroke = am4core.color("#fff");
circleBullet.circle.strokeWidth = 2;
circleBullet.locationX = {avgTime};
var labelBullet = columnSeries.bullets.push(new am4charts.LabelBullet());
labelBullet.label.text = "{avgTime}";
labelBullet.label.dx = +20;
labelBullet.locationX = 0.2;;
var labelBullet = columnSeries.bullets.push(new am4charts.LabelBullet());
labelBullet.label.text = "{avgTime}";
labelBullet.label.dx = +20;
labelBullet.locationX = 0.2;
I'm not quite sure if I understood your question correctly. To set the position of the bullets you have to set the value in the propertyFields accounding to the name of the value in your data:
circleBullet.propertyFields.locationX = "avgTime";
I created a code pen with your example code. Hope that helps.
EDIT: According to the response from zeroin you should consider to change your avgTime to 1 - avgTime, because it is rendered beginning at the end of the column.

Highlighting the highest and lowest point in amcharts

Could someone help me on changing the bullet or highlighting the highest and lowest values using amcharts?.
I am using serial chart. The condition given in the function "highlight" is matching , however the the bullets are not highlighted to the highest and lowest points..
Any help will be appreciated.
Please find my code below.
<link rel="stylesheet" href="style.css" type="text/css">
<script src="amcharts/amcharts.js" type="text/javascript"></script>
<script src="amcharts/serial.js" type="text/javascript"></script>
<script>
var chart;
var chartData = [
{"date": "2006", "value": 63, "value1": 87},
{"date": "2007", "value": 64, "value1": 63},
{"date": "2008", "value": 66, "value1": 75},
{"date": "2009", "value": 70, "value1": 51},
{"date": "2010", "value": 63, "value1": 79},
{"date": "2011", "value": 64, "value1": 65},
{"date": "2012", "value": 56, "value1": 52},
{"date": "2013", "value": 60, "value1": 88},
{"date": "2014", "value": 56, "value1": 90},
{"date": "2015", "value": 68, "value1": 83},
{"date": "2016", "value": 68, "value1": 63},
{"date": "2017", "value": 69, "value1": 74},
{"date": "2018", "value": 70, "value1": 68},
{"date": "2019", "value": 55, "value1": 65}, ];
AmCharts.ready(function () {
// SERIAL CHART
chart = new AmCharts.AmSerialChart();
chart.dataProvider = chartData;
chart.dataDateFormat = "YYYY";
chart.categoryField = "date";
chart.addTitle("Graph Chart-Connects/ Disconnects");
chart.addListener("rendered", highlight);
// AXES
// category
var categoryAxis = chart.categoryAxis;
categoryAxis.parseDates = true; // as our data is date-based, we set parseDates to true
categoryAxis.minPeriod = "YYYY"; // our data is daily, so we set minPeriod to DD
categoryAxis.gridAlpha = 0.1;
categoryAxis.minorGridAlpha = 0.1;
categoryAxis.axisAlpha = 0;
categoryAxis.minorGridEnabled = true;
categoryAxis.inside = true;
// value
var valueAxis = new AmCharts.ValueAxis();
valueAxis.tickLength = 0;
valueAxis.axisAlpha = 0;
valueAxis.showFirstLabel = false;
valueAxis.showLastLabel = false;
chart.addValueAxis(valueAxis);
// GRAPH
var graph = new AmCharts.AmGraph();
graph.title = "Connects";
graph.dashLength = 3;
graph.lineColor = "#00CC00";
graph.valueField = "value";
graph.bullet = "round";
graph.balloonText = "[[category]]<br><b><span style='font-size:14px;'>Connects:[[value]]</span></b>";
chart.addGraph(graph);
// GRAPH
var graph1 = new AmCharts.AmGraph();
graph1.title = "Disconnects";
graph1.dashLength = 3;
graph1.lineColor = "#EF9B0F";
graph1.valueField = "value1";
graph1.bullet = "square";
graph1.balloonText = "[[category]]<br><b><span style='font-size:14px;'>Disconnects:[[value1]]</span></b>";
graph1.fillToGraph = graph;
chart.addGraph(graph1);
// CURSOR
var chartCursor = new AmCharts.ChartCursor();
chartCursor.valueLineEnabled = true;
chartCursor.valueLineBalloonEnabled = true;
chart.addChartCursor(chartCursor);
// SCROLLBAR
var chartScrollbar = new AmCharts.ChartScrollbar();
chart.addChartScrollbar(chartScrollbar);
// HORIZONTAL GREEN RANGE
var guide = new AmCharts.Guide();
guide.value = 10;
guide.toValue = 20;
guide.fillColor = "#00CC00";
guide.inside = true;
guide.fillAlpha = 0.2;
guide.lineAlpha = 0;
valueAxis.addGuide(guide);
var legend = new AmCharts.AmLegend();
legend.marginLeft = 110;
// legend.data = [{markerType:"round",title:"Connects",color:"#EF9B0F"}, {markerType:"square",title:"Disconnects",color:"#00CC00"}]
chart.addLegend(legend);
// WRITE
chart.write("chartdiv");
});
function highlight(event) {
// get chart and value axis
var chart = event.chart;
var axis = chart.valueAxes[0];
var graph = chart.graphs[1];
if (chart.minMaxMarked)
return;
// find data points with highest and biggest values
for (var i = 0; i < chart.dataProvider.length; i++) {
var dp = chart.dataProvider[i];
console.log(dp[graph.valueField] + "<=>" + axis.maxReal);
//alert(axis.minReal);
if (dp[graph.valueField] == axis.maxReal) {
alert('test');
dp.markerType = "bubble";
dp.bulletSize = 8;
//dp.
}
else if (dp[graph.valueField] == axis.minReal) {
// alert('test');
dp.markerType = "bubble";
dp.bulletSize = 8;
}
}
// set flag that we're done already
chart.minMaxMarked = true;
// take in updated data
chart.validateData();
}
</script>
You are correctly setting the size/type parameters for high/low data points in data.
However, your graphs are not set up to use those fields.
To make the graph look for bullet type in data use its bulletField property. For bullet size: bulletSizeField:
graph.bulletSizeField = "bulletSize";
graph.bulletField = "markerType";
// ...
graph1.bulletSizeField = "bulletSize";
graph1.bulletField = "markerType";
Solution posted martynasm !!! Thanks.
var chart;
var chartData = [
{"date": "2006", "value": 67, "value1": 83},
{"date": "2007", "value": 70, "value1": 90},
{"date": "2008", "value": 66, "value1": 56},
{"date": "2009", "value": 65, "value1": 50},
{"date": "2010", "value": 55, "value1": 90},
{"date": "2011", "value": 60, "value1": 89},
{"date": "2012", "value": 60, "value1": 52},
{"date": "2013", "value": 61, "value1": 63},
{"date": "2014", "value": 65, "value1": 74},
{"date": "2015", "value": 64, "value1": 53},
{"date": "2016", "value": 66, "value1": 61},
{"date": "2017", "value": 60, "value1": 76},
{"date": "2018", "value": 62, "value1": 65},
{"date": "2019", "value": 61, "value1": 51},
];
AmCharts.ready(function () {
// SERIAL CHART
chart = new AmCharts.AmSerialChart();
chart.dataProvider = chartData;
chart.dataDateFormat = "YYYY";
chart.categoryField = "date";
chart.addTitle("Graph Chart-Connects/ Disconnects");
chart.addListener("rendered", highlightY1);
chart.addListener("rendered", highlightY2);
// AXES
// category
var categoryAxis = chart.categoryAxis;
categoryAxis.parseDates = true; // as our data is date-based, we set parseDates to true
categoryAxis.minPeriod = "YYYY"; // our data is daily, so we set minPeriod to DD
categoryAxis.gridAlpha = 0.1;
categoryAxis.minorGridAlpha = 0.1;
categoryAxis.axisAlpha = 0;
categoryAxis.minorGridEnabled = true;
categoryAxis.inside = true;
// value
var valueAxis = new AmCharts.ValueAxis();
valueAxis.tickLength = 0;
valueAxis.axisAlpha = 0;
valueAxis.showFirstLabel = false;
valueAxis.showLastLabel = false;
chart.addValueAxis(valueAxis);
// GRAPH
var graph = new AmCharts.AmGraph();
graph.title = "Connects";
graph.dashLength = 3;
graph.lineColor = "#00CC00";
graph.valueField = "value";
graph.bullet = "round";
//graph.bulletSizeField = "30";
// graph.bulletField = "value";
graph.balloonText = "[[category]]<br><b><span style='font-size:14px;'>Connects:[[value]]</span></b>";
chart.addGraph(graph);
// GRAPH
var graph1 = new AmCharts.AmGraph();
graph1.title = "Disconnects";
graph1.dashLength = 3;
graph1.lineColor = "#EF9B0F";
graph1.valueField = "value1";
graph1.bullet = "square";
//graph1.bulletSizeField = "30";
// graph1.bulletField = "bullet";
graph1.balloonText = "[[category]]<br><b><span style='font-size:14px;'>Disconnects:[[value1]]</span></b>";
graph1.fillToGraph = graph;
chart.addGraph(graph1);
// CURSOR
var chartCursor = new AmCharts.ChartCursor();
chartCursor.valueLineEnabled = true;
chartCursor.valueLineBalloonEnabled = true;
chart.addChartCursor(chartCursor);
// SCROLLBAR
var chartScrollbar = new AmCharts.ChartScrollbar();
chart.addChartScrollbar(chartScrollbar);
// HORIZONTAL GREEN RANGE
var guide = new AmCharts.Guide();
guide.value = 10;
guide.toValue = 20;
guide.fillColor = "#00CC00";
guide.inside = true;
guide.fillAlpha = 0.2;
guide.lineAlpha = 0;
valueAxis.addGuide(guide);
var legend = new AmCharts.AmLegend();
legend.marginLeft = 110;
// legend.data = [{markerType:"round",title:"Connects",color:"#EF9B0F"}, {markerType:"square",title:"Disconnects",color:"#00CC00"}]
chart.addLegend(legend);
// WRITE
chart.write("chartdiv");
});
function highlightY1(event) {
// get chart and value axis
var chart = event.chart;
// var axis = chart.valueAxes[0];
var graph = chart.graphs[0];
graph.bulletSizeField = "bulletSize1";
graph.bulletField = "markerType1";
if (chart.minMaxMarked)
return;
var connectsValue = new Array();
for (var i = 0; i < chart.dataProvider.length; i++) {
connectsValue[i] = chart.dataProvider[i][graph.valueField];
}
connectsValue.sort();
// find data points with highest and biggest values
connectsMax = parseInt(connectsValue[connectsValue.length - 1]);
connectsMin = parseInt(connectsValue[0]);
for (var i = 0; i < chart.dataProvider.length; i++) {
var dp = chart.dataProvider[i];
if (dp[graph.valueField] == connectsMax) {
console.log(dp[graph.valueField] + "<=>" + connectsMax);
dp.markerType1 = "triangleUp";
dp.bulletSize1 = 18;
}
if (dp[graph.valueField] == connectsMin) {
// alert('test');
console.log(dp[graph.valueField] + "<=>" + connectsMin);
dp.markerType1 = "triangleDown";
dp.bulletSize1 = 18;
}
}
// set flag that we're done already
//chart.minMaxMarked = true;
// take in updated data
// chart.validateData();
}
function highlightY2(event) {
// get chart and value axis
var chart = event.chart;
// var axis = chart.valueAxes[0];
var graph1 = chart.graphs[1];
graph1.bulletSizeField = "bulletSize2";
graph1.bulletField = "markerType2";
if (chart.minMaxMarked)
return;
var disconnectsValue = new Array();
for (var i = 0; i < chart.dataProvider.length; i++) {
disconnectsValue[i] = chart.dataProvider[i][graph1.valueField];
}
disconnectsValue.sort();
// find data points with highest and biggest values
disconnectsMax = parseInt(disconnectsValue[disconnectsValue.length - 1]);
disconnectsMin = parseInt(disconnectsValue[0]);
for (var i = 0; i < chart.dataProvider.length; i++) {
var dp = chart.dataProvider[i];
if (dp[graph1.valueField] == disconnectsMax) {
console.log(dp[graph1.valueField] + "<=>" + disconnectsMax);
dp.markerType2 = "triangleUp";
dp.bulletSize2 = 18;
}
if (dp[graph1.valueField] == disconnectsMin) {
// alert('test');
console.log(dp[graph1.valueField] + "<=>" + disconnectsMin);
dp.markerType2 = "triangleDown";
dp.bulletSize2 = 18;
}
}
// set flag that we're done already
chart.minMaxMarked = true;
// take in updated data
chart.validateData();
}
html, body {
width: 100%;
height: 100%;
margin: 0px;
}
#chartdiv {
width: 100%;
height: 100%;
}
<script src="//www.amcharts.com/lib/3/amcharts.js"></script>
<script src="//www.amcharts.com/lib/3/serial.js"></script>
<script src="//www.amcharts.com/lib/3/themes/light.js"></script>
<div id="chartdiv"></div>

How I can draw the tree with values stored in nodes with graphviz?

I need to draw tree looks like this (with values associated with some nodes):
But I find only the way to draw tree like next:
I try to use subgraphs, and nested subgraphs, but there is no effect needed. Currently, I use the next gv script:
digraph "test-graph" {
graph [rankdir=TB dpi=96]
subgraph n0 {
rank=same;
"0_0" [ label = "a" ];
}
subgraph n1 {
rank=same;
"1_0" [ label = "b" ];
"1_1" [ label = "d" ];
"1_2" [ label = "e" ];
subgraph {
"v3" [ label = "3", shape = "box" ];
"1_1"->"v3" [ dir = none, constraint = false ];
}
}
subgraph n2 {
rank=same;
"2_0" [ label = "g" ];
}
subgraph n3 {
rank=same;
"3_0" [ label = "a" ];
"3_1" [ label = "b" ];
"3_2" [ label = "c" ];
subgraph {
"v2" [ label = "2", shape = "box" ];
"3_0"->"v2" [ dir = none, constraint = false ];
"v0" [ label = "0", shape = "box" ];
"3_1"->"v0" [ dir = none, constraint = false ];
"v5" [ label = "5", shape = "box" ];
"3_2"->"v5" [ dir = none, constraint = false ];
}
}
subgraph n4 {
rank=same;
"4_0" [ label = "f" ];
subgraph {
"v1" [ label = "1", shape = "box" ];
"4_0"->"v1" [ dir = none, constraint = false ];
}
}
subgraph n5 {
rank=same;
"5_0" [ label = "c" ];
subgraph {
"v4" [ label = "4", shape = "box" ];
"5_0"->"v4" [ dir = none, constraint = false ];
}
}
"start"->"0_0";
"0_0"->"1_0";
"0_0"->"1_1";
"0_0"->"1_2";
"1_0"->"5_0";
"1_1"->"2_0";
"1_2"->"4_0";
"2_0"->"3_0";
"2_0"->"3_1";
"2_0"->"3_2";
}
Using "cluster_" prefix solves some of problems (thanks Anne), but there is important in wich order nodes and it's values folows in the dot script.
After all I got new problem - nodes not properly ordered on graph: a, b, c nodes (node 'g' childs) follows in wrong order:
Also, is there a way to tell dot place values at right side from nodes? The best, of course, is then the values are placed under nodes, but, how I can find, this is unsolvable problem.
Dot script is:
digraph "test-graph" {
graph [rankdir=TB dpi=96]
subgraph cluster_n0 {
rank=same;
style=invis;
"0_0" [ label = "a" ];
}
subgraph cluster_n1 {
rank=same;
style=invis;
"1_0" [ label = "b" ];
"1_1" [ label = "d" ];
"v3" [ label = "3", shape = "box", width=.01, height=.01 ];
"1_1"->"v3" [ dir = none, constraint = false ];
"1_2" [ label = "e" ];
}
subgraph cluster_n2 {
rank=same;
style=invis;
"2_0" [ label = "g" ];
}
subgraph cluster_n3 {
rank=same;
style=invis;
"3_0" [ label = "a" ];
"v2" [ label = "2", shape = "box", width=.01, height=.01 ];
"3_0"->"v2" [ dir = none, constraint = false ];
"3_1" [ label = "b" ];
"v0" [ label = "0", shape = "box", width=.01, height=.01 ];
"3_1"->"v0" [ dir = none, constraint = false ];
"3_2" [ label = "c" ];
"v5" [ label = "5", shape = "box", width=.01, height=.01 ];
"3_2"->"v5" [ dir = none, constraint = false ];
}
subgraph cluster_n4 {
rank=same;
style=invis;
"4_0" [ label = "f" ];
"v1" [ label = "1", shape = "box", width=.01, height=.01 ];
"4_0"->"v1" [ dir = none, constraint = false ];
}
subgraph cluster_n5 {
rank=same;
style=invis;
"5_0" [ label = "c" ];
"v4" [ label = "4", shape = "box", width=.01, height=.01 ];
"5_0"->"v4" [ dir = none, constraint = false ];
}
"start"->"0_0";
"0_0"->"1_0";
"0_0"->"1_1";
"0_0"->"1_2";
"1_0"->"5_0";
"1_1"->"2_0";
"1_2"->"4_0";
"2_0"->"3_0";
"2_0"->"3_1";
"2_0"->"3_2";
}
To group the "value" node with the node, you have to use subgraphs with a name starting by cluster_. For instance:
subgraph cluster_n4_0 {
rank=same;
"4_0" [ label = "f" ];
"v1" [ label = "1", shape = "box" ];
"4_0"->"v1" [ dir = none];
}
To have smaller nodes for the values, you can use the width and height attributes.
I don't think that you need several level of subgraphs here, using clusters for pairs of node should be enougt.
add an invisiable edge from box to next level node, like following example
digraph "test-graph" {
graph [rankdir=TB,dpi=96,splines=false]
"1_1" [ label = "d" ];
"v3" [ label = "3", shape = "box", width = 0, height = 0];
"2_0" [ label = "g" ];
"1_1"->"v3" [ dir = none];
v3->"2_0"[style=invisible,dir = none];
"1_1"->"2_0";
}

Resources