compassql
Version:
CompassQL visualization query language
168 lines (142 loc) • 5.45 kB
text/typescript
import * as CHANNEL from 'vega-lite/build/src/channel';
import {Channel} from 'vega-lite/build/src/channel';
import {Config} from 'vega-lite/build/src/config';
import {DEFAULT_PROP_PRECEDENCE, toKey} from './property';
import {DEFAULT_ENUM_INDEX, EnumIndex} from './wildcard';
// We name this QueryConfig to avoid confusion with Vega-Lite's Config
export interface QueryConfig {
verbose?: boolean;
defaultSpecConfig?: Config;
propertyPrecedence?: string[];
enum?: Partial<EnumIndex>;
/** Default ratio for number fields to be considered ordinal */
numberNominalProportion?: number;
/** Default cutoff for not applying the numberOrdinalProportion inference */
numberNominalLimit?: number;
// SPECIAL MODE
/**
* Allow automatically adding a special count (autoCount) field for plots
* that contain only discrete fields. In such cases, adding count make the
* output plots way more meaningful.
*/
autoAddCount?: boolean;
// CONSTRAINTS
constraintManuallySpecifiedValue?: boolean;
// Spec Constraints
hasAppropriateGraphicTypeForMark?: boolean;
omitAggregate?: boolean;
omitAggregatePlotWithDimensionOnlyOnFacet?: boolean;
omitAggregatePlotWithoutDimension?: boolean;
omitBarLineAreaWithOcclusion?: boolean;
omitBarTickWithSize?: boolean;
omitMultipleNonPositionalChannels?: boolean;
omitRaw?: boolean;
omitRawContinuousFieldForAggregatePlot?: boolean;
omitRawWithXYBothOrdinalScaleOrBin?: boolean;
omitRepeatedField?: boolean;
omitNonPositionalOrFacetOverPositionalChannels?: boolean;
omitTableWithOcclusionIfAutoAddCount?: boolean;
omitVerticalDotPlot?: boolean;
omitInvalidStackSpec?: boolean;
omitNonSumStack?: boolean;
preferredBinAxis?: Channel;
preferredTemporalAxis?: Channel;
preferredOrdinalAxis?: Channel;
preferredNominalAxis?: Channel;
preferredFacet?: Channel;
// Field Encoding Constraints
minCardinalityForBin?: number;
maxCardinalityForCategoricalColor?: number;
maxCardinalityForFacet?: number;
maxCardinalityForShape?: number;
timeUnitShouldHaveVariation?: boolean;
typeMatchesSchemaType?: boolean;
// STYLIZE
stylize?: boolean;
smallRangeStepForHighCardinalityOrFacet?: {maxCardinality: number; rangeStep: number};
nominalColorScaleForHighCardinality?: {maxCardinality: number; palette: string};
xAxisOnTopForHighYCardinalityWithoutColumn?: {maxCardinality: number};
// EFFECTIVENESS PREFERENCE
maxGoodCardinalityForColor?: number; // FIXME: revise
maxGoodCardinalityForFacet?: number; // FIXME: revise
// HIGH CARDINALITY STRINGS
minPercentUniqueForKey?: number;
minCardinalityForKey?: number;
}
export const DEFAULT_QUERY_CONFIG: QueryConfig = {
verbose: false,
defaultSpecConfig: {
line: {point: true},
scale: {useUnaggregatedDomain: true}
},
propertyPrecedence: DEFAULT_PROP_PRECEDENCE.map(toKey),
enum: DEFAULT_ENUM_INDEX,
numberNominalProportion: 0.05,
numberNominalLimit: 40,
// CONSTRAINTS
constraintManuallySpecifiedValue: false,
// Spec Constraints -- See description inside src/constraints/spec.ts
autoAddCount: false,
hasAppropriateGraphicTypeForMark: true,
omitAggregate: false,
omitAggregatePlotWithDimensionOnlyOnFacet: true,
omitAggregatePlotWithoutDimension: false,
omitBarLineAreaWithOcclusion: true,
omitBarTickWithSize: true,
omitMultipleNonPositionalChannels: true,
omitRaw: false,
omitRawContinuousFieldForAggregatePlot: true,
omitRepeatedField: true,
omitNonPositionalOrFacetOverPositionalChannels: true,
omitTableWithOcclusionIfAutoAddCount: true,
omitVerticalDotPlot: false,
omitInvalidStackSpec: true,
omitNonSumStack: true,
preferredBinAxis: CHANNEL.X,
preferredTemporalAxis: CHANNEL.X,
preferredOrdinalAxis: CHANNEL.Y, // ordinal on y makes it easier to read.
preferredNominalAxis: CHANNEL.Y, // nominal on y makes it easier to read.
preferredFacet: CHANNEL.ROW, // row make it easier to scroll than column
// Field Encoding Constraints -- See description inside src/constraint/field.ts
minCardinalityForBin: 15,
maxCardinalityForCategoricalColor: 20,
maxCardinalityForFacet: 20,
maxCardinalityForShape: 6,
timeUnitShouldHaveVariation: true,
typeMatchesSchemaType: true,
// STYLIZE
stylize: true,
smallRangeStepForHighCardinalityOrFacet: {maxCardinality: 10, rangeStep: 12},
nominalColorScaleForHighCardinality: {maxCardinality: 10, palette: 'category20'},
xAxisOnTopForHighYCardinalityWithoutColumn: {maxCardinality: 30},
// RANKING PREFERENCE
maxGoodCardinalityForFacet: 5, // FIXME: revise
maxGoodCardinalityForColor: 7, // FIXME: revise
// HIGH CARDINALITY STRINGS
minPercentUniqueForKey: 0.8,
minCardinalityForKey: 50
};
export function extendConfig(opt: QueryConfig) {
return {
...DEFAULT_QUERY_CONFIG,
...opt,
enum: extendEnumIndex(opt.enum)
};
}
function extendEnumIndex(enumIndex: Partial<EnumIndex>) {
const enumOpt: EnumIndex = {
...DEFAULT_ENUM_INDEX,
...enumIndex,
binProps: extendNestedEnumIndex(enumIndex, 'bin'),
scaleProps: extendNestedEnumIndex(enumIndex, 'scale'),
axisProps: extendNestedEnumIndex(enumIndex, 'axis'),
legendProps: extendNestedEnumIndex(enumIndex, 'legend')
};
return enumOpt;
}
function extendNestedEnumIndex(enumIndex: Partial<EnumIndex>, prop: 'bin' | 'scale' | 'axis' | 'legend') {
return {
...DEFAULT_ENUM_INDEX[prop + 'Props'],
...enumIndex[prop + 'Props']
};
}