covutils
Version:
Utilities for creating, transforming, and handling Coverage Data objects.
308 lines (261 loc) • 11.2 kB
JavaScript
;
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);
});
}