Last updated

Data connection

This Data Connection tutorial demonstrates how to serve data to WellLog widgets. Data can be located on different servers. The way the data is delivered from the server to the application memory is unrestricted and depends on the task. Delivering data can be accomplished with these two methods:

  • Traditonal: Set up the data directly to the instance of the visual. Set up includes creating a data source such as LogData, requesting data from the server and adding the data to the instance of the visual.
  • Binding: Connect your data model to the WellLog widget. The data model represents a hierarchical data structure (the data is organized into a tree-like structure) located in memory and a set of data- binding. The binding associates a visual instance, such as a curve, with data. The widget notifies a data source to request a range of the data which is provided by a request from the server and fills the data model.

# Traditional Method - setData called on child shape

The Traditional method covers sending data directly to the instance of the visual using the following steps.

  • Create a WellLog widget and add tracks.
  • Create a data source. The code below creates log data in the memory. For example, by using an Ajax request to the server.
  • Create a curve and connect data to it.
import { Plot } from "@int/geotoolkit/plot/Plot.ts";
import { HeaderType } from "@int/geotoolkit/welllog/header/LogAxisVisualHeader.ts";
import { TrackType } from "@int/geotoolkit/welllog/TrackType.ts";
import { KnownColors } from "@int/geotoolkit/util/ColorUtil.ts";
import { createCurve } from "/src/code/WellLog/utils/curveData.ts";
import { createWellLogWidget } from "/src/code/WellLog/utils/common.ts";
const createScene = (canvas) => {
  const widget = createWellLogWidget().setAxisHeaderType(HeaderType.Simple).scale(0.192);
  widget.addTrack(TrackType.IndexTrack);
  widget.addTrack(TrackType.LinearTrack).addChild([createCurve(4500, 10, "CALI", KnownColors.Green)]);
  widget.addTrack(TrackType.LinearTrack).addChild([createCurve(4500, 10, "CALI", KnownColors.Red)]);
  return new Plot({
    "canvaselement": canvas,
    "root": widget
  });
};
export { createScene };

createScene(document.querySelector('[ref="plot"]'));

# Traditional Method with update request

In most cases, the data is big and it is necessary to load only a part of the data by request as a rule visible range. The first step is to set up a full depth or time range to the widget using the method setDepthLimits. If a widget is scrolled or the depth scale is changed, the widget sends notification events and data can be requested from the server. To avoid unnecessary server requests, GeoToolkit does not send notification events on individual log data.

import { HeaderType } from "@int/geotoolkit/welllog/header/LogAxisVisualHeader.ts";
import { TrackType } from "@int/geotoolkit/welllog/TrackType.ts";
import { from } from "@int/geotoolkit/selection/from.ts";
import { LogCurve } from "@int/geotoolkit/welllog/LogCurve.ts";
import { LogData } from "@int/geotoolkit/welllog/data/LogData.ts";
import { Plot } from "@int/geotoolkit/plot/Plot.ts";
import { KnownColors } from "@int/geotoolkit/util/ColorUtil.ts";
import { Events } from "@int/geotoolkit/welllog/widgets/Events.ts";
import { getCurveData } from "/src/code/WellLog/utils/curveData.ts";
import { createWellLogWidget } from "/src/code/WellLog/utils/common.ts";
const updateCurves = (widget) => {
  const limits = widget.getVisibleDepthLimits();
  from(widget).where((node) => node instanceof LogCurve).execute((node) => {
    const curveMnemonic = node.getName();
    const data = node.getDataSource();
    const depths = [];
    const values = [];
    const step = 10;
    const start = 4500;
    const curveData = getCurveData(curveMnemonic);
    const amountOfPoints = curveData.length;
    for (let i = 0; i < amountOfPoints; i++) {
      const depth = i * step + start;
      if (depth < limits.getLow() - step)
        continue;
      if (depth > limits.getHigh() + step)
        break;
      depths.push(depth);
      values.push(curveData[i]);
    }
    data.setValues(depths, values);
  });
};
const createScene = (canvas) => {
  const widget = createWellLogWidget().setAxisHeaderType(HeaderType.Simple).scale(0.192);
  widget.addTrack(TrackType.IndexTrack);
  widget.addTrack(TrackType.LinearTrack).addChild([
    new LogCurve(new LogData("CALI")).setLineStyle(KnownColors.Green).setNormalizationLimits(7, 12)
  ]);
  widget.addTrack(TrackType.LinearTrack).addChild([
    new LogCurve(new LogData("DLT")).setLineStyle(KnownColors.Red).setNormalizationLimits(42, 109)
  ]);
  widget.on(Events.VisibleDepthLimitsChanged, () => {
    updateCurves(widget);
  });
  widget.on(Events.DataUpdating, () => {
    updateCurves(widget);
  });
  updateCurves(widget);
  return new Plot({
    "canvaselement": canvas,
    "root": widget
  });
};
export { createScene };

createScene(document.querySelector('[ref="plot"]'));

# Binding - setData called on WellLog Widget

Controlling the data source for each curve is not very convenient, so widgets provides an API to group data to one data model and provide a way to connect data to each visual. This is called data binding, which includes the following steps. Create a WellLog widget, then add tracks, shapes, and a binding function, which is called each time new data is set up or a new visual is added. Binding functions require two methods:

  1. Accept, run to check if the data is compatible with the child visual.

  2. Bind, if accepted, should switch the data in the child visual.

Optionally, a binding function can contain unbind, run to cleanup a child visual prior to bind. A typical use would be to change like data with like data between data sets.

import { HeaderType } from "@int/geotoolkit/welllog/header/LogAxisVisualHeader.ts";
import { TrackType } from "@int/geotoolkit/welllog/TrackType.ts";
import { LogCurve } from "@int/geotoolkit/welllog/LogCurve.ts";
import { LogData } from "@int/geotoolkit/welllog/data/LogData.ts";
import { Plot } from "@int/geotoolkit/plot/Plot.ts";
import { KnownColors } from "@int/geotoolkit/util/ColorUtil.ts";
import { DataSource } from "/src/code/WellLog/DataAndTemplates/DataConnection/datasource.ts";
import { DataBindingRegistry } from "@int/geotoolkit/data/DataBindingRegistry.ts";
import { createWellLogWidget } from "/src/code/WellLog/utils/common.ts";
const createScene = (canvas) => {
  const widget = createWellLogWidget().setAxisHeaderType(HeaderType.Simple).scale(2);
  widget.addTrack(TrackType.IndexTrack);
  widget.addTrack(TrackType.LinearTrack).addChild([
    new LogCurve(new LogData("GR")).setLineStyle(KnownColors.Green)
  ]);
  widget.addTrack(TrackType.LogTrack).addChild([
    new LogCurve(new LogData("ROP")).setLineStyle(KnownColors.Red)
  ]);
  const data = new DataSource();
  const widgetBinding = widget.getDataBinding();
  if (widgetBinding instanceof DataBindingRegistry) {
    data.bind(widgetBinding);
  }
  widget.setData(data).setDepthLimits(data.getIndexRange());
  return [new Plot({
    "canvaselement": canvas,
    "root": widget
  }), data];
};
const dispose = (plot, data) => {
  data.dispose();
  plot.dispose();
};
export { createScene, dispose };

createScene(document.querySelector('[ref="plot"]'));

# Datasource Implementation

Implementing the data source extends the geotoolkit/data/DataSource and provides LogCurveDataSource for each curve.