Skip to content

Commit

Permalink
[fix] Hexbin layer color aggregation incorrect on load (#2415)
Browse files Browse the repository at this point in the history
Signed-off-by: Ihor Dykhta <dikhta.igor@gmail.com>
Co-authored-by: Jacob Wasilkowski <4933392+jwasilgeo@users.noreply.github.com>
  • Loading branch information
igorDykhta and jwasilgeo committed Oct 28, 2023
1 parent 58f0bb7 commit b995c9b
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 18 deletions.
27 changes: 23 additions & 4 deletions src/components/src/side-panel/layer-panel/layer-configurator.tsx
Expand Up @@ -45,7 +45,11 @@ import LayerErrorMessage from './layer-error-message';

import {capitalizeFirstLetter} from '@kepler.gl/utils';

import {CHANNEL_SCALE_SUPPORTED_FIELDS, LAYER_TYPES} from '@kepler.gl/constants';
import {
CHANNEL_SCALE_SUPPORTED_FIELDS,
LAYER_TYPES,
AGGREGATION_TYPE_OPTIONS
} from '@kepler.gl/constants';
import {Layer, LayerBaseConfig, VisualChannel, AggregationLayer} from '@kepler.gl/layers';

import {NestedPartial, LayerVisConfig, ColorUI, Field} from '@kepler.gl/types';
Expand Down Expand Up @@ -1183,16 +1187,31 @@ export const AggregationTypeSelector = ({channel, layer, onChange}: AggregationS
const {visConfig} = layer.config;

// aggregation should only be selectable when field is selected
const aggregationOptions = layer.getAggregationOptions(key);
const layerAggregationTypes = layer.getAggregationOptions(key);

const aggregationOptions = AGGREGATION_TYPE_OPTIONS.filter(({id}) =>
layerAggregationTypes.includes(id)
);

const selectedAggregation = aggregation
? aggregationOptions.find(({id}) => id === visConfig[aggregation])
: [];

return (
<SidePanelSection>
<PanelLabel>
<FormattedMessage id={'layer.aggregateBy'} values={{field: selectedField.name}} />
<FormattedMessage
id={'layer.aggregateBy'}
values={{
field: selectedField.displayName
}}
/>
</PanelLabel>
<ItemSelector
selectedItems={visConfig[aggregation as string]}
selectedItems={selectedAggregation}
options={aggregationOptions}
displayOption="label"
getOptionValue="id"
multiSelect={false}
searchable={false}
onChange={value =>
Expand Down
18 changes: 16 additions & 2 deletions src/constants/src/default-settings.ts
Expand Up @@ -565,7 +565,7 @@ export const AGGREGATION_TYPES: {
variance: 'variance';
// ordinal
mode: 'mode';
countUnique: 'count unique';
countUnique: 'countUnique';
} = {
// default
count: 'count',
Expand All @@ -579,9 +579,23 @@ export const AGGREGATION_TYPES: {
variance: 'variance',
// ordinal
mode: 'mode',
countUnique: 'count unique'
countUnique: 'countUnique'
};

export const AGGREGATION_TYPE_OPTIONS: {id: string; label: string}[] = Object.entries(
AGGREGATION_TYPES
).map(([key, value]) => ({
id: key,
label:
key === 'stdev'
? 'Std Deviation'
: key === 'countUnique'
? 'Count Unique'
: typeof value === 'string'
? value.charAt(0).toUpperCase() + value.slice(1)
: value
}));

export const linearFieldScaleFunctions = {
[CHANNEL_SCALES.color]: [SCALE_TYPES.quantize, SCALE_TYPES.quantile],
[CHANNEL_SCALES.radius]: [SCALE_TYPES.sqrt],
Expand Down
14 changes: 8 additions & 6 deletions src/reducers/src/vis-state-merger.ts
Expand Up @@ -831,11 +831,6 @@ export function validateLayerWithData(
}
}

// visual channel field is saved to be {name, type}
// find visual channel field by matching both name and type
// refer to vis-state-schema.js VisualChannelSchemaV1
newLayer = validateSavedVisualChannels(fields, newLayer, savedLayer, options);

const textLabel =
savedLayer.config.textLabel && newLayer.config.textLabel
? validateSavedTextLabel(
Expand All @@ -850,14 +845,21 @@ export function validateLayerWithData(
const visConfig = newLayer.copyLayerConfig(
newLayer.config.visConfig,
savedLayer.config.visConfig || {},
{shallowCopy: ['colorRange', 'strokeColorRange']}
{
shallowCopy: ['colorRange', 'strokeColorRange']
}
);

newLayer.updateLayerConfig({
visConfig,
textLabel
});

// visual channel field is saved to be {name, type}
// find visual channel field by matching both name and type
// refer to vis-state-schema.js VisualChannelSchemaV1
newLayer = validateSavedVisualChannels(fields, newLayer, savedLayer, options);

if (throwOnError) {
if (!newLayer.isValidToSave()) {
throw new Error(`Layer is not valid to save: ${newLayer.id}`);
Expand Down
2 changes: 1 addition & 1 deletion test/fixtures/state-saved-v0.js
Expand Up @@ -1267,7 +1267,7 @@ mergedLayer3.config = {
},
visConfig: {
colorAggregation: 'maximum',
sizeAggregation: 'average',
sizeAggregation: 'count',
enable3d: true,
opacity: 0.8,
worldUnitSize: 0.5,
Expand Down
6 changes: 3 additions & 3 deletions test/fixtures/state-saved-v1-3.js
Expand Up @@ -263,7 +263,7 @@ export const savedStateV1 = {
percentile: [0, 96.54],
elevationPercentile: [0, 100],
elevationScale: 5,
colorAggregation: 'average',
colorAggregation: 'count', // if associated visualChannel colorField value is null, it can only default to 'count'
sizeAggregation: 'average',
enable3d: false
}
Expand Down Expand Up @@ -468,8 +468,8 @@ mergedLayer1.config = {
elevationPercentile: [0, 100],
elevationScale: 5,
enableElevationZoomFactor: true,
colorAggregation: 'average',
sizeAggregation: 'average',
colorAggregation: 'count', // if associated colorField value is null, it can only default to 'count'
sizeAggregation: 'count', // if associated sizeField value is null, it can only default to 'count'
enable3d: false
},
animation: {enabled: false}
Expand Down
4 changes: 2 additions & 2 deletions test/node/utils/aggregate-utils-test.js
Expand Up @@ -45,12 +45,12 @@ test('AggregateUtils - GetMode', t => {

test('AggregateUtils - aggregate', t => {
const data = [1, 2, 3, 1, 2, 3, 4, 3];
const results = [8, 2.375, 4, 1, 2.5, 1.0606601717798212, 19, 1.125, '3', 8];
const results = [8, 2.375, 4, 1, 2.5, 1.0606601717798212, 19, 1.125, '3', 4];
Object.keys(AGGREGATION_TYPES).map((technique, index) => {
t.equal(
aggregate(data, technique),
results[index],
`Should compute the right aggregation using ${technique} - ${index}`
`Should compute the right aggregation using ${technique} - ${aggregate(data, technique)}`
);
});

Expand Down

0 comments on commit b995c9b

Please sign in to comment.