import * as d3 from "d3"; import { calculateBoxStatistics, calculateBinExtent } from "./utils"; export function createBinModel(dataArray, valueMap: Function, binWidth: number){ let dataModel: any = {}, data = dataArray.map(valueMap), [min, max] = d3.extent(data), extent = calculateBinExtent(min, max, binWidth), binRange = d3.range(extent[0], extent[1], binWidth), histogramGenerator = d3.histogram().domain(extent).thresholds(binRange), dataBinArray = histogramGenerator(data); dataModel.dataArray = dataBinArray; dataModel.binRange = binRange; return dataModel; } export function createBoxModel(dataArray, valueMap: Function){ let i, dataModel: any, lowerWhisker: number, upperWhisker: number, whiskerLimit: number, outliers = [], datum, data = dataArray.map(valueMap); data = data.sort(d3.ascending); dataModel = calculateBoxStatistics(data); i = 0; whiskerLimit = (dataModel.q1Val - (1.5 * dataModel.iqr)); while (i < data.length) { datum = data[i]; if (datum < whiskerLimit) { outliers.push(datum); } else { lowerWhisker = datum; break; } i++; } i = data.length - 1; whiskerLimit = (dataModel.q3Val + (1.5 * dataModel.iqr)); while (i >= 0) { datum = data[i]; if (datum > whiskerLimit) { outliers.push(datum); } else { upperWhisker = datum; break; } i--; } dataModel.upperWhisker = upperWhisker; dataModel.lowerWhisker = lowerWhisker; dataModel.outliers = outliers; return dataModel; } export function createPieModel(dataArray, valueMap: Function) { let dataModel: any = {}, dataPieArray = d3.pie().value(valueMap)(dataArray); dataModel.dataArray = dataPieArray; return dataModel; } export function createStackModel(dataArray, mapper){ let datum, value, key, category, dataMap = {}, dataMapKey, dLayout, positiveDataLayoutMap = {}, negativeDataLayoutMap = {}, positiveDataLayoutArray = [], negativeDataLayoutArray = [], keyArray = [], categoryArray = [], stackLayout, stackedDataArray, positiveStackedDataArray, negativeStackedDataArray, dataModel: any = { valueMin: 0, valueMax: 0 }; // unique categories for (datum of dataArray) { key = mapper.colorValueMap(datum); if (keyArray.indexOf(key) === -1) { keyArray.push(key); } } function createLayoutDatum(c) { return { category: c, valueMax: 0, valueMin: 0, value: 0 }; } for (datum of dataArray) { category = mapper.categoryValueMap(datum); value = mapper.valueValueMap(datum); if (value >= 0) { dLayout = positiveDataLayoutMap[category]; if (!dLayout) { categoryArray.push(category); dLayout = createLayoutDatum(category); positiveDataLayoutMap[category] = dLayout; } } else { dLayout = negativeDataLayoutMap[category]; if (!dLayout) { categoryArray.push(category); dLayout = createLayoutDatum(category); negativeDataLayoutMap[category] = dLayout; } } key = mapper.colorValueMap(datum); dataMapKey = key + "_" + category; dataMap[dataMapKey] = datum; dLayout[key] = value; if (value > 0){ dLayout.valueMax = Math.max(value, dLayout.valueMax + value); } else { dLayout.valueMin = Math.min(value, dLayout.valueMin + value); } } for (category in positiveDataLayoutMap) { if (positiveDataLayoutMap.hasOwnProperty(category)) { dLayout = positiveDataLayoutMap[category]; positiveDataLayoutArray.push(dLayout); } } for (category in negativeDataLayoutMap) { if (negativeDataLayoutMap.hasOwnProperty(category)) { dLayout = negativeDataLayoutMap[category]; negativeDataLayoutArray.push(dLayout); } } stackLayout = d3.stack().keys(keyArray); positiveStackedDataArray = stackLayout(positiveDataLayoutArray); negativeStackedDataArray = stackLayout(negativeDataLayoutArray); stackedDataArray = positiveStackedDataArray.concat(negativeStackedDataArray); let stackData, stackDataItem; for (stackData of stackedDataArray) { for (stackDataItem of stackData) { dataMapKey = stackData.key + "_" + stackDataItem.data.category; stackDataItem.original = dataMap[dataMapKey]; } } dataModel.dataArray = stackedDataArray; dataModel.categoryArray = categoryArray; if (negativeDataLayoutArray.length > 0) { dataModel.valueMin = d3.min(negativeDataLayoutArray, function(d){ return d.valueMin; }); } if (positiveDataLayoutArray.length > 0) { dataModel.valueMax = d3.max(positiveDataLayoutArray, function(d){ return d.valueMax; }); } dataModel.colorValueMap = function(d){ return d.key; }; dataModel.detailsMap = mapper.detailsMap; return dataModel; }