UNPKG

cione-comp-lib

Version:

`$ yarn add cione-comp-lib` 或者 `$ npm i cione-comp-lib -S`

767 lines (766 loc) 24.7 kB
import { map, keys, reduce, clone, createHashMap } from "../../../zrender/lib/core/util.mjs"; import { parseDataValue } from "./helper/dataValueHelper.mjs"; import { shouldRetrieveDataByName } from "./Source.mjs"; var UNDEFINED = "undefined"; var CtorUint32Array = typeof Uint32Array === UNDEFINED ? Array : Uint32Array; var CtorUint16Array = typeof Uint16Array === UNDEFINED ? Array : Uint16Array; var CtorInt32Array = typeof Int32Array === UNDEFINED ? Array : Int32Array; var CtorFloat64Array = typeof Float64Array === UNDEFINED ? Array : Float64Array; var dataCtors = { "float": CtorFloat64Array, "int": CtorInt32Array, "ordinal": Array, "number": Array, "time": CtorFloat64Array }; var defaultDimValueGetters; function getIndicesCtor(rawCount) { return rawCount > 65535 ? CtorUint32Array : CtorUint16Array; } function getInitialExtent() { return [Infinity, -Infinity]; } function cloneChunk(originalChunk) { var Ctor = originalChunk.constructor; return Ctor === Array ? originalChunk.slice() : new Ctor(originalChunk); } function prepareStore(store, dimIdx, dimType, end, append) { var DataCtor = dataCtors[dimType || "float"]; if (append) { var oldStore = store[dimIdx]; var oldLen = oldStore && oldStore.length; if (!(oldLen === end)) { var newStore = new DataCtor(end); for (var j = 0; j < oldLen; j++) { newStore[j] = oldStore[j]; } store[dimIdx] = newStore; } } else { store[dimIdx] = new DataCtor(end); } } var DataStore = function() { function DataStore2() { this._chunks = []; this._rawExtent = []; this._extent = []; this._count = 0; this._rawCount = 0; this._calcDimNameToIdx = createHashMap(); } DataStore2.prototype.initData = function(provider, inputDimensions, dimValueGetter) { this._provider = provider; this._chunks = []; this._indices = null; this.getRawIndex = this._getRawIdxIdentity; var source = provider.getSource(); var defaultGetter = this.defaultDimValueGetter = defaultDimValueGetters[source.sourceFormat]; this._dimValueGetter = dimValueGetter || defaultGetter; this._rawExtent = []; shouldRetrieveDataByName(source); this._dimensions = map(inputDimensions, function(dim) { return { type: dim.type, property: dim.property }; }); this._initDataFromProvider(0, provider.count()); }; DataStore2.prototype.getProvider = function() { return this._provider; }; DataStore2.prototype.getSource = function() { return this._provider.getSource(); }; DataStore2.prototype.ensureCalculationDimension = function(dimName, type) { var calcDimNameToIdx = this._calcDimNameToIdx; var dimensions = this._dimensions; var calcDimIdx = calcDimNameToIdx.get(dimName); if (calcDimIdx != null) { if (dimensions[calcDimIdx].type === type) { return calcDimIdx; } } else { calcDimIdx = dimensions.length; } dimensions[calcDimIdx] = { type }; calcDimNameToIdx.set(dimName, calcDimIdx); this._chunks[calcDimIdx] = new dataCtors[type || "float"](this._rawCount); this._rawExtent[calcDimIdx] = getInitialExtent(); return calcDimIdx; }; DataStore2.prototype.collectOrdinalMeta = function(dimIdx, ordinalMeta) { var chunk = this._chunks[dimIdx]; var dim = this._dimensions[dimIdx]; var rawExtents = this._rawExtent; var offset = dim.ordinalOffset || 0; var len = chunk.length; if (offset === 0) { rawExtents[dimIdx] = getInitialExtent(); } var dimRawExtent = rawExtents[dimIdx]; for (var i = offset; i < len; i++) { var val = chunk[i] = ordinalMeta.parseAndCollect(chunk[i]); if (!isNaN(val)) { dimRawExtent[0] = Math.min(val, dimRawExtent[0]); dimRawExtent[1] = Math.max(val, dimRawExtent[1]); } } dim.ordinalMeta = ordinalMeta; dim.ordinalOffset = len; dim.type = "ordinal"; }; DataStore2.prototype.getOrdinalMeta = function(dimIdx) { var dimInfo = this._dimensions[dimIdx]; var ordinalMeta = dimInfo.ordinalMeta; return ordinalMeta; }; DataStore2.prototype.getDimensionProperty = function(dimIndex) { var item = this._dimensions[dimIndex]; return item && item.property; }; DataStore2.prototype.appendData = function(data) { var provider = this._provider; var start = this.count(); provider.appendData(data); var end = provider.count(); if (!provider.persistent) { end += start; } if (start < end) { this._initDataFromProvider(start, end, true); } return [start, end]; }; DataStore2.prototype.appendValues = function(values, minFillLen) { var chunks = this._chunks; var dimensions = this._dimensions; var dimLen = dimensions.length; var rawExtent = this._rawExtent; var start = this.count(); var end = start + Math.max(values.length, minFillLen || 0); for (var i = 0; i < dimLen; i++) { var dim = dimensions[i]; prepareStore(chunks, i, dim.type, end, true); } var emptyDataItem = []; for (var idx = start; idx < end; idx++) { var sourceIdx = idx - start; for (var dimIdx = 0; dimIdx < dimLen; dimIdx++) { var dim = dimensions[dimIdx]; var val = defaultDimValueGetters.arrayRows.call(this, values[sourceIdx] || emptyDataItem, dim.property, sourceIdx, dimIdx); chunks[dimIdx][idx] = val; var dimRawExtent = rawExtent[dimIdx]; val < dimRawExtent[0] && (dimRawExtent[0] = val); val > dimRawExtent[1] && (dimRawExtent[1] = val); } } this._rawCount = this._count = end; return { start, end }; }; DataStore2.prototype._initDataFromProvider = function(start, end, append) { var provider = this._provider; var chunks = this._chunks; var dimensions = this._dimensions; var dimLen = dimensions.length; var rawExtent = this._rawExtent; var dimNames = map(dimensions, function(dim2) { return dim2.property; }); for (var i = 0; i < dimLen; i++) { var dim = dimensions[i]; if (!rawExtent[i]) { rawExtent[i] = getInitialExtent(); } prepareStore(chunks, i, dim.type, end, append); } if (provider.fillStorage) { provider.fillStorage(start, end, chunks, rawExtent); } else { var dataItem = []; for (var idx = start; idx < end; idx++) { dataItem = provider.getItem(idx, dataItem); for (var dimIdx = 0; dimIdx < dimLen; dimIdx++) { var dimStorage = chunks[dimIdx]; var val = this._dimValueGetter(dataItem, dimNames[dimIdx], idx, dimIdx); dimStorage[idx] = val; var dimRawExtent = rawExtent[dimIdx]; val < dimRawExtent[0] && (dimRawExtent[0] = val); val > dimRawExtent[1] && (dimRawExtent[1] = val); } } } if (!provider.persistent && provider.clean) { provider.clean(); } this._rawCount = this._count = end; this._extent = []; }; DataStore2.prototype.count = function() { return this._count; }; DataStore2.prototype.get = function(dim, idx) { if (!(idx >= 0 && idx < this._count)) { return NaN; } var dimStore = this._chunks[dim]; return dimStore ? dimStore[this.getRawIndex(idx)] : NaN; }; DataStore2.prototype.getValues = function(dimensions, idx) { var values = []; var dimArr = []; if (idx == null) { idx = dimensions; dimensions = []; for (var i = 0; i < this._dimensions.length; i++) { dimArr.push(i); } } else { dimArr = dimensions; } for (var i = 0, len = dimArr.length; i < len; i++) { values.push(this.get(dimArr[i], idx)); } return values; }; DataStore2.prototype.getByRawIndex = function(dim, rawIdx) { if (!(rawIdx >= 0 && rawIdx < this._rawCount)) { return NaN; } var dimStore = this._chunks[dim]; return dimStore ? dimStore[rawIdx] : NaN; }; DataStore2.prototype.getSum = function(dim) { var dimData = this._chunks[dim]; var sum = 0; if (dimData) { for (var i = 0, len = this.count(); i < len; i++) { var value = this.get(dim, i); if (!isNaN(value)) { sum += value; } } } return sum; }; DataStore2.prototype.getMedian = function(dim) { var dimDataArray = []; this.each([dim], function(val) { if (!isNaN(val)) { dimDataArray.push(val); } }); var sortedDimDataArray = dimDataArray.sort(function(a, b) { return a - b; }); var len = this.count(); return len === 0 ? 0 : len % 2 === 1 ? sortedDimDataArray[(len - 1) / 2] : (sortedDimDataArray[len / 2] + sortedDimDataArray[len / 2 - 1]) / 2; }; DataStore2.prototype.indexOfRawIndex = function(rawIndex) { if (rawIndex >= this._rawCount || rawIndex < 0) { return -1; } if (!this._indices) { return rawIndex; } var indices = this._indices; var rawDataIndex = indices[rawIndex]; if (rawDataIndex != null && rawDataIndex < this._count && rawDataIndex === rawIndex) { return rawIndex; } var left = 0; var right = this._count - 1; while (left <= right) { var mid = (left + right) / 2 | 0; if (indices[mid] < rawIndex) { left = mid + 1; } else if (indices[mid] > rawIndex) { right = mid - 1; } else { return mid; } } return -1; }; DataStore2.prototype.indicesOfNearest = function(dim, value, maxDistance) { var chunks = this._chunks; var dimData = chunks[dim]; var nearestIndices = []; if (!dimData) { return nearestIndices; } if (maxDistance == null) { maxDistance = Infinity; } var minDist = Infinity; var minDiff = -1; var nearestIndicesLen = 0; for (var i = 0, len = this.count(); i < len; i++) { var dataIndex = this.getRawIndex(i); var diff = value - dimData[dataIndex]; var dist = Math.abs(diff); if (dist <= maxDistance) { if (dist < minDist || dist === minDist && diff >= 0 && minDiff < 0) { minDist = dist; minDiff = diff; nearestIndicesLen = 0; } if (diff === minDiff) { nearestIndices[nearestIndicesLen++] = i; } } } nearestIndices.length = nearestIndicesLen; return nearestIndices; }; DataStore2.prototype.getIndices = function() { var newIndices; var indices = this._indices; if (indices) { var Ctor = indices.constructor; var thisCount = this._count; if (Ctor === Array) { newIndices = new Ctor(thisCount); for (var i = 0; i < thisCount; i++) { newIndices[i] = indices[i]; } } else { newIndices = new Ctor(indices.buffer, 0, thisCount); } } else { var Ctor = getIndicesCtor(this._rawCount); newIndices = new Ctor(this.count()); for (var i = 0; i < newIndices.length; i++) { newIndices[i] = i; } } return newIndices; }; DataStore2.prototype.filter = function(dims, cb) { if (!this._count) { return this; } var newStore = this.clone(); var count = newStore.count(); var Ctor = getIndicesCtor(newStore._rawCount); var newIndices = new Ctor(count); var value = []; var dimSize = dims.length; var offset = 0; var dim0 = dims[0]; var chunks = newStore._chunks; for (var i = 0; i < count; i++) { var keep = void 0; var rawIdx = newStore.getRawIndex(i); if (dimSize === 0) { keep = cb(i); } else if (dimSize === 1) { var val = chunks[dim0][rawIdx]; keep = cb(val, i); } else { var k = 0; for (; k < dimSize; k++) { value[k] = chunks[dims[k]][rawIdx]; } value[k] = i; keep = cb.apply(null, value); } if (keep) { newIndices[offset++] = rawIdx; } } if (offset < count) { newStore._indices = newIndices; } newStore._count = offset; newStore._extent = []; newStore._updateGetRawIdx(); return newStore; }; DataStore2.prototype.selectRange = function(range) { var newStore = this.clone(); var len = newStore._count; if (!len) { return this; } var dims = keys(range); var dimSize = dims.length; if (!dimSize) { return this; } var originalCount = newStore.count(); var Ctor = getIndicesCtor(newStore._rawCount); var newIndices = new Ctor(originalCount); var offset = 0; var dim0 = dims[0]; var min = range[dim0][0]; var max = range[dim0][1]; var storeArr = newStore._chunks; var quickFinished = false; if (!newStore._indices) { var idx = 0; if (dimSize === 1) { var dimStorage = storeArr[dims[0]]; for (var i = 0; i < len; i++) { var val = dimStorage[i]; if (val >= min && val <= max || isNaN(val)) { newIndices[offset++] = idx; } idx++; } quickFinished = true; } else if (dimSize === 2) { var dimStorage = storeArr[dims[0]]; var dimStorage2 = storeArr[dims[1]]; var min2 = range[dims[1]][0]; var max2 = range[dims[1]][1]; for (var i = 0; i < len; i++) { var val = dimStorage[i]; var val2 = dimStorage2[i]; if ((val >= min && val <= max || isNaN(val)) && (val2 >= min2 && val2 <= max2 || isNaN(val2))) { newIndices[offset++] = idx; } idx++; } quickFinished = true; } } if (!quickFinished) { if (dimSize === 1) { for (var i = 0; i < originalCount; i++) { var rawIndex = newStore.getRawIndex(i); var val = storeArr[dims[0]][rawIndex]; if (val >= min && val <= max || isNaN(val)) { newIndices[offset++] = rawIndex; } } } else { for (var i = 0; i < originalCount; i++) { var keep = true; var rawIndex = newStore.getRawIndex(i); for (var k = 0; k < dimSize; k++) { var dimk = dims[k]; var val = storeArr[dimk][rawIndex]; if (val < range[dimk][0] || val > range[dimk][1]) { keep = false; } } if (keep) { newIndices[offset++] = newStore.getRawIndex(i); } } } } if (offset < originalCount) { newStore._indices = newIndices; } newStore._count = offset; newStore._extent = []; newStore._updateGetRawIdx(); return newStore; }; DataStore2.prototype.map = function(dims, cb) { var target = this.clone(dims); this._updateDims(target, dims, cb); return target; }; DataStore2.prototype.modify = function(dims, cb) { this._updateDims(this, dims, cb); }; DataStore2.prototype._updateDims = function(target, dims, cb) { var targetChunks = target._chunks; var tmpRetValue = []; var dimSize = dims.length; var dataCount = target.count(); var values = []; var rawExtent = target._rawExtent; for (var i = 0; i < dims.length; i++) { rawExtent[dims[i]] = getInitialExtent(); } for (var dataIndex = 0; dataIndex < dataCount; dataIndex++) { var rawIndex = target.getRawIndex(dataIndex); for (var k = 0; k < dimSize; k++) { values[k] = targetChunks[dims[k]][rawIndex]; } values[dimSize] = dataIndex; var retValue = cb && cb.apply(null, values); if (retValue != null) { if (typeof retValue !== "object") { tmpRetValue[0] = retValue; retValue = tmpRetValue; } for (var i = 0; i < retValue.length; i++) { var dim = dims[i]; var val = retValue[i]; var rawExtentOnDim = rawExtent[dim]; var dimStore = targetChunks[dim]; if (dimStore) { dimStore[rawIndex] = val; } if (val < rawExtentOnDim[0]) { rawExtentOnDim[0] = val; } if (val > rawExtentOnDim[1]) { rawExtentOnDim[1] = val; } } } } }; DataStore2.prototype.lttbDownSample = function(valueDimension, rate) { var target = this.clone([valueDimension], true); var targetStorage = target._chunks; var dimStore = targetStorage[valueDimension]; var len = this.count(); var sampledIndex = 0; var frameSize = Math.floor(1 / rate); var currentRawIndex = this.getRawIndex(0); var maxArea; var area; var nextRawIndex; var newIndices = new (getIndicesCtor(this._rawCount))(Math.min((Math.ceil(len / frameSize) + 2) * 2, len)); newIndices[sampledIndex++] = currentRawIndex; for (var i = 1; i < len - 1; i += frameSize) { var nextFrameStart = Math.min(i + frameSize, len - 1); var nextFrameEnd = Math.min(i + frameSize * 2, len); var avgX = (nextFrameEnd + nextFrameStart) / 2; var avgY = 0; for (var idx = nextFrameStart; idx < nextFrameEnd; idx++) { var rawIndex = this.getRawIndex(idx); var y = dimStore[rawIndex]; if (isNaN(y)) { continue; } avgY += y; } avgY /= nextFrameEnd - nextFrameStart; var frameStart = i; var frameEnd = Math.min(i + frameSize, len); var pointAX = i - 1; var pointAY = dimStore[currentRawIndex]; maxArea = -1; nextRawIndex = frameStart; var firstNaNIndex = -1; var countNaN = 0; for (var idx = frameStart; idx < frameEnd; idx++) { var rawIndex = this.getRawIndex(idx); var y = dimStore[rawIndex]; if (isNaN(y)) { countNaN++; if (firstNaNIndex < 0) { firstNaNIndex = rawIndex; } continue; } area = Math.abs((pointAX - avgX) * (y - pointAY) - (pointAX - idx) * (avgY - pointAY)); if (area > maxArea) { maxArea = area; nextRawIndex = rawIndex; } } if (countNaN > 0 && countNaN < frameEnd - frameStart) { newIndices[sampledIndex++] = Math.min(firstNaNIndex, nextRawIndex); nextRawIndex = Math.max(firstNaNIndex, nextRawIndex); } newIndices[sampledIndex++] = nextRawIndex; currentRawIndex = nextRawIndex; } newIndices[sampledIndex++] = this.getRawIndex(len - 1); target._count = sampledIndex; target._indices = newIndices; target.getRawIndex = this._getRawIdx; return target; }; DataStore2.prototype.downSample = function(dimension, rate, sampleValue, sampleIndex) { var target = this.clone([dimension], true); var targetStorage = target._chunks; var frameValues = []; var frameSize = Math.floor(1 / rate); var dimStore = targetStorage[dimension]; var len = this.count(); var rawExtentOnDim = target._rawExtent[dimension] = getInitialExtent(); var newIndices = new (getIndicesCtor(this._rawCount))(Math.ceil(len / frameSize)); var offset = 0; for (var i = 0; i < len; i += frameSize) { if (frameSize > len - i) { frameSize = len - i; frameValues.length = frameSize; } for (var k = 0; k < frameSize; k++) { var dataIdx = this.getRawIndex(i + k); frameValues[k] = dimStore[dataIdx]; } var value = sampleValue(frameValues); var sampleFrameIdx = this.getRawIndex(Math.min(i + sampleIndex(frameValues, value) || 0, len - 1)); dimStore[sampleFrameIdx] = value; if (value < rawExtentOnDim[0]) { rawExtentOnDim[0] = value; } if (value > rawExtentOnDim[1]) { rawExtentOnDim[1] = value; } newIndices[offset++] = sampleFrameIdx; } target._count = offset; target._indices = newIndices; target._updateGetRawIdx(); return target; }; DataStore2.prototype.each = function(dims, cb) { if (!this._count) { return; } var dimSize = dims.length; var chunks = this._chunks; for (var i = 0, len = this.count(); i < len; i++) { var rawIdx = this.getRawIndex(i); switch (dimSize) { case 0: cb(i); break; case 1: cb(chunks[dims[0]][rawIdx], i); break; case 2: cb(chunks[dims[0]][rawIdx], chunks[dims[1]][rawIdx], i); break; default: var k = 0; var value = []; for (; k < dimSize; k++) { value[k] = chunks[dims[k]][rawIdx]; } value[k] = i; cb.apply(null, value); } } }; DataStore2.prototype.getDataExtent = function(dim) { var dimData = this._chunks[dim]; var initialExtent = getInitialExtent(); if (!dimData) { return initialExtent; } var currEnd = this.count(); var useRaw = !this._indices; var dimExtent; if (useRaw) { return this._rawExtent[dim].slice(); } dimExtent = this._extent[dim]; if (dimExtent) { return dimExtent.slice(); } dimExtent = initialExtent; var min = dimExtent[0]; var max = dimExtent[1]; for (var i = 0; i < currEnd; i++) { var rawIdx = this.getRawIndex(i); var value = dimData[rawIdx]; value < min && (min = value); value > max && (max = value); } dimExtent = [min, max]; this._extent[dim] = dimExtent; return dimExtent; }; DataStore2.prototype.getRawDataItem = function(idx) { var rawIdx = this.getRawIndex(idx); if (!this._provider.persistent) { var val = []; var chunks = this._chunks; for (var i = 0; i < chunks.length; i++) { val.push(chunks[i][rawIdx]); } return val; } else { return this._provider.getItem(rawIdx); } }; DataStore2.prototype.clone = function(clonedDims, ignoreIndices) { var target = new DataStore2(); var chunks = this._chunks; var clonedDimsMap = clonedDims && reduce(clonedDims, function(obj, dimIdx) { obj[dimIdx] = true; return obj; }, {}); if (clonedDimsMap) { for (var i = 0; i < chunks.length; i++) { target._chunks[i] = !clonedDimsMap[i] ? chunks[i] : cloneChunk(chunks[i]); } } else { target._chunks = chunks; } this._copyCommonProps(target); if (!ignoreIndices) { target._indices = this._cloneIndices(); } target._updateGetRawIdx(); return target; }; DataStore2.prototype._copyCommonProps = function(target) { target._count = this._count; target._rawCount = this._rawCount; target._provider = this._provider; target._dimensions = this._dimensions; target._extent = clone(this._extent); target._rawExtent = clone(this._rawExtent); }; DataStore2.prototype._cloneIndices = function() { if (this._indices) { var Ctor = this._indices.constructor; var indices = void 0; if (Ctor === Array) { var thisCount = this._indices.length; indices = new Ctor(thisCount); for (var i = 0; i < thisCount; i++) { indices[i] = this._indices[i]; } } else { indices = new Ctor(this._indices); } return indices; } return null; }; DataStore2.prototype._getRawIdxIdentity = function(idx) { return idx; }; DataStore2.prototype._getRawIdx = function(idx) { if (idx < this._count && idx >= 0) { return this._indices[idx]; } return -1; }; DataStore2.prototype._updateGetRawIdx = function() { this.getRawIndex = this._indices ? this._getRawIdx : this._getRawIdxIdentity; }; DataStore2.internalField = function() { function getDimValueSimply(dataItem, property, dataIndex, dimIndex) { return parseDataValue(dataItem[dimIndex], this._dimensions[dimIndex]); } defaultDimValueGetters = { arrayRows: getDimValueSimply, objectRows: function(dataItem, property, dataIndex, dimIndex) { return parseDataValue(dataItem[property], this._dimensions[dimIndex]); }, keyedColumns: getDimValueSimply, original: function(dataItem, property, dataIndex, dimIndex) { var value = dataItem && (dataItem.value == null ? dataItem : dataItem.value); return parseDataValue(value instanceof Array ? value[dimIndex] : value, this._dimensions[dimIndex]); }, typedArray: function(dataItem, property, dataIndex, dimIndex) { return dataItem[dimIndex]; } }; }(); return DataStore2; }(); var DataStore$1 = DataStore; export { CtorFloat64Array, CtorInt32Array, CtorUint16Array, CtorUint32Array, DataStore$1 as default };