File

src/pages/dataPortal/modules/graphPanel/objects/data/covJsonData.ts

Index

Properties
Methods
Accessors

Constructor

constructor(dataConfigurableId: string)
Parameters :
Name Type Optional
dataConfigurableId string No

Properties

Private Readonly _traces
Default value : new Array<Trace>()

Methods

Public addErrorTrace
addErrorTrace(rawErrorTrace: Trace, errorMin: Array, errorMax: Array)
Parameters :
Name Type Optional
rawErrorTrace Trace No
errorMin Array<string> No
errorMax Array<string> No
Returns : void
Public createTraces
createTraces(data: Record)
Parameters :
Name Type Optional
data Record<string | > No
Returns : Array<Trace>
Public getAxisValues
getAxisValues(valuesObject: Record)

numbers: { "values": [0.1, 0.2, ... ,0.3] } { "start": -179.5, "stop": 179.5, "num": 360 } date/time: { "values": ["2018-01-01T00:00:00.000Z", "2018-01-02T00:00:00.000Z", ..., "2018-01-01T23:59:00.000Z"] } { "start": "2018-01-01T00:00:00.000Z", "stop": "2018-01-01T23:59:00.000Z", "num": 1440 }

Parameters :
Name Type Optional Description
valuesObject Record<string | > No

either of form: numbers: { "values": [0.1, 0.2, ... ,0.3] } { "start": -179.5, "stop": 179.5, "num": 360 } date/time: { "values": ["2018-01-01T00:00:00.000Z", "2018-01-02T00:00:00.000Z", ..., "2018-01-01T23:59:00.000Z"] } { "start": "2018-01-01T00:00:00.000Z", "stop": "2018-01-01T23:59:00.000Z", "num": 1440 }

Returns : Array<string>
Private getDataValue
getDataValue(data: Record, path: Array, onlyString)
Type parameters :
  • T
Parameters :
Name Type Optional Default value
data Record<string | > No
path Array<string> No
onlyString No false
Returns : T
Private getMode
getMode(mode: string)
Parameters :
Name Type Optional
mode string No
Returns : ModePlotly
Private getType
getType(type: string)
Parameters :
Name Type Optional
type string No
Returns : null | PlotType
Private temporalValuesFromDateStrings
temporalValuesFromDateStrings(startString: string, stopString: string, count: number)
Parameters :
Name Type Optional
startString string No
stopString string No
count number No
Returns : Array<string>
Private temporalValuesFromNumbers
temporalValuesFromNumbers(start: number, stop: number, count: number)
Parameters :
Name Type Optional
start number No
stop number No
count number No
Returns : Array<string>

Accessors

traces
gettraces()
import moment from 'moment-es6';
import { PlotType } from 'plotly.js';
import { Trace ,ModePlotly } from '../trace';


enum TraceDataTypes {
  PARAMETER_GROUP = 'ParameterGroup',
  PARAMETER = 'Parameter',
  ERROR_MAX = 'error_max',
  ERROR_MIN = 'error_min',
}



export class CovJsonData {
  private readonly _traces = new Array<Trace>();
  constructor(private readonly dataConfigurableId: string) {
  }

  get traces(): Array<Trace> {
    return this._traces;
  }

  public createTraces(data: Record<string, unknown>): Array<Trace> {
    // some services with Graph visualization do not have 'type' property specified. These services are all single Coverage. This is why we check here for 'data.type == null'.
    // GNSS has to pass 'type' (all the services have to!) !!!
    // Coverage
    if (data.type === 'Coverage' || data.type == null ) {
      const members: string[] = [];
      let errorMax: Array<string> = [];
      let errorMin: Array<string> = [];
      // First pass: Populate members
      for (const key of Object.keys(this.getDataValue(data, ['parameters']))) {
        const covJsonType = this.getDataValue<string>(data, ['parameters', key, 'type']);
        if (covJsonType === (TraceDataTypes.PARAMETER_GROUP as string)) {
          const newMembers = this.getDataValue<string[]>(data, ['parameters', key, 'members']) || [];
          members.push(...newMembers);
        }
      }
      // Second pass: Process traces
      for (const key of Object.keys(this.getDataValue(data, ['parameters']))) {
        const covJsonType = this.getDataValue<string>(data, ['parameters', key, 'type']);
        const paramId = this.getDataValue<string>(data, ['parameters', key, 'observedProperty', 'id']);
        const mode = this.getMode(this.getDataValue(data, ['parameters' , key , 'plotType']));
        if (covJsonType === (TraceDataTypes.PARAMETER as string)) {
          const type = this.getType(this.getDataValue(data, ['domain', 'domainType']));
          const name = this.getDataValue<string>(data, ['parameters', key, 'observedProperty', 'label', 'en']);
          const description = this.getDataValue<string>(data, ['parameters', key, 'description', 'en']);
          const yUnit = this.getDataValue<string>(data, ['parameters', key, 'unit', 'symbol', 'value'], true);
          let yUnitLabel = this.getDataValue<string>(data, ['parameters', key, 'unit', 'label', 'en'], true);
          if (yUnitLabel === '') {
            yUnitLabel = this.getDataValue<string>(data, ['parameters', key, 'observedProperty', 'label', 'en'], true);
          }
          const yValues = this.getAxisValues(this.getDataValue(data, ['ranges', key]));
          const xValues = this.getAxisValues(this.getDataValue(data, ['domain', 'axes', 't']));
          if (paramId === (TraceDataTypes.ERROR_MAX as string)) {
            errorMax = this.getAxisValues(this.getDataValue(data, ['ranges', key]));
          }
          if (paramId === (TraceDataTypes.ERROR_MIN as string)) {
            errorMin = this.getAxisValues(this.getDataValue(data, ['ranges', key]));
          }
          if (type !== null) {
            const trace = new Trace(this.dataConfigurableId, key + this.dataConfigurableId, type, name, description, yUnit, yUnitLabel, yValues, xValues ,mode);
            if (key !== (TraceDataTypes.ERROR_MIN as string) && key !== (TraceDataTypes.ERROR_MAX as string)) {
              this._traces.push(trace);
            }
            if (members.length > 0) {
              if (members.includes(key) && key !== (TraceDataTypes.ERROR_MIN as string) && key !== (TraceDataTypes.ERROR_MAX as string)) {
                this.addErrorTrace(trace, errorMin, errorMax);
              }
            }
          }
        }
      }
      return this._traces;
    }
    // CoverageCollection
    else {
      Object.keys(this.getDataValue(data, ['coverages'])).forEach((key: string) => {
        // CoverageCollection
        const type = this.getType(this.getDataValue(data, ['coverages', '0' , 'domain', 'domainType']));
        const name = this.getDataValue<string>(data, ['coverages', key, 'name']);
        let ccParamDesc: string = '';
        let ccParamYUnit: string = '';
        let ccParamYUnitLabel: string = '';
        let ccParamYValues: string[] = [];
        // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call
        const ranges = this.getDataValue<object>(data, ['coverages', key, 'ranges']);

        for (const rangeKey of Object.keys(ranges)) {
          ccParamDesc = this.getDataValue<string>(data, ['parameters', rangeKey, 'description', 'en']);
          ccParamYUnit = this.getDataValue<string>(data, ['parameters', rangeKey, 'unit', 'symbol']);
          ccParamYUnitLabel = this.getDataValue<string>(data, ['parameters', rangeKey, 'observedProperty', 'label', 'en'], true);
          ccParamYValues = this.getAxisValues(this.getDataValue(data, ['coverages', key, 'ranges', rangeKey]));

          // const mode = this.getMode(this.getDataValue(data, ['parameters' , rangeKey, 'plotType']));

          const description = ccParamDesc;
          const yUnit = ccParamYUnit;
          const yUnitLabel = ccParamYUnitLabel;
          /* if (yUnitLabel === '') {
            yUnitLabel = this.getDataValue<string>(data, ['parameters', key, 'observedProperty', 'label', 'en'], true);
          } */

          const yValues = ccParamYValues; // this.getAxisValues(this.getDataValue(data, ['coverages', key, 'ranges', key, 'values']));
          const xValues = this.getAxisValues(this.getDataValue(data, ['coverages', key, 'domain', 'axes', 't']));

          if (null != type) {
            this._traces.push(
              new Trace(
                this.dataConfigurableId,
                key + this.dataConfigurableId + rangeKey,
                // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
                type,
                name + ' - ' + rangeKey,
                description,
                yUnit,
                yUnitLabel,
                yValues,
                xValues,
                // mode,
              ),
            );
          }
        }

      });
      return this._traces;
    }
  }

  public addErrorTrace(rawErrorTrace: Trace, errorMin: Array<string>, errorMax: Array<string>): void {
    const errorTrace = new Trace(
      this.dataConfigurableId,
      rawErrorTrace.id + this.dataConfigurableId,
      rawErrorTrace.type,
      rawErrorTrace.name + ' with errors',
      rawErrorTrace.description,
      rawErrorTrace.yUnit,
      rawErrorTrace.yUnitLabel,
      rawErrorTrace.yValues,
      rawErrorTrace.xValues,
      rawErrorTrace.mode,
    );
    errorTrace.yErrorMinValues = errorMin;
    errorTrace.yErrorMaxValues = errorMax;
    this._traces.push(errorTrace);
  }

  /**
   * @param valuesObject either of form:
   * numbers:
   * { "values": [0.1, 0.2, ... ,0.3] }
   * { "start": -179.5, "stop": 179.5, "num": 360 }
   * date/time:
   * { "values": ["2018-01-01T00:00:00.000Z", "2018-01-02T00:00:00.000Z", ..., "2018-01-01T23:59:00.000Z"] }
   * { "start": "2018-01-01T00:00:00.000Z", "stop": "2018-01-01T23:59:00.000Z", "num": 1440 }
   */
  // TODO lint: new return type and forced conversions to string need testing!
  public getAxisValues(valuesObject: Record<string, unknown>): Array<string> {
    let axisValues = new Array<string>();
    try {
      // values in array form
      if (null != valuesObject.values) {
        axisValues = (valuesObject.values as Array<unknown>).map((val) => String(val));
      } else if (typeof valuesObject.num === 'number') {
        // values need expanding
        const count = valuesObject.num;
        if (typeof valuesObject.start === 'number') {
          axisValues = this.temporalValuesFromNumbers(valuesObject.start, Number(valuesObject.stop), count);
        } else if (typeof valuesObject.start === 'string' && moment.utc(valuesObject.start).isValid()) {
          axisValues = this.temporalValuesFromDateStrings(valuesObject.start, String(valuesObject.stop), count);
        }
      }
    } catch (e) {
      console.warn('CovJSON data: problem proceessing axis values', valuesObject);
    }
    return axisValues;
  }

  private temporalValuesFromDateStrings(startString: string, stopString: string, count: number): Array<string> {
    const start = moment.utc(startString);
    const stop = moment.utc(stopString);
    const min = Math.min(start.valueOf(), stop.valueOf());
    const max = Math.max(start.valueOf(), stop.valueOf());
    const increment = (max - min) / (count - 1);
    const expandedValues = new Array<string>();
    for (let i = min; i <= max; i += increment) {
      expandedValues.push(moment.utc(i).toISOString());
    }
    if (start.isAfter(stop)) {
      expandedValues.reverse();
    }
    return expandedValues;
  }

  private temporalValuesFromNumbers(start: number, stop: number, count: number): Array<string> {
    // numbers
    const min = Math.min(start, stop);
    const max = Math.max(start, stop);
    const increment = (max - min) / (count - 1);
    const expandedValues = new Array<string>();
    for (let i = min; i <= max; i += increment) {
      expandedValues.push(String(i));
    }
    if (start > stop) {
      expandedValues.reverse();
    }
    return expandedValues;
  }

  private getDataValue<T = unknown>(data: Record<string, unknown>, path: Array<string>, onlyString = false): T {
    let value = data as unknown;
    path.forEach((pathSection: string) => {
      if ((value as Record<string, unknown>)[pathSection] !== undefined) {
        value = (value as Record<string, unknown>)[pathSection];
        if (null == value) {
          return null;
        }
      }
    });

    if (onlyString === true && typeof value === 'object') {
      value = '';
    }

    return value as T;
  }

  private getType(type: string): null | PlotType {
    switch (type) {
      case 'PointSeries':
        return 'scatter';
      default:
        console.warn(`Unrecognised trace type: '${type}' `);
        return null;
    }
  }

  private getMode(mode: string): ModePlotly{
    switch (mode) {
      case 'https://www.data-to-viz.com/graph/scatter.html':
        return 'markers';
      default:
        console.warn(`Unrecognised trace mode: '${mode}' `);
        return  'lines';
    }
  }
}

results matching ""

    No results matching ""