UNPKG

covutils

Version:

Utilities for creating, transforming, and handling Coverage Data objects.

308 lines (261 loc) 11.2 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); exports.subsetByBbox = subsetByBbox; exports.subsetByIndex = subsetByIndex; exports.subsetByValue = subsetByValue; var _referencing = require('../domain/referencing.js'); var _subset = require('../domain/subset.js'); var _array = require('../array.js'); var _constants = require('../constants.js'); function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } /** * Returns a copy of the grid coverage subsetted to the given bounding box. * * Any grid cell is included which intersects with the bounding box. * * @param {Coverage} cov A Coverage object with domain Grid. * @param {array} bbox [xmin,ymin,xmax,ymax] in native CRS coordinates. * @param {array} [axes=['x','y']] Axis names [x,y]. * @returns {Promise<Coverage>} A promise with a Coverage object as result. */ function subsetByBbox(cov, bbox) { var _cov$subsetByValue; var axes = arguments.length <= 2 || arguments[2] === undefined ? ['x', 'y'] : arguments[2]; var _bbox = _slicedToArray(bbox, 4); var xmin = _bbox[0]; var ymin = _bbox[1]; var xmax = _bbox[2]; var ymax = _bbox[3]; return cov.subsetByValue((_cov$subsetByValue = {}, _defineProperty(_cov$subsetByValue, axes[0], { start: xmin, stop: xmax }), _defineProperty(_cov$subsetByValue, axes[1], { start: ymin, stop: ymax }), _cov$subsetByValue)); } /** * Generic subsetByIndex function that can be used when building new Coverage objects. * * @example * var cov = { * type: 'Coverage', * ... * subsetByIndex: constraints => CovUtils.subsetByIndex(cov, constraints) * } */ function subsetByIndex(cov, constraints) { return cov.loadDomain().then(function (domain) { constraints = (0, _subset.normalizeIndexSubsetConstraints)(domain, constraints); var newdomain = (0, _subset.subsetDomainByIndex)(domain, constraints); // subset ranges (on request) var rangeWrapper = function rangeWrapper(range) { var newrange = { dataType: range.dataType, get: function get(obj) { // translate subsetted to original indices var newobj = {}; var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = Object.keys(obj)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var axisName = _step.value; var _constraints$axisName = constraints[axisName]; var start = _constraints$axisName.start; var step = _constraints$axisName.step; newobj[axisName] = start + obj[axisName] * step; } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } return range.get(newobj); } }; newrange.shape = new Map(); var _iteratorNormalCompletion2 = true; var _didIteratorError2 = false; var _iteratorError2 = undefined; try { for (var _iterator2 = domain.axes.keys()[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { var axisName = _step2.value; var size = newdomain.axes.get(axisName).values.length; newrange.shape.set(axisName, size); } } catch (err) { _didIteratorError2 = true; _iteratorError2 = err; } finally { try { if (!_iteratorNormalCompletion2 && _iterator2.return) { _iterator2.return(); } } finally { if (_didIteratorError2) { throw _iteratorError2; } } } return newrange; }; var loadRange = function loadRange(key) { return cov.loadRange(key).then(rangeWrapper); }; var loadRanges = function loadRanges(keys) { return cov.loadRanges(keys).then(function (ranges) { return new Map([].concat(_toConsumableArray(ranges)).map(function (_ref) { var _ref2 = _slicedToArray(_ref, 2); var key = _ref2[0]; var range = _ref2[1]; return [key, rangeWrapper(range)]; })); }); }; // assemble everything to a new coverage var newcov = { type: _constants.COVERAGE, domainType: cov.domainType, parameters: cov.parameters, loadDomain: function loadDomain() { return Promise.resolve(newdomain); }, loadRange: loadRange, loadRanges: loadRanges }; newcov.subsetByIndex = subsetByIndex.bind(null, newcov); newcov.subsetByValue = subsetByValue.bind(null, newcov); return newcov; }); } /** * Generic subsetByValue function that can be used when building new Coverage objects. * Requires cov.subsetByIndex function. * * @example * var cov = { * type: 'Coverage', * ... * subsetByValue: constraints => CovUtils.subsetByValue(cov, constraints) * } */ function subsetByValue(cov, constraints) { return cov.loadDomain().then(function (domain) { // calculate indices and use subsetByIndex var indexConstraints = {}; var _iteratorNormalCompletion3 = true; var _didIteratorError3 = false; var _iteratorError3 = undefined; try { for (var _iterator3 = Object.keys(constraints)[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { var axisName = _step3.value; var spec = constraints[axisName]; if (spec === undefined || spec === null || !domain.axes.has(axisName)) { continue; } var axis = domain.axes.get(axisName); var vals = axis.values; // special-case handling var isISODate = (0, _referencing.isISODateAxis)(domain, axisName); var isLongitude = (0, _referencing.isLongitudeAxis)(domain, axisName); // wrap input longitudes into longitude range of domain axis var lonWrapper = isLongitude ? (0, _referencing.getLongitudeWrapper)(domain, axisName) : undefined; if (typeof spec === 'number' || typeof spec === 'string' || spec instanceof Date) { var match = spec; if (isISODate) { // convert times to numbers before searching match = (0, _referencing.asTime)(match); vals = vals.map(function (v) { return new Date(v).getTime(); }); } else if (isLongitude) { match = lonWrapper(match); } var i = void 0; // older browsers don't have TypedArray.prototype.indexOf if (vals.indexOf) { i = vals.indexOf(match); } else { i = Array.prototype.indexOf.call(vals, match); } if (i === -1) { throw new Error('Domain value not found: ' + spec); } indexConstraints[axisName] = i; } else if ('target' in spec) { // find index of value closest to target var target = spec.target; if (isISODate) { // convert times to numbers before searching target = (0, _referencing.asTime)(target); vals = vals.map(function (v) { return new Date(v).getTime(); }); } else if (isLongitude) { target = lonWrapper(target); } else if (typeof vals[0] !== 'number' || typeof target !== 'number') { throw new Error('Invalid axis or constraint value type'); } var _i = (0, _array.indexOfNearest)(vals, target); indexConstraints[axisName] = _i; } else if ('start' in spec && 'stop' in spec) { // TODO what about bounds? var start = spec.start; var stop = spec.stop; if (isISODate) { var _ref3 = [(0, _referencing.asTime)(start), (0, _referencing.asTime)(stop)]; // convert times to numbers before searching start = _ref3[0]; stop = _ref3[1]; vals = vals.map(function (v) { return new Date(v).getTime(); }); } else if (isLongitude) { var _ref4 = [lonWrapper(start), lonWrapper(stop)]; start = _ref4[0]; stop = _ref4[1]; } else if (typeof vals[0] !== 'number' || typeof start !== 'number') { throw new Error('Invalid axis or constraint value type'); } var _indicesOfNearest = (0, _array.indicesOfNearest)(vals, start); var _indicesOfNearest2 = _slicedToArray(_indicesOfNearest, 2); var lo1 = _indicesOfNearest2[0]; var hi1 = _indicesOfNearest2[1]; var _indicesOfNearest3 = (0, _array.indicesOfNearest)(vals, stop); var _indicesOfNearest4 = _slicedToArray(_indicesOfNearest3, 2); var lo2 = _indicesOfNearest4[0]; var hi2 = _indicesOfNearest4[1]; // cov is a bit arbitrary and may include one or two indices too much // (but since we don't handle bounds it doesn't matter that much) var imin = Math.min(lo1, hi1, lo2, hi2); var imax = Math.max(lo1, hi1, lo2, hi2) + 1; // subsetByIndex is exclusive indexConstraints[axisName] = { start: imin, stop: imax }; } else { throw new Error('Invalid subset constraints'); } } } catch (err) { _didIteratorError3 = true; _iteratorError3 = err; } finally { try { if (!_iteratorNormalCompletion3 && _iterator3.return) { _iterator3.return(); } } finally { if (_didIteratorError3) { throw _iteratorError3; } } } return cov.subsetByIndex(indexConstraints); }); }