Skip to content

Commit

Permalink
add custom color ramp and connected layer
Browse files Browse the repository at this point in the history
  • Loading branch information
alvarezmelissa87 committed Jan 18, 2022
1 parent 7af220b commit 2273e4d
Show file tree
Hide file tree
Showing 10 changed files with 79 additions and 71 deletions.
19 changes: 19 additions & 0 deletions x-pack/plugins/ml/common/constants/anomalies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,25 @@ export const SEVERITY_COLORS = {
BLANK: '#ffffff',
};

export const SEVERITY_COLOR_RAMP = [
{
stop: ANOMALY_THRESHOLD.LOW,
color: SEVERITY_COLORS.WARNING,
},
{
stop: ANOMALY_THRESHOLD.MINOR,
color: SEVERITY_COLORS.MINOR,
},
{
stop: ANOMALY_THRESHOLD.MAJOR,
color: SEVERITY_COLORS.MAJOR,
},
{
stop: ANOMALY_THRESHOLD.CRITICAL,
color: SEVERITY_COLORS.CRITICAL,
},
];

export const ANOMALY_RESULT_TYPE = {
BUCKET: 'bucket',
RECORD: 'record',
Expand Down
7 changes: 6 additions & 1 deletion x-pack/plugins/ml/common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@

export { ES_CLIENT_TOTAL_HITS_RELATION } from './types/es_client';
export type { ChartData } from './types/field_histograms';
export { ANOMALY_SEVERITY, ANOMALY_THRESHOLD, SEVERITY_COLORS } from './constants/anomalies';
export {
ANOMALY_SEVERITY,
ANOMALY_THRESHOLD,
SEVERITY_COLOR_RAMP,
SEVERITY_COLORS,
} from './constants/anomalies';
export { getSeverityColor, getSeverityType } from './util/anomaly_utils';
export { isPopulatedObject } from './util/object_utils';
export { composeValidators, patternValidator } from './util/validators';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,11 @@
*/

import { FIELD_ORIGIN, LAYER_TYPE, STYLE_TYPE } from '../../../../../maps/common';
import { ANOMALY_THRESHOLD, SEVERITY_COLORS } from '../../../../common';
import { SEVERITY_COLOR_RAMP } from '../../../../common';
import { AnomaliesTableData } from '../explorer_utils';

const FEATURE = 'Feature';
const POINT = 'Point';
const SEVERITY_COLOR_RAMP = [
{
stop: ANOMALY_THRESHOLD.LOW,
color: SEVERITY_COLORS.WARNING,
},
{
stop: ANOMALY_THRESHOLD.MINOR,
color: SEVERITY_COLORS.MINOR,
},
{
stop: ANOMALY_THRESHOLD.MAJOR,
color: SEVERITY_COLORS.MAJOR,
},
{
stop: ANOMALY_THRESHOLD.CRITICAL,
color: SEVERITY_COLORS.CRITICAL,
},
];

function getAnomalyFeatures(
anomalies: AnomaliesTableData['anomalies'],
Expand Down
10 changes: 4 additions & 6 deletions x-pack/plugins/ml/public/maps/anomaly_layer_wizard_factory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import React from 'react';
import uuid from 'uuid';
import type { StartServicesAccessor } from 'kibana/public';
import type { LayerWizard, RenderWizardArguments } from '../../../maps/public';
import { COLOR_MAP_TYPE, FIELD_ORIGIN, LAYER_TYPE, STYLE_TYPE } from '../../../maps/common';
import { FIELD_ORIGIN, LAYER_TYPE, STYLE_TYPE } from '../../../maps/common';
import { SEVERITY_COLOR_RAMP } from '../../common';
import { CreateAnomalySourceEditor } from './create_anomaly_source_editor';
import {
VectorLayerDescriptor,
Expand Down Expand Up @@ -70,15 +71,12 @@ export class AnomalyLayerWizardFactory {
fillColor: {
type: STYLE_TYPE.DYNAMIC,
options: {
color: 'Blue to Red',
colorCategory: 'palette_0',
fieldMetaOptions: { isEnabled: true, sigma: 3 },
type: COLOR_MAP_TYPE.ORDINAL,
customColorRamp: SEVERITY_COLOR_RAMP,
field: {
name: 'record_score',
origin: FIELD_ORIGIN.SOURCE,
},
useCustomColorRamp: false,
useCustomColorRamp: true,
},
},
} as unknown as VectorStylePropertiesDescriptor,
Expand Down
9 changes: 6 additions & 3 deletions x-pack/plugins/ml/public/maps/anomaly_source.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import type { SourceEditorArgs } from '../../../maps/public';
import type { DataRequest } from '../../../maps/public';
import type { IVectorSource, SourceStatus } from '../../../maps/public';
import { ML_ANOMALY } from './anomaly_source_factory';
import { getResultsForJobId } from './util';
import { getResultsForJobId, MlAnomalyLayers } from './util';
import { UpdateAnomalySourceEditor } from './update_anomaly_source_editor';

export type SearchFilters = any & {
Expand All @@ -33,7 +33,7 @@ export type SearchFilters = any & {

export interface AnomalySourceDescriptor extends AbstractSourceDescriptor {
jobId: string;
typicalActual: 'typical' | 'actual';
typicalActual: MlAnomalyLayers;
}

export class AnomalySource implements IVectorSource {
Expand Down Expand Up @@ -203,6 +203,7 @@ export class AnomalySource implements IVectorSource {
// Return true if you can compute bounds of data
return true;
}

// Promise<Array<{ name: string; license: string }>>
async getLicensedFeatures(): Promise<any[]> {
return [{ name: 'layer from ML anomaly job', license: 'enterprise' }];
Expand All @@ -226,7 +227,9 @@ export class AnomalySource implements IVectorSource {
}

async getSupportedShapeTypes(): Promise<VECTOR_SHAPE_TYPE[]> {
return [VECTOR_SHAPE_TYPE.POINT];
return this._descriptor.typicalActual === 'connected'
? [VECTOR_SHAPE_TYPE.LINE]
: [VECTOR_SHAPE_TYPE.POINT];
}

getSyncMeta(): object | null {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { EuiPanel } from '@elastic/eui';
import { AnomalySourceDescriptor } from './anomaly_source';
import { AnomalyJobSelector } from './anomaly_job_selector';
import { LayerSelector } from './layer_selector';
import { MlAnomalyLayers } from './util';

interface Props {
onSourceConfigChange: (sourceConfig: Partial<AnomalySourceDescriptor> | null) => void;
Expand All @@ -19,7 +20,7 @@ interface Props {

interface State {
jobId?: string;
typicalActual?: 'typical' | 'actual';
typicalActual?: MlAnomalyLayers;
}

export class CreateAnomalySourceEditor extends Component<Props, State> {
Expand All @@ -39,7 +40,7 @@ export class CreateAnomalySourceEditor extends Component<Props, State> {
this._isMounted = true;
}

private onTypicalActualChange = (typicalActual: 'typical' | 'actual') => {
private onTypicalActualChange = (typicalActual: MlAnomalyLayers) => {
if (!this._isMounted) {
return;
}
Expand Down
11 changes: 8 additions & 3 deletions x-pack/plugins/ml/public/maps/layer_selector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ import React, { Component } from 'react';

import { EuiComboBox, EuiFormRow, EuiComboBoxOptionOption } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { MlAnomalyLayers } from './util';

interface Props {
onChange: (typicalActual: 'typical' | 'actual') => void;
typicalActual: 'typical' | 'actual';
onChange: (typicalActual: MlAnomalyLayers) => void;
typicalActual: MlAnomalyLayers;
}

// eslint-disable-next-line @typescript-eslint/no-empty-interface
Expand All @@ -32,7 +33,10 @@ export class LayerSelector extends Component<Props, State> {
}

onSelect = (selectedOptions: Array<EuiComboBoxOptionOption<string>>) => {
const typicalActual: 'typical' | 'actual' = selectedOptions[0].value! as 'typical' | 'actual';
const typicalActual: MlAnomalyLayers = selectedOptions[0].value! as
| 'typical'
| 'actual'
| 'connected';
if (this._isMounted) {
this.setState({ typicalActual });
this.props.onChange(typicalActual);
Expand All @@ -54,6 +58,7 @@ export class LayerSelector extends Component<Props, State> {
options={[
{ value: 'typical', label: 'typical' },
{ value: 'actual', label: 'actual' },
{ value: 'connected', label: 'connected' },
]}
selectedOptions={options}
/>
Expand Down
42 changes: 12 additions & 30 deletions x-pack/plugins/ml/public/maps/record_score_field.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,6 @@ export class RecordScoreField implements IField {
return this._source;
}

isCount() {
return false;
}

isEqual(field: IField): boolean {
return this.getName() === field.getName();
}
Expand All @@ -102,49 +98,35 @@ export class RecordScoreField implements IField {
return true;
}

pluckRangeFromTileMetaFeature(metaFeature: TileMetaFeature) {
return null;
supportsFieldMetaFromLocalData(): boolean {
return true;
}

// NA
canReadFromGeoJson(): boolean {
supportsFieldMetaFromEs(): boolean {
return false;
}

// NA
canValueBeFormatted(): boolean {
return false;
}

// NA
supportsAutoDomain(): boolean {
return false;
}

// NA
supportsFieldMeta(): boolean {
return false;
async getExtendedStatsFieldMetaRequest(): Promise<unknown> {
return null;
}

supportsFieldMetaFromLocalData(): boolean {
return false;
async getPercentilesFieldMetaRequest(percentiles: number[]): Promise<unknown> {
return null;
}

supportsFieldMetaFromEs(): boolean {
return false;
async getCategoricalFieldMetaRequest(size: number): Promise<unknown> {
return null;
}

// NA
async getPercentilesFieldMetaRequest(percentiles: number[]): Promise<unknown | null> {
pluckRangeFromTileMetaFeature(metaFeature: TileMetaFeature): { min: number; max: number } | null {
return null;
}

// NA
async getExtendedStatsFieldMetaRequest(): Promise<unknown | null> {
return undefined;
}
// NA
async getCategoricalFieldMetaRequest(size: number): Promise<unknown> {
return undefined;
isCount(): boolean {
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ import React, { Fragment, Component } from 'react';
import { FormattedMessage } from '@kbn/i18n-react';
import { EuiPanel, EuiSpacer, EuiTitle } from '@elastic/eui';
import { LayerSelector } from './layer_selector';
import { MlAnomalyLayers } from './util';

interface Props {
onChange: (...args: Array<{ propName: string; value: unknown }>) => void;
typicalActual: 'typical' | 'actual';
typicalActual: MlAnomalyLayers;
}

// eslint-disable-next-line @typescript-eslint/no-empty-interface
Expand All @@ -33,7 +34,7 @@ export class UpdateAnomalySourceEditor extends Component<Props, State> {
</EuiTitle>
<EuiSpacer size="s" />
<LayerSelector
onChange={(typicalActual: 'typical' | 'actual') => {
onChange={(typicalActual: MlAnomalyLayers) => {
this.props.onChange({
propName: 'typicalActual',
value: typicalActual,
Expand Down
22 changes: 17 additions & 5 deletions x-pack/plugins/ml/public/maps/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ import { MlApiServices } from '../application/services/ml_api_service';
import { MLAnomalyDoc } from '../../common/types/anomalies';
import type { SearchFilters } from './anomaly_source';

export type MlAnomalyLayers = 'typical' | 'actual' | 'connected';

export async function getResultsForJobId(
mlResultsService: MlApiServices['results'],
jobId: string,
locationType: 'typical' | 'actual',
locationType: MlAnomalyLayers,
searchFilters: SearchFilters
): Promise<FeatureCollection> {
const { timeFilters } = searchFilters;
Expand Down Expand Up @@ -85,13 +87,23 @@ export async function getResultsForJobId(
});
}

// @ts-ignore
const features: Feature[] = hits!.map((result) => {
return {
type: 'Feature',
geometry: {
let geometry;
if (locationType === 'typical' || locationType === 'actual') {
geometry = {
type: 'Point',
coordinates: locationType === 'typical' ? result.typical : result.actual,
},
};
} else {
geometry = {
type: 'LineString',
coordinates: [result.typical, result.actual],
};
}
return {
type: 'Feature',
geometry,
properties: {
record_score: result.record_score,
},
Expand Down

0 comments on commit 2273e4d

Please sign in to comment.