UNPKG

kepler.gl

Version:

kepler.gl is a webgl based application to visualize large scale location data in the browser

789 lines (666 loc) 79 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.processCsvData = processCsvData; exports.parseRowsByFields = parseRowsByFields; exports.getSampleForTypeAnalyze = getSampleForTypeAnalyze; exports.parseCsvRowsByFieldType = parseCsvRowsByFieldType; exports.getFieldsFromData = getFieldsFromData; exports.renameDuplicateFields = renameDuplicateFields; exports.analyzerTypeToFieldType = analyzerTypeToFieldType; exports.processRowObject = processRowObject; exports.processGeojson = processGeojson; exports.formatCsv = formatCsv; exports.validateInputData = validateInputData; exports.processKeplerglJSON = processKeplerglJSON; exports.processKeplerglDataset = processKeplerglDataset; exports.Processors = exports.DATASET_HANDLERS = exports.PARSE_FIELD_VALUE_FROM_STRING = exports.CSV_NULLS = exports.ACCEPTED_ANALYZER_TYPES = void 0; var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _d3Dsv = require("d3-dsv"); var _d3Array = require("d3-array"); var _window = require("global/window"); var _assert = _interopRequireDefault(require("assert")); var _typeAnalyzer = require("type-analyzer"); var _geojsonNormalize = _interopRequireDefault(require("@mapbox/geojson-normalize")); var _defaultSettings = require("../constants/default-settings"); var _dataUtils = require("../utils/data-utils"); var _schemas = _interopRequireDefault(require("../schemas")); var _userGuides = require("../constants/user-guides"); var _utils = require("../utils/utils"); var _PARSE_FIELD_VALUE_FR, _DATASET_HANDLERS; function _createForOfIteratorHelper(o, allowArrayLike) { var it; if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = o[Symbol.iterator](); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } var ACCEPTED_ANALYZER_TYPES = [_typeAnalyzer.DATA_TYPES.DATE, _typeAnalyzer.DATA_TYPES.TIME, _typeAnalyzer.DATA_TYPES.DATETIME, _typeAnalyzer.DATA_TYPES.NUMBER, _typeAnalyzer.DATA_TYPES.INT, _typeAnalyzer.DATA_TYPES.FLOAT, _typeAnalyzer.DATA_TYPES.BOOLEAN, _typeAnalyzer.DATA_TYPES.STRING, _typeAnalyzer.DATA_TYPES.GEOMETRY, _typeAnalyzer.DATA_TYPES.GEOMETRY_FROM_STRING, _typeAnalyzer.DATA_TYPES.PAIR_GEOMETRY_FROM_STRING, _typeAnalyzer.DATA_TYPES.ZIPCODE, _typeAnalyzer.DATA_TYPES.ARRAY, _typeAnalyzer.DATA_TYPES.OBJECT]; // if any of these value occurs in csv, parse it to null; // const CSV_NULLS = ['', 'null', 'NULL', 'Null', 'NaN', '/N']; // matches empty string exports.ACCEPTED_ANALYZER_TYPES = ACCEPTED_ANALYZER_TYPES; var CSV_NULLS = /^(null|NULL|Null|NaN|\/N||)$/; exports.CSV_NULLS = CSV_NULLS; var IGNORE_DATA_TYPES = Object.keys(_typeAnalyzer.DATA_TYPES).filter(function (type) { return !ACCEPTED_ANALYZER_TYPES.includes(type); }); var PARSE_FIELD_VALUE_FROM_STRING = (_PARSE_FIELD_VALUE_FR = {}, (0, _defineProperty2["default"])(_PARSE_FIELD_VALUE_FR, _defaultSettings.ALL_FIELD_TYPES["boolean"], { valid: function valid(d) { return typeof d === 'boolean'; }, parse: function parse(d) { return d === 'true' || d === 'True' || d === 'TRUE' || d === '1'; } }), (0, _defineProperty2["default"])(_PARSE_FIELD_VALUE_FR, _defaultSettings.ALL_FIELD_TYPES.integer, { valid: function valid(d) { return parseInt(d, 10) === d; }, parse: function parse(d) { return parseInt(d, 10); } }), (0, _defineProperty2["default"])(_PARSE_FIELD_VALUE_FR, _defaultSettings.ALL_FIELD_TYPES.timestamp, { valid: function valid(d, field) { return ['x', 'X'].includes(field.format) ? typeof d === 'number' : typeof d === 'string'; }, parse: function parse(d, field) { return ['x', 'X'].includes(field.format) ? Number(d) : d; } }), (0, _defineProperty2["default"])(_PARSE_FIELD_VALUE_FR, _defaultSettings.ALL_FIELD_TYPES.real, { valid: function valid(d) { return parseFloat(d) === d; }, // Note this will result in NaN for some string parse: parseFloat }), _PARSE_FIELD_VALUE_FR); /** * Process csv data, output a data object with `{fields: [], rows: []}`. * The data object can be wrapped in a `dataset` and pass to [`addDataToMap`](../actions/actions.md#adddatatomap) * @param rawData raw csv string * @returns data object `{fields: [], rows: []}` can be passed to addDataToMaps * @type {typeof import('./data-processor').processCsvData} * @public * @example * import {processCsvData} from 'kepler.gl/processors'; * * const testData = `gps_data.utc_timestamp,gps_data.lat,gps_data.lng,gps_data.types,epoch,has_result,id,time,begintrip_ts_utc,begintrip_ts_local,date * 2016-09-17 00:09:55,29.9900937,31.2590542,driver_analytics,1472688000000,False,1,2016-09-23T00:00:00.000Z,2016-10-01 09:41:39+00:00,2016-10-01 09:41:39+00:00,2016-09-23 * 2016-09-17 00:10:56,29.9927699,31.2461142,driver_analytics,1472688000000,False,2,2016-09-23T00:00:00.000Z,2016-10-01 09:46:37+00:00,2016-10-01 16:46:37+00:00,2016-09-23 * 2016-09-17 00:11:56,29.9907261,31.2312742,driver_analytics,1472688000000,False,3,2016-09-23T00:00:00.000Z,,,2016-09-23 * 2016-09-17 00:12:58,29.9870074,31.2175827,driver_analytics,1472688000000,False,4,2016-09-23T00:00:00.000Z,,,2016-09-23` * * const dataset = { * info: {id: 'test_data', label: 'My Csv'}, * data: processCsvData(testData) * }; * * dispatch(addDataToMap({ * datasets: [dataset], * options: {centerMap: true, readOnly: true} * })); */ exports.PARSE_FIELD_VALUE_FROM_STRING = PARSE_FIELD_VALUE_FROM_STRING; function processCsvData(rawData, header) { var rows; var headerRow; if (typeof rawData === 'string') { var _parsedRows = (0, _d3Dsv.csvParseRows)(rawData); if (!Array.isArray(_parsedRows) || _parsedRows.length < 2) { // looks like an empty file, throw error to be catch throw new Error('process Csv Data Failed: CSV is empty'); } headerRow = _parsedRows[0]; rows = _parsedRows.slice(1); } else if (Array.isArray(rawData) && rawData.length) { rows = rawData; headerRow = header; if (!Array.isArray(headerRow)) { // if data is passed in as array of rows and missing header // assume first row is header headerRow = rawData[0]; rows = rawData.slice(1); } } if (!rows || !headerRow) { throw new Error('invalid input passed to processCsvData'); } // here we assume the csv file that people uploaded will have first row // as name of the column cleanUpFalsyCsvValue(rows); // No need to run type detection on every data point // here we get a list of none null values to run analyze on var sample = getSampleForTypeAnalyze({ fields: headerRow, rows: rows }); var fields = getFieldsFromData(sample, headerRow); var parsedRows = parseRowsByFields(rows, fields); return { fields: fields, rows: parsedRows }; } /** * Parse rows of csv by analyzed field types. So that `'1'` -> `1`, `'True'` -> `true` * @param {Array<Array>} rows * @param {Array<Object>} fields */ function parseRowsByFields(rows, fields) { // Edit rows in place var geojsonFieldIdx = fields.findIndex(function (f) { return f.name === '_geojson'; }); fields.forEach(parseCsvRowsByFieldType.bind(null, rows, geojsonFieldIdx)); return rows; } /** * Getting sample data for analyzing field type. * * @type {typeof import('./data-processor').getSampleForTypeAnalyze} */ function getSampleForTypeAnalyze(_ref) { var fields = _ref.fields, rows = _ref.rows, _ref$sampleCount = _ref.sampleCount, sampleCount = _ref$sampleCount === void 0 ? 50 : _ref$sampleCount; var total = Math.min(sampleCount, rows.length); // const fieldOrder = fields.map(f => f.name); var sample = (0, _d3Array.range)(0, total, 1).map(function (d) { return {}; }); // collect sample data for each field fields.forEach(function (field, fieldIdx) { // data counter var i = 0; // sample counter var j = 0; while (j < total) { if (i >= rows.length) { // if depleted data pool sample[j][field] = null; j++; } else if ((0, _dataUtils.notNullorUndefined)(rows[i][fieldIdx])) { var value = rows[i][fieldIdx]; sample[j][field] = typeof value === 'string' ? value.trim() : value; j++; i++; } else { i++; } } }); return sample; } /** * Convert falsy value in csv including `'', 'null', 'NULL', 'Null', 'NaN'` to `null`, * so that type-analyzer won't detect it as string * * @param {Array<Array>} rows */ function cleanUpFalsyCsvValue(rows) { var re = new RegExp(CSV_NULLS, 'g'); for (var i = 0; i < rows.length; i++) { for (var j = 0; j < rows[i].length; j++) { // analyzer will set any fields to 'string' if there are empty values // which will be parsed as '' by d3.csv // here we parse empty data as null // TODO: create warning when deltect `CSV_NULLS` in the data if (typeof rows[i][j] === 'string' && rows[i][j].match(re)) { rows[i][j] = null; } } } } /** * Process uploaded csv file to parse value by field type * * @param rows * @param geoFieldIdx field index * @param field * @param i * @type {typeof import('./data-processor').parseCsvRowsByFieldType} */ function parseCsvRowsByFieldType(rows, geoFieldIdx, field, i) { var parser = PARSE_FIELD_VALUE_FROM_STRING[field.type]; if (parser) { // check first not null value of it's already parsed var first = rows.find(function (r) { return (0, _dataUtils.notNullorUndefined)(r[i]); }); if (!first || parser.valid(first[i], field)) { return; } rows.forEach(function (row) { // parse string value based on field type if (row[i] !== null) { row[i] = parser.parse(row[i], field); if (geoFieldIdx > -1 && row[geoFieldIdx] && row[geoFieldIdx].properties) { row[geoFieldIdx].properties[field.name] = row[i]; } } }); } } /** * Analyze field types from data in `string` format, e.g. uploaded csv. * Assign `type`, `fieldIdx` and `format` (timestamp only) to each field * * @param data array of row object * @param fieldOrder array of field names as string * @returns formatted fields * @type {typeof import('./data-processor').getFieldsFromData} * @public * @example * * import {getFieldsFromData} from 'kepler.gl/processors'; * const data = [{ * time: '2016-09-17 00:09:55', * value: '4', * surge: '1.2', * isTrip: 'true', * zeroOnes: '0' * }, { * time: '2016-09-17 00:30:08', * value: '3', * surge: null, * isTrip: 'false', * zeroOnes: '1' * }, { * time: null, * value: '2', * surge: '1.3', * isTrip: null, * zeroOnes: '1' * }]; * * const fieldOrder = ['time', 'value', 'surge', 'isTrip', 'zeroOnes']; * const fields = getFieldsFromData(data, fieldOrder); * // fields = [ * // {name: 'time', format: 'YYYY-M-D H:m:s', fieldIdx: 1, type: 'timestamp'}, * // {name: 'value', format: '', fieldIdx: 4, type: 'integer'}, * // {name: 'surge', format: '', fieldIdx: 5, type: 'real'}, * // {name: 'isTrip', format: '', fieldIdx: 6, type: 'boolean'}, * // {name: 'zeroOnes', format: '', fieldIdx: 7, type: 'integer'}]; * */ function getFieldsFromData(data, fieldOrder) { // add a check for epoch timestamp var metadata = _typeAnalyzer.Analyzer.computeColMeta(data, [{ regex: /.*geojson|all_points/g, dataType: 'GEOMETRY' }, { regex: /.*census/g, dataType: 'STRING' }], { ignoredDataTypes: IGNORE_DATA_TYPES }); var _renameDuplicateField = renameDuplicateFields(fieldOrder), fieldByIndex = _renameDuplicateField.fieldByIndex; var result = fieldOrder.map(function (field, index) { var name = fieldByIndex[index]; var fieldMeta = metadata.find(function (m) { return m.key === field; }); var _ref2 = fieldMeta || {}, type = _ref2.type, format = _ref2.format; return { name: name, id: name, displayName: name, format: format, fieldIdx: index, type: analyzerTypeToFieldType(type), analyzerType: type, valueAccessor: function valueAccessor(dc) { return function (d) { return dc.valueAt(d.index, index); }; } }; }); // @ts-ignore return result; } /** * pass in an array of field names, rename duplicated one * and return a map from old field index to new name * * @param {Array} fieldOrder * @returns {Object} new field name by index */ function renameDuplicateFields(fieldOrder) { return fieldOrder.reduce(function (accu, field, i) { var allNames = accu.allNames; var fieldName = field; // add a counter to duplicated names if (allNames.includes(field)) { var counter = 0; while (allNames.includes("".concat(field, "-").concat(counter))) { counter++; } fieldName = "".concat(field, "-").concat(counter); } accu.fieldByIndex[i] = fieldName; accu.allNames.push(fieldName); return accu; }, { allNames: [], fieldByIndex: {} }); } /** * Convert type-analyzer output to kepler.gl field types * * @param aType * @returns corresponding type in `ALL_FIELD_TYPES` * @type {typeof import('./data-processor').analyzerTypeToFieldType}} */ /* eslint-disable complexity */ function analyzerTypeToFieldType(aType) { var DATE = _typeAnalyzer.DATA_TYPES.DATE, TIME = _typeAnalyzer.DATA_TYPES.TIME, DATETIME = _typeAnalyzer.DATA_TYPES.DATETIME, NUMBER = _typeAnalyzer.DATA_TYPES.NUMBER, INT = _typeAnalyzer.DATA_TYPES.INT, FLOAT = _typeAnalyzer.DATA_TYPES.FLOAT, BOOLEAN = _typeAnalyzer.DATA_TYPES.BOOLEAN, STRING = _typeAnalyzer.DATA_TYPES.STRING, GEOMETRY = _typeAnalyzer.DATA_TYPES.GEOMETRY, GEOMETRY_FROM_STRING = _typeAnalyzer.DATA_TYPES.GEOMETRY_FROM_STRING, PAIR_GEOMETRY_FROM_STRING = _typeAnalyzer.DATA_TYPES.PAIR_GEOMETRY_FROM_STRING, ZIPCODE = _typeAnalyzer.DATA_TYPES.ZIPCODE, ARRAY = _typeAnalyzer.DATA_TYPES.ARRAY, OBJECT = _typeAnalyzer.DATA_TYPES.OBJECT; // TODO: un recognized types // CURRENCY PERCENT NONE switch (aType) { case DATE: return _defaultSettings.ALL_FIELD_TYPES.date; case TIME: case DATETIME: return _defaultSettings.ALL_FIELD_TYPES.timestamp; case FLOAT: return _defaultSettings.ALL_FIELD_TYPES.real; case INT: return _defaultSettings.ALL_FIELD_TYPES.integer; case BOOLEAN: return _defaultSettings.ALL_FIELD_TYPES["boolean"]; case GEOMETRY: case GEOMETRY_FROM_STRING: case PAIR_GEOMETRY_FROM_STRING: case ARRAY: case OBJECT: // TODO: create a new data type for objects and arrays return _defaultSettings.ALL_FIELD_TYPES.geojson; case NUMBER: case STRING: case ZIPCODE: return _defaultSettings.ALL_FIELD_TYPES.string; default: _window.console.warn("Unsupported analyzer type: ".concat(aType)); return _defaultSettings.ALL_FIELD_TYPES.string; } } /* eslint-enable complexity */ /** * Process data where each row is an object, output can be passed to [`addDataToMap`](../actions/actions.md#adddatatomap) * NOTE: This function may mutate input. * @param rawData an array of row object, each object should have the same number of keys * @returns dataset containing `fields` and `rows` * @type {typeof import('./data-processor').processRowObject} * @public * @example * import {addDataToMap} from 'kepler.gl/actions'; * import {processRowObject} from 'kepler.gl/processors'; * * const data = [ * {lat: 31.27, lng: 127.56, value: 3}, * {lat: 31.22, lng: 126.26, value: 1} * ]; * * dispatch(addDataToMap({ * datasets: { * info: {label: 'My Data', id: 'my_data'}, * data: processRowObject(data) * } * })); */ function processRowObject(rawData) { if (!Array.isArray(rawData) || !rawData.length) { return null; } var keys = Object.keys(rawData[0]); var rows = rawData.map(function (d) { return keys.map(function (key) { return d[key]; }); }); // row object an still contain values like `Null` or `N/A` cleanUpFalsyCsvValue(rows); return processCsvData(rows, keys); } /** * Process GeoJSON [`FeatureCollection`](http://wiki.geojson.org/GeoJSON_draft_version_6#FeatureCollection), * output a data object with `{fields: [], rows: []}`. * The data object can be wrapped in a `dataset` and passed to [`addDataToMap`](../actions/actions.md#adddatatomap) * NOTE: This function may mutate input. * * @param rawData raw geojson feature collection * @returns dataset containing `fields` and `rows` * @type {typeof import('./data-processor').processGeojson} * @public * @example * import {addDataToMap} from 'kepler.gl/actions'; * import {processGeojson} from 'kepler.gl/processors'; * * const geojson = { * "type" : "FeatureCollection", * "features" : [{ * "type" : "Feature", * "properties" : { * "capacity" : "10", * "type" : "U-Rack" * }, * "geometry" : { * "type" : "Point", * "coordinates" : [ -71.073283, 42.417500 ] * } * }] * }; * * dispatch(addDataToMap({ * datasets: { * info: { * label: 'Sample Taxi Trips in New York City', * id: 'test_trip_data' * }, * data: processGeojson(geojson) * } * })); */ function processGeojson(rawData) { var normalizedGeojson = (0, _geojsonNormalize["default"])(rawData); if (!normalizedGeojson || !Array.isArray(normalizedGeojson.features)) { var error = new Error("Read File Failed: File is not a valid GeoJSON. Read more about [supported file format](".concat(_userGuides.GUIDES_FILE_FORMAT_DOC, ")")); throw error; // fail to normalize geojson } // getting all feature fields var allDataRows = []; for (var i = 0; i < normalizedGeojson.features.length; i++) { var f = normalizedGeojson.features[i]; if (f.geometry) { allDataRows.push(_objectSpread({ // add feature to _geojson field _geojson: f }, f.properties || {})); } } // get all the field var fields = allDataRows.reduce(function (prev, curr) { Object.keys(curr).forEach(function (key) { if (!prev.includes(key)) { prev.push(key); } }); return prev; }, []); // make sure each feature has exact same fields allDataRows.forEach(function (d) { fields.forEach(function (f) { if (!(f in d)) { d[f] = null; d._geojson.properties[f] = null; } }); }); return processRowObject(allDataRows); } /** * On export data to csv * @param {import('utils/table-utils/data-container-interface').DataContainerInterface} dataContainer * @param {Array<Object>} fields `dataset.fields` * @returns {string} csv string */ function formatCsv(dataContainer, fields) { var columns = fields.map(function (f) { return f.displayName || f.name; }); var formattedData = [columns]; // parse geojson object as string var _iterator = _createForOfIteratorHelper(dataContainer.rows(true)), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { var row = _step.value; formattedData.push(row.map(function (d, i) { return (0, _dataUtils.parseFieldValue)(d, fields[i].type); })); } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } return (0, _d3Dsv.csvFormatRows)(formattedData); } /** * Validate input data, adding missing field types, rename duplicate columns * @type {typeof import('./data-processor').validateInputData} */ function validateInputData(data) { if (!(0, _utils.isPlainObject)(data)) { (0, _assert["default"])('addDataToMap Error: dataset.data cannot be null'); return null; } else if (!Array.isArray(data.fields)) { (0, _assert["default"])('addDataToMap Error: expect dataset.data.fields to be an array'); return null; } else if (!Array.isArray(data.rows)) { (0, _assert["default"])('addDataToMap Error: expect dataset.data.rows to be an array'); return null; } var fields = data.fields, rows = data.rows; // check if all fields has name, format and type var allValid = fields.every(function (f, i) { if (!(0, _utils.isPlainObject)(f)) { (0, _assert["default"])("fields needs to be an array of object, but find ".concat((0, _typeof2["default"])(f))); fields[i] = {}; } if (!f.name) { (0, _assert["default"])("field.name is required but missing in ".concat(JSON.stringify(f))); // assign a name fields[i].name = "column_".concat(i); } if (!_defaultSettings.ALL_FIELD_TYPES[f.type]) { (0, _assert["default"])("unknown field type ".concat(f.type)); return false; } if (!fields.every(function (field) { return field.analyzerType; })) { (0, _assert["default"])('field missing analyzerType'); return false; } // check time format is correct based on first 10 not empty element if (f.type === _defaultSettings.ALL_FIELD_TYPES.timestamp) { var sample = findNonEmptyRowsAtField(rows, i, 10).map(function (r) { return { ts: r[i] }; }); var analyzedType = _typeAnalyzer.Analyzer.computeColMeta(sample)[0]; return analyzedType && analyzedType.category === 'TIME' && analyzedType.format === f.format; } return true; }); if (allValid) { return { rows: rows, fields: fields }; } // if any field has missing type, recalculate it for everyone // because we simply lost faith in humanity var sampleData = getSampleForTypeAnalyze({ fields: fields.map(function (f) { return f.name; }), rows: rows }); var fieldOrder = fields.map(function (f) { return f.name; }); var meta = getFieldsFromData(sampleData, fieldOrder); var updatedFields = fields.map(function (f, i) { return _objectSpread(_objectSpread({}, f), {}, { type: meta[i].type, format: meta[i].format, analyzerType: meta[i].analyzerType }); }); return { fields: updatedFields, rows: rows }; } function findNonEmptyRowsAtField(rows, fieldIdx, total) { var sample = []; var i = 0; while (sample.length < total && i < rows.length) { if ((0, _dataUtils.notNullorUndefined)(rows[i][fieldIdx])) { sample.push(rows[i]); } i++; } return sample; } /** * Process saved kepler.gl json to be pass to [`addDataToMap`](../actions/actions.md#adddatatomap). * The json object should contain `datasets` and `config`. * @param {Object} rawData * @param {Array} rawData.datasets * @param {Object} rawData.config * @returns {Object} datasets and config `{datasets: {}, config: {}}` * @public * @example * import {addDataToMap} from 'kepler.gl/actions'; * import {processKeplerglJSON} from 'kepler.gl/processors'; * * dispatch(addDataToMap(processKeplerglJSON(keplerGlJson))); */ function processKeplerglJSON(rawData) { return rawData ? _schemas["default"].load(rawData.datasets, rawData.config) : null; } /** * Parse a single or an array of datasets saved using kepler.gl schema * @param {Array | Array<Object>} rawData */ function processKeplerglDataset(rawData) { if (!rawData) { return null; } var results = _schemas["default"].parseSavedData((0, _utils.toArray)(rawData)); if (!results) { return null; } return Array.isArray(rawData) ? results : results[0]; } var DATASET_HANDLERS = (_DATASET_HANDLERS = {}, (0, _defineProperty2["default"])(_DATASET_HANDLERS, _defaultSettings.DATASET_FORMATS.row, processRowObject), (0, _defineProperty2["default"])(_DATASET_HANDLERS, _defaultSettings.DATASET_FORMATS.geojson, processGeojson), (0, _defineProperty2["default"])(_DATASET_HANDLERS, _defaultSettings.DATASET_FORMATS.csv, processCsvData), (0, _defineProperty2["default"])(_DATASET_HANDLERS, _defaultSettings.DATASET_FORMATS.keplergl, processKeplerglDataset), _DATASET_HANDLERS); exports.DATASET_HANDLERS = DATASET_HANDLERS; var Processors = { processGeojson: processGeojson, processCsvData: processCsvData, processRowObject: processRowObject, processKeplerglJSON: processKeplerglJSON, processKeplerglDataset: processKeplerglDataset, analyzerTypeToFieldType: analyzerTypeToFieldType, getFieldsFromData: getFieldsFromData, parseCsvRowsByFieldType: parseCsvRowsByFieldType, formatCsv: formatCsv }; exports.Processors = Processors; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9wcm9jZXNzb3JzL2RhdGEtcHJvY2Vzc29yLmpzIl0sIm5hbWVzIjpbIkFDQ0VQVEVEX0FOQUxZWkVSX1RZUEVTIiwiQW5hbHl6ZXJEQVRBX1RZUEVTIiwiREFURSIsIlRJTUUiLCJEQVRFVElNRSIsIk5VTUJFUiIsIklOVCIsIkZMT0FUIiwiQk9PTEVBTiIsIlNUUklORyIsIkdFT01FVFJZIiwiR0VPTUVUUllfRlJPTV9TVFJJTkciLCJQQUlSX0dFT01FVFJZX0ZST01fU1RSSU5HIiwiWklQQ09ERSIsIkFSUkFZIiwiT0JKRUNUIiwiQ1NWX05VTExTIiwiSUdOT1JFX0RBVEFfVFlQRVMiLCJPYmplY3QiLCJrZXlzIiwiZmlsdGVyIiwidHlwZSIsImluY2x1ZGVzIiwiUEFSU0VfRklFTERfVkFMVUVfRlJPTV9TVFJJTkciLCJBTExfRklFTERfVFlQRVMiLCJ2YWxpZCIsImQiLCJwYXJzZSIsImludGVnZXIiLCJwYXJzZUludCIsInRpbWVzdGFtcCIsImZpZWxkIiwiZm9ybWF0IiwiTnVtYmVyIiwicmVhbCIsInBhcnNlRmxvYXQiLCJwcm9jZXNzQ3N2RGF0YSIsInJhd0RhdGEiLCJoZWFkZXIiLCJyb3dzIiwiaGVhZGVyUm93IiwicGFyc2VkUm93cyIsIkFycmF5IiwiaXNBcnJheSIsImxlbmd0aCIsIkVycm9yIiwic2xpY2UiLCJjbGVhblVwRmFsc3lDc3ZWYWx1ZSIsInNhbXBsZSIsImdldFNhbXBsZUZvclR5cGVBbmFseXplIiwiZmllbGRzIiwiZ2V0RmllbGRzRnJvbURhdGEiLCJwYXJzZVJvd3NCeUZpZWxkcyIsImdlb2pzb25GaWVsZElkeCIsImZpbmRJbmRleCIsImYiLCJuYW1lIiwiZm9yRWFjaCIsInBhcnNlQ3N2Um93c0J5RmllbGRUeXBlIiwiYmluZCIsInNhbXBsZUNvdW50IiwidG90YWwiLCJNYXRoIiwibWluIiwibWFwIiwiZmllbGRJZHgiLCJpIiwiaiIsInZhbHVlIiwidHJpbSIsInJlIiwiUmVnRXhwIiwibWF0Y2giLCJnZW9GaWVsZElkeCIsInBhcnNlciIsImZpcnN0IiwiZmluZCIsInIiLCJyb3ciLCJwcm9wZXJ0aWVzIiwiZGF0YSIsImZpZWxkT3JkZXIiLCJtZXRhZGF0YSIsIkFuYWx5emVyIiwiY29tcHV0ZUNvbE1ldGEiLCJyZWdleCIsImRhdGFUeXBlIiwiaWdub3JlZERhdGFUeXBlcyIsInJlbmFtZUR1cGxpY2F0ZUZpZWxkcyIsImZpZWxkQnlJbmRleCIsInJlc3VsdCIsImluZGV4IiwiZmllbGRNZXRhIiwibSIsImtleSIsImlkIiwiZGlzcGxheU5hbWUiLCJhbmFseXplclR5cGVUb0ZpZWxkVHlwZSIsImFuYWx5emVyVHlwZSIsInZhbHVlQWNjZXNzb3IiLCJkYyIsInZhbHVlQXQiLCJyZWR1Y2UiLCJhY2N1IiwiYWxsTmFtZXMiLCJmaWVsZE5hbWUiLCJjb3VudGVyIiwicHVzaCIsImFUeXBlIiwiZGF0ZSIsImdlb2pzb24iLCJzdHJpbmciLCJnbG9iYWxDb25zb2xlIiwid2FybiIsInByb2Nlc3NSb3dPYmplY3QiLCJwcm9jZXNzR2VvanNvbiIsIm5vcm1hbGl6ZWRHZW9qc29uIiwiZmVhdHVyZXMiLCJlcnJvciIsIkdVSURFU19GSUxFX0ZPUk1BVF9ET0MiLCJhbGxEYXRhUm93cyIsImdlb21ldHJ5IiwiX2dlb2pzb24iLCJwcmV2IiwiY3VyciIsImZvcm1hdENzdiIsImRhdGFDb250YWluZXIiLCJjb2x1bW5zIiwiZm9ybWF0dGVkRGF0YSIsInZhbGlkYXRlSW5wdXREYXRhIiwiYWxsVmFsaWQiLCJldmVyeSIsIkpTT04iLCJzdHJpbmdpZnkiLCJmaW5kTm9uRW1wdHlSb3dzQXRGaWVsZCIsInRzIiwiYW5hbHl6ZWRUeXBlIiwiY2F0ZWdvcnkiLCJzYW1wbGVEYXRhIiwibWV0YSIsInVwZGF0ZWRGaWVsZHMiLCJwcm9jZXNzS2VwbGVyZ2xKU09OIiwiS2VwbGVyR2xTY2hlbWEiLCJsb2FkIiwiZGF0YXNldHMiLCJjb25maWciLCJwcm9jZXNzS2VwbGVyZ2xEYXRhc2V0IiwicmVzdWx0cyIsInBhcnNlU2F2ZWREYXRhIiwiREFUQVNFVF9IQU5ETEVSUyIsIkRBVEFTRVRfRk9STUFUUyIsImNzdiIsImtlcGxlcmdsIiwiUHJvY2Vzc29ycyJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFvQkE7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7Ozs7Ozs7Ozs7Ozs7O0FBRU8sSUFBTUEsdUJBQXVCLEdBQUcsQ0FDckNDLHlCQUFtQkMsSUFEa0IsRUFFckNELHlCQUFtQkUsSUFGa0IsRUFHckNGLHlCQUFtQkcsUUFIa0IsRUFJckNILHlCQUFtQkksTUFKa0IsRUFLckNKLHlCQUFtQkssR0FMa0IsRUFNckNMLHlCQUFtQk0sS0FOa0IsRUFPckNOLHlCQUFtQk8sT0FQa0IsRUFRckNQLHlCQUFtQlEsTUFSa0IsRUFTckNSLHlCQUFtQlMsUUFUa0IsRUFVckNULHlCQUFtQlUsb0JBVmtCLEVBV3JDVix5QkFBbUJXLHlCQVhrQixFQVlyQ1gseUJBQW1CWSxPQVprQixFQWFyQ1oseUJBQW1CYSxLQWJrQixFQWNyQ2IseUJBQW1CYyxNQWRrQixDQUFoQyxDLENBaUJQO0FBQ0E7QUFDQTs7O0FBQ08sSUFBTUMsU0FBUyxHQUFHLDhCQUFsQjs7QUFFUCxJQUFNQyxpQkFBaUIsR0FBR0MsTUFBTSxDQUFDQyxJQUFQLENBQVlsQix3QkFBWixFQUFnQ21CLE1BQWhDLENBQ3hCLFVBQUFDLElBQUk7QUFBQSxTQUFJLENBQUNyQix1QkFBdUIsQ0FBQ3NCLFFBQXhCLENBQWlDRCxJQUFqQyxDQUFMO0FBQUEsQ0FEb0IsQ0FBMUI7QUFJTyxJQUFNRSw2QkFBNkIsd0ZBQ3ZDQywyQ0FEdUMsRUFDYjtBQUN6QkMsRUFBQUEsS0FBSyxFQUFFLGVBQUFDLENBQUM7QUFBQSxXQUFJLE9BQU9BLENBQVAsS0FBYSxTQUFqQjtBQUFBLEdBRGlCO0FBRXpCQyxFQUFBQSxLQUFLLEVBQUUsZUFBQUQsQ0FBQztBQUFBLFdBQUlBLENBQUMsS0FBSyxN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