d3.js - update a GeoJSON element - javascript

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);
});
}

Related

Multi-dimensional input in Keras.js

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

Javascript get data from sql using object with openlayers 3

I added some points on the map using javascript(OpenLayers3). These points' positions are fetching from sql(randomly generated). I have to create a pop-up menu about each object on the map. This pop-up includes the data information of each selected point but ı dont know how to get the data from sql using the object on the map.
Points Img
How to get data ? Img
One way to do it is to transfer ID from your sql for each object in map. You can add custom property in that way:
var pointFeature = new ol.Feature({
geometry: new ol.geom.Point([0, 0]),
id: 25
});
Next use click event to get feature and ID:
map.on('click', function(evt) {
var feature = map.forEachFeatureAtPixel(evt.pixel,
function(feature) {
return feature;
});
if (feature) {
alert(feature.get('id'));
}
});
Here you go! All that remain is to make ajax request to your asp.net with ID as parameter.
Another way is to transfer ALL attributes from your sql on map from the beginning, so you won't need to make ajax request - you could just get properties from feature. But be careful as this solution will increase your point data greatly.

Modify Cubism.js Graphite Title Text

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; }));

leaflet choropleth map using dynamic value

I am doing a choropleth map using leaflet and JSON data. I got a clean tutorial in leaflet site. In that tutorial the used us-states.js JSON file where the choropleth was based on the feature.properties.density feature of the JSON if I am not wrong. If we see the JS file we can found there is a field called "ID" which is state id. I have a database where I have 5 different categories of data based on state ID. Categories are population, density, male_population, female_population, literacy_rate. I am calling those data through ajax and get a GeoJSON data state-wise as follows (Its a dummy data).
[{"state_id":"01","population":"123456","density":"1234","male_pop":"65432","female_pop":"57421","literacy_rate":"98"}]
...
[{"state_id":"50","population":"123456","density":"1234","male_pop":"65432","female_pop":"57421","literacy_rate":"98"}]
I want to integrate this data as choropleth value. when I call on literacy function the variation of color will be based on literacy_rate data. I can make the changes in getcolor function category wise.
Thanks
I would recommend using Leaflet Data Visualization Framework (DVF) plugin, located here. This plugin contains a set of Layers, (such as a Choropleth layer) and a set of functions to help color-code your data.
The example located here will demonstrate the DVF Choropleth Data layer.
Using DVF, you can create a color function to create your scaling color values. For example, this function will generate a function from yellow to red. The point values contain the range of values, and the HSL Hue.
var yellowToRed = new L.HSLHueFunction(new L.Point(50, 60), new L.Point(100, 0));
DVF contains a L.ChoroplethDataLayer layer that will accept your GeoJSON, and your color function, and will generate the layer for you.
var layer = new L.ChoroplethDataLayer(geoJSON, {
// For the full options, see the documentation
displayOptions: {
// The display will be colored by your 'density' property in your GeoJSON. This accesses the feature object directory, so the 'properties' prefix is required if you're going to access a GeoJSON property on your data.
'properties.density': {
// A legend will automatically be generated for you. You can add this as a control. This displayName property will be the title for this layer's legend.
displayName: 'Density',
color: yellowToRed
}
};
});
This is just a simple example. For your data, it might look slightly different. Go through the DVF documentation and samples and you'll find what's right for you.

Rickshaw RangeSlider - Zoom in by default

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()

Categories