My x-axis for google visualisation chart is javascript new Date(year+i, 0, 0). However when I print the line chart. It shows M J S at the bottom with the year number.
How can I remove these M J S (which I presume are May June and September).
the following snippet re-produces the problem, with year number combined with month abbreviations...
2020 M J S 2021 M J S etc...
google.charts.load('current', {
packages: ['corechart']
}).then(function () {
var data = new google.visualization.DataTable();
data.addColumn('date', 'Date');
data.addColumn('number', 'Mutual Fund');
for (var y = 2020; y < 2024; y++) {
for (var m = 0; m < 12; m++) {
data.addRow([new Date(y, m, 1), (10000 + y + m)]);
}
}
var container = document.getElementById('chart');
var chart = new google.visualization.LineChart(container);
chart.draw(data);
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart"></div>
to only show year, you can use hAxis option format.
hAxis: {
format: 'yyyy'
}
however, this could cause the year to repeat (depending on the width of the chart)...
2020 2020 2020 2020 2021 2021 2021
see following snippet...
google.charts.load('current', {
packages: ['corechart']
}).then(function () {
var data = new google.visualization.DataTable();
data.addColumn('date', 'Date');
data.addColumn('number', 'Mutual Fund');
for (var y = 2020; y < 2024; y++) {
for (var m = 0; m < 12; m++) {
data.addRow([new Date(y, m, 1), (10000 + y + m)]);
}
}
var container = document.getElementById('chart');
var chart = new google.visualization.LineChart(container);
chart.draw(data, {
hAxis: {
format: 'yyyy'
}
});
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart"></div>
to ensure the year doesn't repeat, we must also provide hAxis option ticks.
ticks must be in the same format as the data on the x-axis, in this case a date.
so we provide the jan date for each year...
hAxis: {
format: 'yyyy',
ticks: [new Date(2020, 0, 1), new Date(2021, 0, 1), new Date(2022, 0, 1)]
}
you should be able to create the ticks dynamically, from the data.
see following snippet for an example...
google.charts.load('current', {
packages: ['corechart']
}).then(function () {
var data = new google.visualization.DataTable();
data.addColumn('date', 'Date');
data.addColumn('number', 'Mutual Fund');
var ticks = [];
for (var y = 2020; y < 2024; y++) {
for (var m = 0; m < 12; m++) {
data.addRow([new Date(y, m, 1), (10000 + y + m)]);
if (m === 0) {
ticks.push(new Date(y, m, 1));
}
}
}
var container = document.getElementById('chart');
var chart = new google.visualization.LineChart(container);
chart.draw(data, {
hAxis: {
format: 'yyyy',
ticks: ticks
}
});
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart"></div>
Related
I want to load in my matlab geometry into my three.js scene. My 3D data is saved in a struct .mat file which contains .vertices, .faces, .VertexNormals and .VertexColorData arrays. I am able to load it into JavaScript and use buffer geometry and set attributes to store the data into a mesh geometry.
var keyName = keysArray[0];
meshGeometry = new THREE.BufferGeometry();
var index = 0;
var positions = new Float32Array(bfjson.data[keyName].vertices.length * 3);
for (let i = 0; i < bfjson.data[keyName].vertices.length; i++) {
positions[index++] = bfjson.data[keyName].vertices[i][0];
positions[index++] = bfjson.data[keyName].vertices[i][1];
positions[index++] = bfjson.data[keyName].vertices[i][2];
}
meshGeometry.setAttribute(
'position',
new THREE.BufferAttribute(positions, 3));
var index = 0;
var vectornormals = new Float32Array(bfjson.data[keyName].VertexNormals.length * 3);
for (let i = 0; i < bfjson.data[keyName].VertexNormals.length; i++) {
vectornormals[index++] = bfjson.data[keyName].VertexNormals[i][0];
vectornormals[index++] = bfjson.data[keyName].VertexNormals[i][1];
vectornormals[index++] = bfjson.data[keyName].VertexNormals[i][2];
}
meshGeometry.setAttribute(
'normal',
new THREE.BufferAttribute(vectornormals, 3));
var index = 0;
//var faces = new Uint16Array(bfjson.data[keyName].faces.length * 3);
var faces = [];
for (let i = 0; i < bfjson.data[keyName].faces.length; i++) {
faces[index++] = bfjson.data[keyName].faces[i][0];
faces[index++] = bfjson.data[keyName].faces[i][1];
faces[index++] = bfjson.data[keyName].faces[i][2];
}
meshGeometry.setIndex(faces);
// default color attribute
const colors = [];
for (let i = 0, n = meshGeometry.attributes.position.count; i < n; ++i) {
colors.push(1, 1, 1);
}
meshGeometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
for (let i = 0; i < bfjson.data[keyName].CData.length; i++) {
CData[i] = (bfjson.data[keyName].CData[i]);
}
meshGeometry.setAttribute('perfusion', new THREE.Float32BufferAttribute(CData, 1));
mesh.geometry = meshGeometry;
updateColors();
The vertex coloring works fine. However, I end up with mesh with index faces or normal not connecting into a normal surface.
mesh with index faces or normal not connecting up into a normal surface.
I am not sure what I am doing wrong. I will be extremely grateful for any help provided.
Edit--
I have made a jsfiddle to help.
https://jsfiddle.net/marieO/5zdhsk78/68/
But you need to download the .mat file first then upload it to the scene. (as I was unable to add it to the jsfiddle)
https://dev.kingsvirtualanatomyandhistology.kcl.ac.uk//models/mat/p21_newmod.mat
Thanks for posting a working example with the steps needed to reproduce the error. It makes it much easier to help.
You have 652 vertices in your Matlab geometry. When using .setIndex(), these indices have to be in the [0, 651] range, because JavaScript arrays start at index 0. However, your faces data ranges from [1, 652], which means all your triangles are off by 1 vertex.
This is easily solvable by adding a -1 when assigning the index:
var index = 0;
var faces = [];
for (let i = 1; i < bfjson.data[keyName].faces.length; i++) {
faces[index++] = bfjson.data[keyName].faces[i][0] - 1;
faces[index++] = bfjson.data[keyName].faces[i][1] - 1;
faces[index++] = bfjson.data[keyName].faces[i][2] - 1;
}
meshGeometry.setIndex(faces);
Result:
I have a Perceptron written in Javascript that works fine, code below. My question is about the threshold in the activation function. Other code I have seen has something like if (sum > 0) {return 1} else {return 0}. My perceptron only works with if (sum > 1) {return 1} else {return 0}. Why is that? Full code below.
(function () {
"use strict";
function Perceptron(numInputs=2) {
let weights = Array.from({length: numInputs}, () => 2 * Math.random() - 1); // [-1, 1)
this.learningRate = 0.5;
this.train = function (inputs, goal) {
// feed forward
let guess = this.predict(inputs);
// back propagation
let error = goal - guess;
if (error !== 0) {
for (let i = 0; i < weights.length; i += 1) {
weights[i] += this.learningRate * error * inputs[i];
}
}
}
this.predict = function (inputs) {
// transfer function
let sumProducts = 0;
for (let i = 0; i < inputs.length; i += 1) {
sumProducts += inputs[i] * weights[i];
}
// activation function, threshold = 1
return (sumProducts >= 1) ? 1 : 0; // <-- this is the line I have a question about
}
}
// train
let data = [
[0, 0, 0],
[0, 1, 0],
[1, 0, 0],
[1, 1, 1]
];
let p = new Perceptron(2);
const epochs = 20;
for (let i = 0; i < epochs; i += 1) {
let r = Math.floor(Math.random() * data.length);
p.train(data[r].slice(0, 2), data[r].slice(-1));
}
// test
for (let i = 0; i < data.length; i += 1) {
let inputs = data[i].slice(0, 2);
console.log(`inputs = ${inputs}; output = ${p.predict(inputs)}`);
}
}());
Your perceptron lacks a bias term, your equation is of form SUM_i w_i x_i, instead of SUM_i w_i x_i + b. With the functional form you have it is impossible to separate points, where the separating hyperplane does not cross the origin (and yours does not). Alternatively you can add a column of "1s" to your data, it will serve the same purpose, as the corresponding w_i will just behave as b (since all x_i will be 1)
For anyone else following this question, here is the final code. Thanks to #lejlot for helping!
/*jslint for:true, long:true, devel:true, this:true */
/*jshint esversion: 6*/
(function () {
"use strict";
function Perceptron(numInputs = 2) {
this.weights = Array.from({length: numInputs}, () => 2 * Math.random() - 1); // [-1, 1)
this.learningRate = 0.5;
this.bias = 1;
this.train = function (inputs, goal) {
// feed forward
let guess = this.predict(inputs);
// back propagation
let error = goal - guess;
if (error !== 0) {
for (let i = 0; i < this.weights.length; i += 1) {
this.weights[i] += error * inputs[i] * this.learningRate;
}
// Bias should be learned, not fixed. The update rules is
// identical to the weight, just lacks "* inputs[i]" (as
// described in the answer it is equivalent to having a constant
// input of 1, and multiplying by 1 does nothing).
this.bias += error * this.learningRate;
}
};
this.predict = function (inputs) {
// transfer function
let sumProducts = 0;
for (let i = 0; i < inputs.length; i += 1) {
sumProducts += inputs[i] * this.weights[i];
}
// Your perception lacks a bias term, your equation if of form
// SUM_i w_i x_i, instead of SUM_i w_i x_i + b. With the
// functional form you have it is impossible to separate points,
// where the separating hyperplane does not cross the origin
// (and yours does not). Alternatively you can add a column of
// "1s" to your data, it will serve the same purpose, as the
// corresponding w_i will just behave as "b" (since all x_i will
// be 1)
sumProducts += this.bias;
// activation function
return (sumProducts >= 0) ? 1 : 0;
};
}
// train - boolean AND
let data = [
[0, 0, 0],
[0, 1, 0],
[1, 0, 0],
[1, 1, 1]
];
let p = new Perceptron(2);
const epochs = 100;
for (let i = 0; i < epochs; i += 1) {
let r = Math.floor(Math.random() * data.length);
p.train(data[r].slice(0, 2), data[r].slice(-1));
}
// test
for (let i = 0; i < data.length; i += 1) {
let inputs = data[i].slice(0, 2);
console.log(`inputs = ${inputs}; output = ${p.predict(inputs)}`);
}
}());
Im using line chart from Google Charts. I show date on hAxis (horizontal). My major gridlines show date normally. But there are time labels between date labels. And i dont want time labels.
I tried to put that property in hAxis on chart options but nothing changed
minorGridlines:{textPosition: 'none' }
hAxis options;
hAxis: {titleTextStyle: {color: '#0000ff'},
slantedText:true, slantedTextAngle:60,format: 'd/M/yy',minorGridlines:{textPosition: 'none' },gridlines: {
count: -1,
units: {
days: {format: ['d.MM']},
hours: {format: ['HH:mm']},
}
}
},
is there anyone who knows the solution?
first, remove the options for gridlines.
however, this could cause the same date labels to repeat.
to prevent from repeating,
you can provide your own ticks.
the hAxis.ticks option takes an array, in this case, of dates.
to build the ticks array, we can use data table method --> getColumnRange(colIndex)
this will return the min & max values of the column.
then we can to build our ticks array.
// build hAxis ticks
var hAxisTicks = [];
var dateRange = data.getColumnRange(0);
var oneDay = (24 * 60 * 60 * 1000);
for (var i = dateRange.min.getTime(); i <= dateRange.max.getTime(); i = i + oneDay) {
hAxisTicks.push(new Date(i));
}
see following working snippet...
google.charts.load('current', {
packages: ['corechart']
}).then(function () {
var data = new google.visualization.DataTable();
data.addColumn('date', 'Date');
data.addColumn('number', 'Y');
data.addRows([
[new Date(2019, 0, 1, 0), 10],
[new Date(2019, 0, 1, 6), 20],
[new Date(2019, 0, 1, 12), 30],
[new Date(2019, 0, 1, 18), 40],
[new Date(2019, 0, 2, 0), 10],
[new Date(2019, 0, 2, 6), 20],
[new Date(2019, 0, 2, 12), 30],
[new Date(2019, 0, 2, 18), 40],
[new Date(2019, 0, 3, 0), 10],
[new Date(2019, 0, 3, 6), 20],
[new Date(2019, 0, 3, 12), 30],
[new Date(2019, 0, 3, 18), 40],
[new Date(2019, 0, 4, 0), 10],
[new Date(2019, 0, 4, 6), 20],
[new Date(2019, 0, 4, 12), 30],
[new Date(2019, 0, 4, 18), 40],
]);
// build hAxis ticks
var hAxisTicks = [];
var dateRange = data.getColumnRange(0);
var oneDay = (24 * 60 * 60 * 1000);
for (var i = dateRange.min.getTime(); i <= dateRange.max.getTime(); i = i + oneDay) {
hAxisTicks.push(new Date(i));
}
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
chart.draw(data, {
hAxis: {
format: 'd/M/yy',
ticks: hAxisTicks
}
});
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>
EDIT
building the ticks manually will cause a performance hit,
but only by a couple milliseconds, which is nothing.
see following working snippet,
540 rows are drawn, the milliseconds it takes to build the ticks are shown in the console...
google.charts.load('current', {
packages: ['corechart']
}).then(function () {
var data = new google.visualization.DataTable();
data.addColumn('date', 'Date');
data.addColumn('number', 'Y');
for (var i = (new Date(2019, 0, 1)).getTime(); i <= (new Date(2019, 3, 1)).getTime(); i = i + (4 * 60 * 60 * 1000)) {
data.addRow([new Date(i), i]);
}
// build hAxis ticks
var test = new Date();
console.log('rows', data.getNumberOfRows());
var hAxisTicks = [];
var dateRange = data.getColumnRange(0);
var oneDay = (24 * 60 * 60 * 1000);
for (var i = dateRange.min.getTime(); i <= dateRange.max.getTime(); i = i + oneDay) {
hAxisTicks.push(new Date(i));
}
console.log('milliseconds', ((new Date()).getTime() - test.getTime()));
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
chart.draw(data, {
hAxis: {
format: 'd/M/yy',
ticks: hAxisTicks
}
});
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>
I wondered if it was possible to make the circle, that appears once hovered across the Google line chart, have a coloured border?
you can use a style column role to change the style of a point.
point {stroke-width: 2; stroke-color: red;}
see following working snippet,
hover a point to see the style...
google.charts.load('current', {
packages: ['corechart']
}).then(function () {
var data = new google.visualization.DataTable();
data.addColumn('number', 'x');
data.addColumn('number', 'y');
data.addColumn({role: 'style', type: 'string'});
data.addRows([
[0, 1, 'point {stroke-width: 2; stroke-color: red;}'],
[1, 2, 'point {stroke-width: 2; stroke-color: red;}'],
[2, 3, 'point {stroke-width: 2; stroke-color: red;}'],
[3, 4, 'point {stroke-width: 2; stroke-color: red;}'],
[4, 5, 'point {stroke-width: 2; stroke-color: red;}'],
]);
var options = {
legend: 'none'
};
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
chart.draw(data, options);
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>
My data looks like this:
A B
3 5000
2 6218
4 9435
I need to create a chart where A is the number of points/block size and B is the Value of each point.
For example, the date above will create a line graph where the 2 first points will have the value of 5000, the next 2 points will have the value of 6218, and the next 4 points will have the value of 9435.
The graph I need will look like the automatic one that will be generated for this data:
5000
5000
5000
6218
6218
9435
9435
9435
9435
use the original data table to build a new data table.
for each row in the original table, add a row to the new table however many times 'A' represents.
var x = 0;
for (var row = 0; row < rawData.getNumberOfRows(); row++) {
for (var a = 0; a < rawData.getValue(row, 0); a++) {
chartData.addRow([x, rawData.getValue(row, 1)]);
x++;
}
}
see following working snippet...
google.charts.load('current', {
packages:['corechart']
}).then(function () {
var rawData = google.visualization.arrayToDataTable([
['A', 'B'],
[3, 5000],
[2, 6218],
[4, 9435]
]);
var chartData = new google.visualization.DataTable();
chartData.addColumn('number', 'X');
chartData.addColumn('number', 'Y');
var x = 0;
for (var row = 0; row < rawData.getNumberOfRows(); row++) {
for (var a = 0; a < rawData.getValue(row, 0); a++) {
chartData.addRow([x, rawData.getValue(row, 1)]);
x++;
}
}
var container = document.getElementById('chart_div');
var chart = new google.visualization.LineChart(container);
chart.draw(chartData, {
height: 288,
pointSize: 4,
vAxis: {
minValue: 0
}
});
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>