StackGenVis: Alignment of Data, Algorithms, and Models for Stacking Ensemble Learning Using Performance Metrics
https://doi.org/10.1109/TVCG.2020.3030352
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
182 lines
4.3 KiB
182 lines
4.3 KiB
var fs = require('fs')
|
|
var topojson = require('topojson')
|
|
var gju = require('geojson-utils')
|
|
var common = require('./common')
|
|
|
|
fs.readFile(common.pathToConfig, 'utf8', main)
|
|
|
|
function main (err, configFile) {
|
|
if (err) throw err
|
|
|
|
var config = JSON.parse(configFile)
|
|
var toposToWrite = common.getToposToWrite(config)
|
|
|
|
var barWrite = common.makeBar(
|
|
'Writing into topojson: [:bar] :current/:total',
|
|
[toposToWrite]
|
|
)
|
|
|
|
function propertyTransform (feature) { return feature.properties }
|
|
|
|
toposToWrite.forEach(function (topo) {
|
|
var r = topo.r
|
|
|
|
var s = topo.s
|
|
|
|
var collections = {}
|
|
|
|
config.vectors.forEach(function (v) {
|
|
var path = common.geojsonDir + common.tn(r, s.name, v.name, 'geo.json')
|
|
|
|
var d = fs.readFileSync(path, 'utf8')
|
|
|
|
var collection = JSON.parse(d)
|
|
|
|
if (collection.features) formatProperties(collection, v)
|
|
collections[v.name] = collection
|
|
})
|
|
|
|
// TODO experiment with simplification/quantization
|
|
var topology = topojson.topology(collections, {
|
|
verbose: common.DEBUG,
|
|
'property-transform': propertyTransform
|
|
})
|
|
|
|
pruneProperties(topology)
|
|
|
|
var outPath = common.topojsonDir + common.out(r, s.name)
|
|
|
|
fs.writeFile(outPath, JSON.stringify(topology), function (err) {
|
|
if (err) throw err
|
|
barWrite.tick()
|
|
})
|
|
})
|
|
}
|
|
|
|
function formatProperties (collection, v) {
|
|
var features = collection.features
|
|
|
|
var N = features.length
|
|
|
|
var feature
|
|
|
|
var id
|
|
|
|
function getCentroid (feature) {
|
|
var geometry = feature.geometry
|
|
|
|
function getOne (polygon) {
|
|
var coords = gju.centroid(polygon).coordinates
|
|
return [+coords[0].toFixed(2), +coords[1].toFixed(2)]
|
|
}
|
|
|
|
if (geometry.type === 'MultiPolygon') {
|
|
var coordinates = geometry.coordinates
|
|
|
|
var N = coordinates.length
|
|
|
|
var centroids = new Array(N)
|
|
|
|
var areas = new Array(N)
|
|
|
|
var polygon
|
|
|
|
var indexOfMax
|
|
|
|
// compute one centroid per polygon and
|
|
// pick the one associated with the
|
|
// largest area.
|
|
|
|
for (var i = 0; i < N; i++) {
|
|
polygon = {
|
|
type: 'Polygon',
|
|
coordinates: coordinates[i]
|
|
}
|
|
centroids[i] = getOne(polygon)
|
|
areas[i] = gju.area(polygon)
|
|
}
|
|
|
|
// 'min' works best, not sure why
|
|
indexOfMax = areas.indexOf(Math.min.apply(Math, areas))
|
|
return centroids[indexOfMax]
|
|
} else if (geometry.type === 'Polygon') {
|
|
return getOne(geometry)
|
|
}
|
|
}
|
|
|
|
for (var i = 0; i < N; i++) {
|
|
feature = features[i]
|
|
|
|
if (v.ids) {
|
|
id = feature.properties[v.ids]
|
|
|
|
if (id && id !== '-99') {
|
|
feature.id = id
|
|
feature.properties.ct = getCentroid(feature)
|
|
feature.properties.gu = feature.properties['gu_a3']
|
|
continue
|
|
}
|
|
}
|
|
|
|
// Unfortunately, we need this to include Norway (IS0_A3=NOR)
|
|
// from Natural Earth v4.1.0
|
|
// - https://github.com/nvkelso/natural-earth-vector/issues/252
|
|
if (v.ids && v.ids.indexOf('ISO_A3') === 0) {
|
|
id = feature.properties['SOV_A3']
|
|
|
|
if (id === 'NOR') {
|
|
feature.id = id
|
|
feature.properties.ct = getCentroid(feature)
|
|
feature.properties.gu = feature.properties['gu_a3']
|
|
}
|
|
}
|
|
|
|
// France (IS0_A3=FRA) is also acting weird using IS0_A3,
|
|
// but using ISO_A3_EH seems to work ok
|
|
// - https://github.com/nvkelso/natural-earth-vector/issues/284
|
|
}
|
|
}
|
|
|
|
function pruneProperties (topology) {
|
|
// keep 'gu' (aka governing unit A3 code, which necessary to identify
|
|
// some subunits ids (e.g. 'WA' which can be Washington state and Western
|
|
// Australia)
|
|
var propsToKeep = ['ct', 'gu']
|
|
|
|
var objects = topology.objects
|
|
|
|
Object.keys(objects).forEach(function (objectName) {
|
|
var obj = objects[objectName]
|
|
|
|
delete obj.crs
|
|
delete obj.name
|
|
|
|
var geometries2 = []
|
|
|
|
obj.geometries.forEach(function (geometry) {
|
|
var properties = geometry.properties
|
|
|
|
var newProperties = {}
|
|
|
|
if (properties === undefined) return
|
|
|
|
propsToKeep.forEach(function (prop) {
|
|
if (properties[prop] !== undefined) {
|
|
newProperties[prop] = properties[prop]
|
|
}
|
|
})
|
|
|
|
if (Object.keys(newProperties).length) {
|
|
geometry.properties = newProperties
|
|
} else {
|
|
delete geometry.properties
|
|
}
|
|
|
|
if (geometry.type !== null) {
|
|
geometries2.push(geometry)
|
|
}
|
|
})
|
|
|
|
obj.geometries = geometries2
|
|
})
|
|
}
|
|
|