{"version":3,"file":"reduce.cjs","sources":["../../../../src/transformations/transformers/reduce.ts"],"sourcesContent":["import { map } from 'rxjs/operators';\n\nimport { guessFieldTypeForField } from '../../dataframe/processDataFrame';\nimport { getFieldDisplayName } from '../../field/fieldState';\nimport { KeyValue } from '../../types/data';\nimport { DataFrame, Field, FieldType } from '../../types/dataFrame';\nimport { DataTransformerInfo, FieldMatcher, MatcherConfig } from '../../types/transformations';\nimport { fieldReducers, reduceField, ReducerID } from '../fieldReducer';\nimport { getFieldMatcher } from '../matchers';\nimport { alwaysFieldMatcher, notTimeFieldMatcher } from '../matchers/predicates';\n\nimport { DataTransformerID } from './ids';\n\nexport enum ReduceTransformerMode {\n  SeriesToRows = 'seriesToRows', // default\n  ReduceFields = 'reduceFields', // same structure, add additional row for each type\n}\n\nexport interface ReduceTransformerOptions {\n  reducers: ReducerID[];\n  fields?: MatcherConfig; // Assume all fields\n  mode?: ReduceTransformerMode;\n  includeTimeField?: boolean;\n  labelsToFields?: boolean;\n}\n\nexport const reduceTransformer: DataTransformerInfo<ReduceTransformerOptions> = {\n  id: DataTransformerID.reduce,\n  name: 'Reduce',\n  description: 'Reduce all rows or data points to a single value using a function like max, min, mean or last.',\n  defaultOptions: {\n    reducers: [ReducerID.max],\n  },\n\n  /**\n   * Return a modified copy of the series. If the transform is not or should not\n   * be applied, just return the input series\n   */\n  operator: (options) => (source) =>\n    source.pipe(\n      map((data) => {\n        if (!options?.reducers?.length) {\n          return data; // nothing selected\n        }\n\n        const matcher = options.fields\n          ? getFieldMatcher(options.fields)\n          : options.includeTimeField && options.mode === ReduceTransformerMode.ReduceFields\n            ? alwaysFieldMatcher\n            : notTimeFieldMatcher;\n\n        // Collapse all matching fields into a single row\n        if (options.mode === ReduceTransformerMode.ReduceFields) {\n          return reduceFields(data, matcher, options.reducers);\n        }\n\n        // Add a row for each series\n        const res = reduceSeriesToRows(data, matcher, options.reducers, options.labelsToFields);\n        return res\n          ? [{ ...res, refId: `${DataTransformerID.reduce}-${data.map((frame) => frame.refId).join('-')}` }]\n          : [];\n      })\n    ),\n};\n\n/**\n * @internal only exported for testing\n */\nfunction reduceSeriesToRows(\n  data: DataFrame[],\n  matcher: FieldMatcher,\n  reducerId: ReducerID[],\n  labelsToFields?: boolean\n): DataFrame | undefined {\n  const calculators = fieldReducers.list(reducerId);\n  const reducers = calculators.map((c) => c.id);\n  const processed: DataFrame[] = [];\n  const distinctLabels = labelsToFields ? getDistinctLabelKeys(data) : [];\n\n  for (const series of data) {\n    const source = series.fields.filter((f) => matcher(f, series, data));\n\n    const size = source.length;\n    const fields: Field[] = [];\n    const names: string[] = new Array(size);\n    fields.push({\n      name: 'Field',\n      type: FieldType.string,\n      values: names,\n      config: {},\n    });\n\n    const labels: KeyValue<unknown[]> = {};\n    if (labelsToFields) {\n      for (const key of distinctLabels) {\n        labels[key] = new Array(size);\n        fields.push({\n          name: key,\n          type: FieldType.string,\n          values: labels[key],\n          config: {},\n        });\n      }\n    }\n\n    const calcs: KeyValue<unknown[]> = {};\n    for (const info of calculators) {\n      calcs[info.id] = new Array(size);\n      fields.push({\n        name: info.name,\n        type: FieldType.other, // UNKNOWN until after we call the functions\n        values: calcs[info.id],\n        config: {},\n      });\n    }\n\n    for (let i = 0; i < source.length; i++) {\n      const field = source[i];\n      const results = reduceField({\n        field,\n        reducers,\n      });\n\n      if (labelsToFields) {\n        names[i] = field.name;\n        if (field.labels) {\n          for (const key in field.labels) {\n            labels[key][i] = field.labels[key];\n          }\n        }\n      } else {\n        names[i] = getFieldDisplayName(field, series, data);\n      }\n\n      for (const info of calculators) {\n        const v = results[info.id];\n        if (v === null) {\n          // NaN ensures proper row index, null results in shift\n          calcs[info.id][i] = NaN;\n        } else {\n          calcs[info.id][i] = v;\n        }\n      }\n    }\n\n    // For reduced fields, we don't know the type until we see the value\n    for (const f of fields) {\n      if (f.type === FieldType.other) {\n        const t = guessFieldTypeForField(f);\n        if (t) {\n          f.type = t;\n        }\n      }\n    }\n\n    processed.push({\n      ...series, // Same properties, different fields\n      fields,\n      length: size,\n    });\n  }\n\n  return mergeResults(processed);\n}\n\nfunction getDistinctLabelKeys(frames: DataFrame[]): string[] {\n  const keys = new Set<string>();\n  for (const frame of frames) {\n    for (const field of frame.fields) {\n      if (field.labels) {\n        for (const k of Object.keys(field.labels)) {\n          keys.add(k);\n        }\n      }\n    }\n  }\n  return [...keys];\n}\n\n/**\n * @internal only exported for testing\n */\nfunction mergeResults(data: DataFrame[]): DataFrame | undefined {\n  if (!data?.length) {\n    return undefined;\n  }\n\n  const baseFrame = data[0];\n\n  for (let seriesIndex = 1; seriesIndex < data.length; seriesIndex++) {\n    const series = data[seriesIndex];\n\n    for (let baseIndex = 0; baseIndex < baseFrame.fields.length; baseIndex++) {\n      const baseField = baseFrame.fields[baseIndex];\n      for (let fieldIndex = 0; fieldIndex < series.fields.length; fieldIndex++) {\n        const field = series.fields[fieldIndex];\n        const isFirstField = baseIndex === 0 && fieldIndex === 0;\n        const isSameField = baseField.type === field.type && baseField.name === field.name;\n\n        if (isFirstField || isSameField) {\n          const baseValues = baseField.values;\n          const values = field.values;\n          baseField.values = baseValues.concat(values);\n        }\n      }\n    }\n  }\n\n  baseFrame.name = undefined;\n  baseFrame.length = baseFrame.fields[0].values.length;\n  return baseFrame;\n}\n\n/**\n * @internal -- only exported for testing\n */\nexport function reduceFields(data: DataFrame[], matcher: FieldMatcher, reducerId: ReducerID[]): DataFrame[] {\n  const calculators = fieldReducers.list(reducerId);\n  const reducers = calculators.map((c) => c.id);\n  const processed: DataFrame[] = [];\n  for (const series of data) {\n    const fields: Field[] = [];\n    for (const field of series.fields) {\n      if (matcher(field, series, data)) {\n        const results = reduceField({\n          field,\n          reducers,\n        });\n        for (const reducer of reducers) {\n          const value = results[reducer];\n          const copy = {\n            ...field,\n            labels: { ...field.labels },\n            type: getFieldType(reducer, field),\n            values: [value],\n            state: undefined,\n          };\n          if (reducers.length > 1) {\n            if (!copy.labels) {\n              copy.labels = {};\n            }\n            copy.labels['reducer'] = fieldReducers.get(reducer).name;\n          }\n          fields.push(copy);\n        }\n      }\n    }\n    if (fields.length) {\n      processed.push({\n        ...series,\n        fields,\n        length: 1, // always one row\n      });\n    }\n  }\n\n  return processed;\n}\n\nfunction getFieldType(reducer: string, field: Field) {\n  switch (reducer) {\n    case ReducerID.allValues:\n    case ReducerID.uniqueValues:\n      return FieldType.other;\n    case ReducerID.first:\n    case ReducerID.firstNotNull:\n    case ReducerID.last:\n    case ReducerID.lastNotNull:\n      return field.type;\n    default:\n      return FieldType.number;\n  }\n}\n"],"names":["ReduceTransformerMode","DataTransformerID","ReducerID","map","getFieldMatcher","alwaysFieldMatcher","notTimeFieldMatcher","fieldReducers","FieldType","reduceField","getFieldDisplayName","guessFieldTypeForField"],"mappings":"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"}