Using cubism.js I'm snagging graphite data and creating multiple graphs on page. Looks amazing but I cannot figure out how to modify the default title/text of each graph. Very limited JS experience.
This might be a cubusm.js, d3.js, or general javascript question, I'm not sure. Since graphite nests data within sometimes deep folders structures, I'd like to be able to simplify default the string a bit. Example of text I want to modify ('servers.apt1.loadavg.05', 'servers.apt2.loadavg.05', etc): http://i.imgur.com/4FqwhjA.png
How do I modify the title/text of each graph's Graphite data? Getting "servers.apt1.loadavg.05, want "apt1" displayed.
var context = cubism.context()
.step( 1 * 30 * 1000 )
.size(960);
var graphite = context.graphite("http://graphite.example.com");
graphFind = 'servers.*.loadavg.05'
graphite.find(graphFind, function(error, results) {
// Map find results to array and set to graphite.metric object type
var metrics = results.sort().map(function(i) {
return graphite.metric(i);
});
// loop through array and print stuff to "graphs" div
for (var i=0;i<metrics.length;i++){
d3.select("#graphs").call(function(div) {
div.append("div")
.selectAll(".horizon")
.data([metrics[i]])
.enter()
.append("div")
.attr("class", "horizon")
.call(context.horizon());
});
}
});
According to the documentation, you can do this with the horizon.title() function. So in your case, it would be something like
.call(context.horizon().title("your title here"));
You can also specify this as a function, e.g.
.call(context.horizon().title(function(d) { return d.title; }));
Related
I am looking to implement my Keras model into my website with the Keras.js library. One problem with this library is that when inputting data in javascript, only a Float32Array() is allowed as an input. This type of array is 1D, and in my Keras model, the input is 3D. I have asked on the Keras.js issues page and found some potential solutions such as adding an embedding layer, but that requires a specific input shape, but I would like to have any 3D input work, as it did when I trained the model. The model structure is simple, there is an input layer which takes an array of dimension mxnx3 (it is an image of unknown size with r, g, and b channels) and a Conv2D layer, which then outputs an mxnx1 array. I know the model works because it can give a good output based on an input, so the only problem I have is with the transition to Keras.js. Here is the JS code that I have at the moment.
function predictImageWithCNN(data) { //'data' is mxnx3 array
var final = [];
//instantiating model from json and buf files
var model = new KerasJS.Model({
filepaths: {
model: 'dist/model.json',
weights: 'dist/model_weights.buf',
metadata: 'dist/model_metadata.json'
},
gpu: true //MAY NEED TO CHANGE (NOT SURE REALLY)
});
//Ready the model.
model.ready()
.then(function() {
//This matches our input data with the input key (b/c Sequential Model)
var inputData = {
'input_1': new Float32Array(data)
};
// make predictions based on inputData
return model.predict(inputData);
})
.then(function(outputData) {
//Here we take the outputData and parse it to get a result.
var out = outputData['output']; //Gets output data
console.log(out);
//TODO: Put in code to assign outputData to 'final' so we can then convert it
// This should not be too hard to do.
})
.catch(function(err) {
console.log(err);
// handle error
});
return final; // should return nxmx1 array of vals 0-1.
}
If anyone had any suggestions for how to resolve this, that would be very much appreciated. Thanks! :)
I had the same problem with an LSTM. The way I got around this was by training using a flattened version of the data but using a reshape layer as the first layer to get it to the shape I needed for my LSTM. eg.
model = Sequential()
model.add(Reshape((40,59),input_shape=(1,2360)))
model.add(LSTM(128, input_shape=(maxlen, len(chars))))
model.add(Dense(len(chars)))
model.add(Activation('softmax'))
optimizer = RMSprop(lr=0.01)
model.compile(loss='categorical_crossentropy', optimizer=optimizer)
Then in Keras.JS I can feed in the flattened version from Float32Array
When I call a function like the following, the data object comes out undefined, and the chart won't render. How can I import this data using Meteor?
UPDATE:
I'm trying out deps.autorun... as per this SO thread and #ethaan's answer below. This got my chart to render.
However, oddly enough, it renders with completely the wrong dataset. Very interesting...
Here's the link to the current state of my project on github: https://github.com/goodwordalchemy/Reactive-line-graph-with-meteor/tree/master/barChart_pt2-meteor
Check out waffles.tsv (changed name to distinguish from old file named data.tsv, which d3 seems to be loading).
And here is a screenshot of what's getting rendered:
UPDATE II: As per this SO article I moved my data file into the public folder, and I am able to render my chart in the browser. However, The chart is not reactive. If I change the .tsv file, the data in the chart does not change....
Template.d3chart.rendered = function(){
// chart attributes and scale are defined up here...
var chart = d3.select(".chart")
d3.tsv("data.tsv", type, function(error, data) {
// callback function
}
}
Template.d3chart.rendered = function(){
// chart attributes and scale are defined up here...
Tracker.autorun(function(){
var chart = d3.select(".chart")
d3.tsv("data.tsv", type, function(error, data) {
// callback function
}
})
}
Typo on rendered?, render dosn't exists
EDIT:
Solved the issue: .useInteractiveGuideline(true) changed to .useInteractiveGuideline(false)
ORIGINAL:
I am trying to modify the custom output binding example using an NVD3 line chart with attaching a click event listener to the NVD3 chart. I modified the linechart-bindings.js file as follows. The only modification is this part of the code (the whole file is also copied below so you can see there i added the snippet):
chart.lines.dispatch.on("elementClick", function( e ) {
console.log(e);
});
The app starts without problem, but there is no console log printout when i click the chart. Probably my approach is too simplistic and there is some obvious part missing. Any idea how to solve this?
The full linechar-bindings.js file:
// Put code in an Immediately Invoked Function Expression (IIFE).
// This isn't strictly necessary, but it's good JavaScript hygiene.
(function() {
// See http://rstudio.github.io/shiny/tutorial/#building-outputs for
// more information on creating output bindings.
// First create a generic output binding instance, then overwrite
// specific methods whose behavior we want to change.
var binding = new Shiny.OutputBinding();
binding.find = function(scope) {
// For the given scope, return the set of elements that belong to
// this binding.
return $(scope).find(".nvd3-linechart");
};
binding.renderValue = function(el, data) {
// This function will be called every time we receive new output
// values for a line chart from Shiny. The "el" argument is the
// div for this particular chart.
var $el = $(el);
// The first time we render a value for a particular element, we
// need to initialize the nvd3 line chart and d3 selection. We'll
// store these on $el as a data value called "state".
if (!$el.data("state")) {
var chart = nv.models.lineChart()
.margin({left: 100})
.useInteractiveGuideline(true)
.transitionDuration(350)
.showLegend(true)
.showYAxis(true)
.showXAxis(true);
chart.xAxis //Chart x-axis settings
.axisLabel('Time (ms)')
.tickFormat(d3.format(',r'));
chart.yAxis //Chart y-axis settings
.axisLabel('Voltage (v)')
.tickFormat(d3.format('.02f'));
chart.lines.dispatch.on("elementClick", function( e ) {
console.log(e);
});
nv.utils.windowResize(chart.update);
var selection = d3.select(el).select("svg");
// Store the chart object on el so we can get it next time
$el.data("state", {
chart: chart,
selection: selection
});
}
// Now, the code that'll run every time a value is rendered...
// Retrieve the chart and selection we created earlier
var state = $el.data("state");
// Schedule some work with nvd3
nv.addGraph(function() {
// Update the chart
state.selection
.datum(data)
.transition(500)
.call(state.chart);
return state.chart;
});
};
// Tell Shiny about our new output binding
Shiny.outputBindings.register(binding, "shinyjsexamples.nvd3-linechart");
})();
Not a solution but a workaround:
.useInteractiveGuideline(true) changed to .useInteractiveGuideline(false)
I am looking at a simple Rickshaw chart with data from a JSON file.
d3.json(data, function(error, json) {
var graph = new Rickshaw.Graph( {
element: document.getElementById(chart_id),
renderer: 'line',
series: [
{name: 'myseries',
data: json[0].data}
]
})
graph.render();
});
I would like to access the graph after it has been rendered. Since the graph is created within a callback function I cannot simply return the handle. Also document.getElementById(chart_id) does not have a chart attribute.
My goal is to, for example, allow users to specify a certain range for multiple charts at the same time (e.g. last 5 years) without having to adjust the RangeSlider for each one of them. With access to the chart I could then do
new_rng = [new_min,new_max]
graph.window.xMin = new_rng[0]
graph.window.xMax = new_rng[1]
$('#' + slider_id).slider('option', 'values',new_rng)
Any ideas?
I think this is a similar problem to the one I encountered with a xively feed where the data is not returned when the graph is rendered. Here's my post.
Multiple calls to xively.feed.history()
I'm making a map in which I first define state outlines with paths defined by a GeoJSON file, as well as a little bit of extra info, like state name. After loading, I'd like to fill the states and populate a tooltip based on data from a csv, using some buttons and checkboxes (year, different subsets of data).
I find that when I call .data() on the state objects a second time, using the csv rather than the json file, the paths disappear since they only exist in json. Is there a way I can only update certain variables? Is there a better way to bind the state objects to dynamic data?
The way I have generally approached this, and the way the code is set up in the choropleth map example, is to load the two files separately, and then join the data on feature id when you need it. This is easiest if you load the files in sequence, like this:
// make a container
var counties = svg.append("svg:g")
.attr("id", "counties");
// load the data you're showing
d3.json("unemployment.json", function(data) {
// load the geo data (you could reverse the order here)
d3.json("us-counties.json", function(json) {
// make the map
counties.selectAll("path")
.data(json.features)
.enter().append("svg:path")
.attr("d", path);
// now join the data, maybe in a separate function
update(data)
});
});
In your update() function, you take the data and apply operations (colors, etc) to the map based on id:
update(data) {
// look at the loaded counties
counties.selectAll("path")
// update colors based on data
.attr('fill', function(d) {
// get the id from the joined GeoJSON
var countyId = d.id;
// get the data point. This assumes your data is an object; if your data is
// a CSV, you'll need to convert it to an object keyed to the id
var datum = data[countyId];
// now calculate your color
return myColorScale(datum);
});
}