terriajs
Version:
Geospatial data visualization platform.
188 lines (159 loc) • 6.71 kB
JavaScript
'use strict';
/*global require*/
var CatalogFunction = require('./CatalogFunction');
var CsvCatalogItem = require('./CsvCatalogItem');
var defined = require('terriajs-cesium/Source/Core/defined');
var defineProperties = require('terriajs-cesium/Source/Core/defineProperties');
var extendLoad = require('./extendLoad');
var inherit = require('../Core/inherit');
var invokeTerriaAnalyticsService = require('./invokeTerriaAnalyticsService');
var TerriaError = require('../Core/TerriaError');
var RegionDataParameter = require('./RegionDataParameter');
var RegionParameter = require('./RegionParameter');
var RegionTypeParameter = require('./RegionTypeParameter');
var RuntimeError = require('terriajs-cesium/Source/Core/RuntimeError');
var updateRectangleFromRegion = require('./updateRectangleFromRegion');
/**
* A Terria Spatial Inference function to identify regions that are _most like_ a given region according to a
* given set of characteristics.
*
* @alias PlacesLikeMeCatalogfunction
* @constructor
* @extends CatalogFunction
*
* @param {Terria} terria The Terria instance.
*/
var PlacesLikeMeCatalogfunction = function(terria) {
CatalogFunction.call(this, terria);
this.url = undefined;
this.name = "Regions like this";
this.description = "Identifies regions that are _most like_ a given region according to a given set of characteristics.";
this._regionTypeParameter = new RegionTypeParameter({
terria: this.terria,
catalogFunction: this,
id: 'regionType',
name: 'Region Type',
description: 'The type of region to analyze.'
});
this._regionParameter = new RegionParameter({
terria: this.terria,
catalogFunction: this,
id: 'region',
name: 'Region',
description: 'The region to analyze. The analysis will determine which regions are most similar to this one.',
regionProvider: this._regionTypeParameter
});
this._dataParameter = new RegionDataParameter({
terria: this.terria,
catalogFunction: this,
id: 'data',
name: 'Characteristics',
description: "The region characteristics to include in the analysis.",
regionProvider: this._regionTypeParameter
});
this._parameters = [
this._regionTypeParameter,
this._regionParameter,
this._dataParameter
];
};
inherit(CatalogFunction, PlacesLikeMeCatalogfunction);
defineProperties(PlacesLikeMeCatalogfunction.prototype, {
/**
* Gets the type of data member represented by this instance.
* @memberOf PlacesLikeMeCatalogfunction.prototype
* @type {String}
*/
type : {
get : function() {
return 'places-like-me-function';
}
},
/**
* Gets a human-readable name for this type of data source, 'Spatial Detailing'.
* @memberOf PlacesLikeMeCatalogfunction.prototype
* @type {String}
*/
typeName : {
get : function() {
return 'Places Like Me';
}
},
/**
* Gets the parameters used to {@link CatalogProcess#invoke} to this function.
* @memberOf PlacesLikeMeCatalogfunction
* @type {CatalogProcessParameters[]}
*/
parameters : {
get : function() {
return this._parameters;
}
}
});
PlacesLikeMeCatalogfunction.prototype._load = function() {
};
/**
* Invokes the function.
* @return {ResultPendingCatalogItem} The result of invoking this process. Because the process typically proceeds asynchronously, the result is a temporary
* catalog item that resolves to the real one once the process finishes.
*/
PlacesLikeMeCatalogfunction.prototype.invoke = function() {
var region = this._regionParameter.value;
var data = this._dataParameter.getRegionDataValue();
if (!defined(region)) {
throw new TerriaError({
title: 'Region not selected',
message: 'You must select a Region.'
});
}
var regionProvider = this._regionTypeParameter.value;
var request = {
algorithm: 'placeslikeme',
boundaries_name: regionProvider.regionType,
region_codes: data.regionCodes,
columns: data.columnHeadings,
table: data.table,
parameters: {
query: region.id
}
};
var regionIndex = regionProvider.regions.indexOf(region);
var regionName = region.id;
if (regionIndex >= 0) {
regionName = regionProvider.regionNames[regionIndex] || regionName;
}
var name = 'Places like ' + regionName;
var that = this;
return invokeTerriaAnalyticsService(this.terria, name, this.url, request).then(function(invocationResult) {
var result = invocationResult.result;
var csv = regionProvider.aliases[0] + ',Likeness\n';
var likeness = result.likeness;
if (data.regionCodes.length !== likeness.length) {
throw new RuntimeError('The list of likenesses and the list of region codes do not contain the same number of elements.');
}
for (var i = 0; i < data.regionCodes.length; ++i) {
csv += data.regionCodes[i] + ',' + Math.pow(likeness[i], 3) + '\n'; // Note: to bring out contrast, we are taking the cube of the likeness. Remove.
}
var catalogItem = new CsvCatalogItem(that.terria);
catalogItem.name = name;
catalogItem.data = csv;
catalogItem.dataUrl = invocationResult.url;
catalogItem.tableStyle.colorBins = 40;
catalogItem.tableStyle.colorMap = [
{"color": "rgba(255,255,255,1.00)", "offset": 0},
{"color": "rgba(191, 191, 255, 1.0)", "offset": 0.5},
{"color": "rgba(0, 0, 255, 1.0)", "offset": 1}
];
// {"color": "rgba(255,255,255,1.00)", "offset": 0},
// {"color": "rgba(0,0,255,1.0)", "offset": 1}
var description = 'This is the result of invoking "' + that.name + '" at ' + invocationResult.startDate + ' with these parameters:\n\n';
description += ' * ' + regionProvider.regionType + ' Region: ' + regionName + ' (' + region.id + ')\n';
description += ' * Characteristics: ' + data.columnHeadings.join(', ') + '\n';
catalogItem.description = description;
extendLoad(catalogItem, function() {
return updateRectangleFromRegion(catalogItem, regionProvider, region);
});
catalogItem.isEnabled = true;
});
};
module.exports = PlacesLikeMeCatalogfunction;