I m using zedGraph dll to save image of my graphs using points. Now I need to save a graphs with 1-X Axis and 3-Y axis. Also with 3-X axis and 1-Yaxis. Please help me out.
For the Y axis, this issue is fairly simple. Just add a sufficient number of YAxis objects to the GraphPane.YAxisList and associate the curves with respective axis by setting the YAxisIndex.
After adding all curves to the graph, update the scales of the Y axes by calling GraphPane.AxisChange().
Example:
var pane = zedGraphControl1.GraphPane;
pane.YAxisList.Clear();
var y1 = pane.AddYAxis("First");
var y2 = pane.AddYAxis("Secnd");
var y3 = pane.AddYAxis("Third");
var curve1 = new LineItem(null, new[] { 0.1, 0.5, 0.9 },
new[] { 0.8, 0.3, 0.1 }, Color.Blue, SymbolType.None) { YAxisIndex = y1 };
pane.CurveList.Add(curve1);
var curve2 = new LineItem(null, new[] { 0.1, 0.5, 0.9 },
new[] { -0.8, -0.3, -0.1 }, Color.Green, SymbolType.None) { YAxisIndex = y2 };
pane.CurveList.Add(curve2);
var curve3 = new LineItem(null, new[] { 0.1, 0.5, 0.9 },
new[] { -0.009, 0.001, 0.008 }, Color.Red, SymbolType.None) { YAxisIndex = y3 };
pane.CurveList.Add(curve3);
pane.AxisChange();
will produce the following result:
For X axes, you would be able to have 2 different X axes by utilizing both the XAxis and X2Axis properties of the graph pane, and setting the IsX2Axis property to true for the curve that should reference the second X axis.
I do not know of a solution for more than 2 X axes, though.
Related
Need help with D3.js I have a half-donut component which receives 2 values a value variable and a threshold variable I need to place a cutting arc on the half donut based on the threshold value which is between 0 and 1 where 1 is 100%.
The half-donut component what I have .
The dashed line I need is above.
The code below will do this. Later I will add the link to the tutorial.
import * as d3 from 'd3';
import { attrs } from 'd3-selection-multi'
let btn = d3.select('body').append('button').text('Change data')
.style('margin-bottom', '10px')
let dim = { 'width': 700, 'height': 400 }
let svg = d3.select('body').append('svg').attrs(dim)
.style('border', '1px solid black')
let g = svg.append('g').attr('transform', 'translate(350, 370)')
let arcGen = d3.arc()
arcGen.innerRadius(250).outerRadius(340)
let pth = arcGen({
startAngle: -Math.PI / 2,
endAngle: Math.PI / 2
})
let scale = d3.scaleLinear([0, 1], [-Math.PI / 2, Math.PI / 2])
let data = [Math.random(), Math.random()]
g.append('path').attrs({
'd': pth,
'fill': 'lightgray',
'stroke': 'black'
})
svg.append('clipPath').attr('id', 'mask')
.append('path').attr('d', pth)
let valuePth = arcGen({
startAngle: -Math.PI / 2,
endAngle: scale(data[0])
})
let value = g.append('path').attrs({
'd': valuePth,
'fill': data[0] < data[1]? 'aquamarine': 'lightcoral',
'stroke': 'black'
})
// target line
let pts = d3.pointRadial(scale(data[1]), 0).concat(d3.pointRadial(scale(data[1]), 1000))
let target = g.append('line').attrs({
'x1': pts[0], 'y1': pts[1], 'x2': pts[2], 'y2': pts[3],
'stroke': 'midnightblue',
'stroke-width': 4,
'stroke-dasharray': '6, 3',
'clip-path': 'url(#mask)'
})
btn.on('click', ()=>{
let oldAngle = scale(data[0])
data = [Math.random(), Math.random()]
pts = d3.pointRadial(scale(data[1]), 0).concat(d3.pointRadial(scale(data[1]), 1000))
value.transition().duration(2000).attrTween('d', ()=>{
let start = {startAngle: -Math.PI / 2, endAngle: oldAngle}
let interpolate = d3.interpolate(start, {startAngle: -Math.PI / 2, endAngle: scale(data[0])})
return (t)=>arcGen(interpolate(t))
}).attr('fill', data[0] < data[1]? 'aquamarine': 'lightcoral')
target.transition().duration(2000).attrs({
'x1': pts[0], 'y1': pts[1], 'x2': pts[2], 'y2': pts[3]
})
})
I am using the chart library MPAndroidChart in Kotlin
Everything is working correctly, `but I have a problem with the axis scales. In my graph my maximum values are as follows:
X axis: 1947.7872f
Y axis: 861.5f
But when the graph is made the X axis should be larger than the Y axis, but in my graph it almost shows the same. I need the axes to have the scale respecting the real numerical values of both.
My code to make the graph is the following:
private fun setupLineChartData() {
val yVals = ArrayList<Entry>()
yVals.add(Entry(0f, 241.5f, "0"))
yVals.add(Entry(162.3156f, 323.9f, "1"))
yVals.add(Entry(324.6312f, 529.6f, "2"))
yVals.add(Entry(486.9468f, 738.2f, "3"))
yVals.add(Entry(649.2624f, 839.6f, "4"))
yVals.add(Entry(811.578f, 860.8f, "5"))
yVals.add(Entry(973.8936f, 861.5f, "6"))
yVals.add(Entry(1136.2092f, 860.8f, "7"))
yVals.add(Entry(1298.5248f, 839.6f, "8"))
yVals.add(Entry(1460.8404f, 738.2f, "9"))
yVals.add(Entry(1623.156f, 529.6f, "10"))
yVals.add(Entry(1785.4716f, 323.9f, "11"))
yVals.add(Entry(1947.7872f, 241.5f, "12"))
val set1: LineDataSet
set1 = LineDataSet(yVals, "DataSet 1")
set1.color = Color.BLUE
set1.setCircleColor(Color.BLUE)
set1.lineWidth = 1f
set1.circleRadius = 3f
set1.setDrawCircleHole(true)
set1.valueTextSize = 0f
set1.setDrawFilled(true)
val dataSets = ArrayList<ILineDataSet>()
dataSets.add(set1)
val data = LineData(dataSets)
// set data
lineChart.data = data
lineChart.description.isEnabled = false
lineChart.legend.isEnabled = false
lineChart.setPinchZoom(true)
lineChart.xAxis.setLabelCount(13, true)
lineChart.xAxis.labelRotationAngle = -90f
val minXRange = 0f
val maxXRange = 1947.7872f
lineChart.setVisibleXRange(minXRange, maxXRange)
lineChart.xAxis.position = XAxis.XAxisPosition.BOTTOM
}
I tried with lineChart.setScaleMinima (1f, 1f) but it doesn't work.
For more details see image:
I am trying to make a simple project to find coefficients of an equation using a tensorflow.js model. however, when ran, the loss approaches infinity and becomes NaN withing 4 or so iterations. I don't know why this is happening. Here is my code:
let xs = [];
let ys = [];
let aReal = Math.random();
let bReal = Math.random();
let cReal = Math.random();
let dReal = Math.random();
for (let i = -100; i < 100; i+=1) {
xs.push(i);
ys.push((aReal*Math.pow(i, 3) + bReal*Math.pow(i, 2) + cReal*i + dReal) + Math.random()*10-1);
}
const a = tf.variable(tf.scalar(Math.random()));
const b = tf.variable(tf.scalar(Math.random()));
const c = tf.variable(tf.scalar(Math.random()));
const d = tf.variable(tf.scalar(Math.random()));
function predict(x) {
return tf.tidy(() => {
return a.mul(x.pow(tf.scalar(3, 'int32')))
.add(b.mul(x.square()))
.add(c.mul(x))
.add(d);
});
}
function loss(predictions, labels) {
const meanSquareError = predictions.sub(labels).square().mean();
print(meanSquareError.dataSync());
return meanSquareError;
}
function train(xS, yS, numIterations) {
const learningRate = 0.1;
const optimizer = tf.train.sgd(learningRate);
console.log(xS.dataSync(), yS.dataSync());
for (let iter = 0; iter < numIterations; iter++) {
optimizer.minimize(() => {
const predYs = predict(xS);
return loss(predYs, yS);
});
}
}
train(tf.tensor(xs), tf.tensor(ys), 100);
let yPred = predict(tf.tensor(xs)).dataSync();
console.log(yPred);
let trace1 = {
x: xs,
y: ys,
mode: 'markers',
type: 'scatter'
};
let trace2 = {
x: xs,
y: yPred,
mode: 'lines',
};
console.log(aReal, bReal, cReal, dReal);
console.log(a.dataSync(), b.dataSync(), c.dataSync(), d.dataSync());
let graphData = [trace1, trace2];
Plotly.newPlot('graph', graphData);
Plotly is just a js library I'm using to plot the data.
Try lowering your learning rate. Once it's stable you can tweak it back up to speed training. If it's too high you'll get instability and NaNs
const learningRate = 0.0001;
You should try to normalize your input data for the prediction to work correctly. Otherwise the optimization becomes numerically unstable.
ys = [...];
// compute mean and stdev for ys!
normalized = (ys-ysmean)/(ysstd);
train(xs, normalized);
normed_pred = predict(xs);
pred = ysstd*normed_pred+ysmean;
In the tests I ran, your code works perfect on linear models y=ax+b; therefore my conclusion.
The loss depends on the values you start with, so if they are too big the loss may jump to the infinite and the prediction will return NaN. Try normalizing them so that they scale between 1 and -1. For instance when you train on MNIST, you divide all the values by 255, meaning that some white pixel [255, 255, 255] will become [1., 1., 1.].
Hi I'm trying to build a web-crawler visualization tool for a school project. I decided to use Cytoscape.js and it's been really nice to use. The problem i'm having is the edge lengths for some of the layouts (circle, breadth first, concentric) seem too large and the graph looks odd.
When I first start the application, I manually make and load a graph(it's a tree) with 100 nodes and that looks good in Circle layout:
However after I perform a web-crawl the new graph( this one has 44 nodes) doesn't fit in the view for circle:
Is there a way to get this to work so that the edges are not so long and the nodes look larger?
Edit:
Here's the code I use to change the layout:
changeLayout = function(layoutName, title, root){
var numOfNodes = cy.filter('node').length;
//extent changes when I repeatedly change the layout to circle, (don't understand this behavior)
var extent = cy.extent();
var rect = document.getElementById("cy-container").getBoundingClientRect();
var x1 = rect.left;
var x2 = rect.right;
var y1 = rect.top;
var y2 = rect.bottom;
var height = (y2 - y1);
var width = (x2 - x1);
var fact = (height < width) ? (height/numOfNodes) : (width/numOfNodes);
fact *= 5;
var myRadius = height < width ? (height-fact) : (width-fact);
switch(layoutName){
case 'circle':
myLayout = cy.makeLayout(
{ name: layoutName,
radius: myRadius,
boundingBox: {x1: x1, x2: x2, y1: y1, y2: y2},
fit: true,
avoidOverlap: false
});
break;
case 'concentric':
myLayout = cy.makeLayout(
{ name: layoutName,
height: height,
width: width,
fit: false,
avoidOverlap: true
});
break;
case 'breadthfirst':
myLayout = cy.makeLayout(
{ name: layoutName,
boundingBox: {x1: x1, x2: x2, y1: y1, y2: y2},
fit: true,
roots: root,
avoidOverlap: false
});
break;
default :
myLayout = cy.makeLayout(
{
name: layoutName
});
}
myLayout.run();
$('#graphTitle').text(title + " Layout");
};
The length of an edge is a function of the positions of the nodes. The layout sets the positions, so you have to set the layout options to make the nodes closer together.
For force-directed (physics simulation) layouts, you adjust the forces. In other layouts, you can adjust spacing values or enforce a bounding box to affect how spread out the nodes are.
I need to find the Line coordinates(x1,y1,x2,y2) after the object has been modified. (moved, scaled, rotated)
I thought to use the oCoords information and based on angle and flip information to decide which corners are the line ends, but it seems that it will not be too accurate…
Any help?
Example:
x1: 164,
y1: 295.78334045410156,
x2: 451,
y2: 162.78334045410156
x: 163, y: 161.78334045410156 - top left corner
x: 452, y: 161.78334045410156 - top right corner
x: 163, y: 296.78334045410156 - bottom left corner
x: 452, y: 296.78334045410156 - bottom right corner
When Fabric.js calculates oCoords - i.e. object's corners' coordinates - it takes into account the object's strokeWidth:
// fabric.Object.prototype
_getNonTransformedDimensions: function() {
var strokeWidth = this.strokeWidth,
w = this.width + strokeWidth,
h = this.height + strokeWidth;
return { x: w, y: h };
},
For most objects, stroke is kind of a border that outlines the outer edges, so it makes perfect sense to account for strokeWidth it when calculating corner coordinates.
In fabric.Line, though, stroke is used to draw the body of the line. There is no example in the question but I assume this is the reason behind discrepancies between the real end-point coordinates and those in oCoords.
So, if you really want to use oCoords to detect the coordinates of the end points, you'll have to adjust for strokeWidth / 2, e.g.
const realx1 = line.oCoords.tl.x + line.strokeWidth / 2
const realy1 = line.oCoords.tl.y + line.strokeWidth / 2
Keep in mind that fabric.Line's own _getNonTransformedDimensions() does adjust for strokeWidth, but only when the line's width or height equal 0:
// fabric.Line.prototype
_getNonTransformedDimensions: function() {
var dim = this.callSuper('_getNonTransformedDimensions');
if (this.strokeLineCap === 'butt') {
if (this.width === 0) {
dim.y -= this.strokeWidth;
}
if (this.height === 0) {
dim.x -= this.strokeWidth;
}
}
return dim;
},