Last updated

Depth Index Conversion

This tutorial demonstrates how to switch Depth Index in WellBore and assumes familiarity with WellLog Widget tutorial in WellLog.
At any given point in WellBore, there will be two depths: MD (Measured Depth) and TVD (True Vertical Depth).
For a perfectly vertical WellBore, the values of TVD and MD are equal. However, WellBores are not always drilled perfectly vertical and it is possible that values of MD and TVD are different. At any given point, TVD is less than or equal to MD.

# Create and display Data Table

The following code shows steps to create DataTable and display data in a TableView. For more details, please refer to the Table View tutorial. The main purpose is to illustrate whole data only.

import { Plot } from "@int/geotoolkit/plot/Plot.ts";
import { LogCurveDataSource } from "@int/geotoolkit/welllog/data/LogCurveDataSource.ts";
import { TableView } from "@int/geotoolkit/widgets/TableView.ts";
import { Rect } from "@int/geotoolkit/util/Rect.ts";
import { NumericalDataSeries } from "@int/geotoolkit/data/NumericalDataSeries.ts";
import { DataTable } from "@int/geotoolkit/data/DataTable.ts";
import { TableViewDataSource } from "/src/code/WellLog/DataAndTemplates/DepthIndexConversion/TableViewDataSource.ts";
class TableWidget {
  constructor(options) {
    this.table = this.createDataTable();
    this.widget = this.createTableWidget();
    this.plot = new Plot({
      "canvaselement": options.canvas,
      "root": this.widget
    });
  }
  dispose() {
    if (this.plot) {
      this.plot.dispose();
    }
  }
  createDataTable() {
    const md = new NumericalDataSeries({
      "name": "MD",
      "unit": "ft",
      "data": [10, 12, 20, 27, 30, 35, 40, 42, 50, 55, 60, 67, 70, 75]
    });
    const tvd = new NumericalDataSeries({
      "name": "TVD",
      "unit": "ft",
      "data": [8, 10, 15, 20, 25, 25, 30, 37, 40, 40, 42, 45, 50, 60]
    });
    const gr = new NumericalDataSeries({
      "name": "GR",
      "data": [6, 9, 7, 11, 10, 6, 7, 6, 9, 10, 11, 7, 10, 6]
    });
    const cali = new NumericalDataSeries({
      "name": "CALI",
      "data": [75, 100, 90, 50, 60, 95, 60, 75, 80, 100, 40, 67, 40, 80]
    });
    const series = [md, tvd, gr, cali];
    const dataTable = new DataTable({
      "cols": series
    });
    const depthsMD = dataTable.getColumn(0).toArray();
    const depthsTVD = dataTable.getColumn(1).toArray();
    const grValues = dataTable.getColumn(2).toArray();
    const caliValues = dataTable.getColumn(3).toArray();
    this.dataSourceMD = {
      "GR": new LogCurveDataSource({
        "name": "GR",
        "depths": depthsMD,
        "values": grValues
      }),
      "CALI": new LogCurveDataSource({
        "name": "CALI",
        "depths": depthsMD,
        "values": caliValues
      })
    };
    this.dataSourceTVD = {
      "GR": new LogCurveDataSource({
        "name": "GR",
        "depths": depthsTVD,
        "values": grValues
      }),
      "CALI": new LogCurveDataSource({
        "name": "CALI",
        "depths": depthsTVD,
        "values": caliValues
      })
    };
    const dataForTable = [depthsMD, depthsTVD, grValues, caliValues];
    const tableOptions = {
      rows: dataTable.getNumberOfRows(),
      columns: dataTable.getNumberOfColumns(),
      data: dataForTable
    };
    return new TableViewDataSource(tableOptions);
  }
  createTableWidget() {
    const widget = new TableView({
      "bounds": new Rect(0, 0, 800, 100),
      "horizontalscrollable": "floating",
      "verticalscrollable": "floating"
    }).setData({
      "indexvisible": false,
      "dataprovider": this.table,
      "rows": this.table.getRowsCount(),
      "cols": this.table.getColumnsCount()
    }).fitToWidth(true);
    return widget;
  }
}
export { TableWidget };

createScene();

# Index Conversion in WellLog Widget

For displaying different Indexes in the WellLog widget, update the DataBinding and DepthsLimitis. For that, create DataBindingRegistry for MD and TVD index. DataBindingRegistery is attached to visuals. When the index value is changed, instead of disposing the plot and redrawing it, just change DataBinding and DepthLimits according to LogCurveDataSource.

import { Plot } from "@int/geotoolkit/plot/Plot.ts";
import { LogCurveDataSource } from "@int/geotoolkit/welllog/data/LogCurveDataSource.ts";
import { NumericalDataSeries } from "@int/geotoolkit/data/NumericalDataSeries.ts";
import { DataTable } from "@int/geotoolkit/data/DataTable.ts";
import { DataBindingRegistry } from "@int/geotoolkit/data/DataBindingRegistry.ts";
import { LogCurve } from "@int/geotoolkit/welllog/LogCurve.ts";
import { TrackType } from "@int/geotoolkit/welllog/TrackType.ts";
import { from } from "@int/geotoolkit/selection/from.ts";
import { KnownColors } from "@int/geotoolkit/util/ColorUtil.ts";
import { LogAxis } from "@int/geotoolkit/welllog/LogAxis.ts";
import { createWellLogWidget } from "/src/code/WellLog/utils/common.ts";
class IndexWidget {
  constructor(options) {
    this.leftAxis = null;
    this.rightAxis = null;
    this.dataSourceMD = null;
    this.dataSourceTVD = null;
    this.createData();
    this.createRegistry();
    this.widget = this.createIndexWidget();
    this.plot = new Plot({
      "canvaselement": options.canvas,
      "root": this.widget
    });
    this.widget.fitToHeight().fitToWidth();
    this.setOrder(true);
  }
  dispose() {
    if (this.plot) {
      this.plot.dispose();
    }
  }
  createData() {
    const md = new NumericalDataSeries({
      "name": "MD",
      "unit": "ft",
      "data": [10, 12, 20, 27, 30, 35, 40, 42, 50, 55, 60, 67, 70, 75]
    });
    const tvd = new NumericalDataSeries({
      "name": "TVD",
      "unit": "ft",
      "data": [8, 10, 15, 20, 25, 25, 30, 37, 40, 40, 42, 45, 50, 60]
    });
    const gr = new NumericalDataSeries({
      "name": "GR",
      "data": [6, 9, 7, 11, 10, 6, 7, 6, 9, 10, 11, 7, 10, 6]
    });
    const cali = new NumericalDataSeries({
      "name": "CALI",
      "data": [75, 100, 90, 50, 60, 95, 60, 75, 80, 100, 40, 67, 40, 80]
    });
    const series = [md, tvd, gr, cali];
    const dataTable = new DataTable({
      "cols": series
    });
    const depthsMD = dataTable.getColumn(0).toArray();
    const depthsTVD = dataTable.getColumn(1).toArray();
    const grValues = dataTable.getColumn(2).toArray();
    const caliValues = dataTable.getColumn(3).toArray();
    this.dataSourceMD = {
      "GR": new LogCurveDataSource({
        "name": "GR",
        "depths": depthsMD,
        "values": grValues
      }),
      "CALI": new LogCurveDataSource({
        "name": "CALI",
        "depths": depthsMD,
        "values": caliValues
      })
    };
    this.dataSourceTVD = {
      "GR": new LogCurveDataSource({
        "name": "GR",
        "depths": depthsTVD,
        "values": grValues
      }),
      "CALI": new LogCurveDataSource({
        "name": "CALI",
        "depths": depthsTVD,
        "values": caliValues
      })
    };
  }
  createRegistry() {
    this.registryForMdIndex = new DataBindingRegistry();
    this.registryForMdIndex.add({
      accept: (node) => node instanceof LogCurve,
      bind: (curve) => curve.setData(this.dataSourceMD[curve.getName()])
    });
    this.registryForTvdIndex = new DataBindingRegistry();
    this.registryForTvdIndex.add({
      accept: (node) => node instanceof LogCurve,
      bind: (curve) => curve.setData(this.dataSourceTVD[curve.getName()])
    });
  }
  createIndexWidget() {
    const widget = createWellLogWidget().setDepthLimits(this.dataSourceMD.GR.getMinDepth(), this.dataSourceMD.GR.getMaxDepth()).setDataBinding(this.registryForMdIndex);
    const leftIndex = widget.addTrack(TrackType.IndexTrack);
    widget.addTrack(TrackType.LinearTrack).addChild([
      new LogCurve().setName("CALI").setLineStyle(KnownColors.Orange)
    ]);
    widget.addTrack(TrackType.LinearTrack).addChild([
      new LogCurve().setName("GR").setLineStyle(KnownColors.Green)
    ]);
    const rightIndex = widget.addTrack(TrackType.IndexTrack);
    const getAxis = (track) => from(track).where((node) => node instanceof LogAxis).selectFirst();
    this.leftAxis = getAxis(leftIndex).setName("MD");
    this.rightAxis = getAxis(rightIndex).setName("MD");
    return widget;
  }
  setOrder(value) {
    const dataBinding = value ? this.registryForMdIndex : this.registryForTvdIndex;
    const data = value ? this.dataSourceMD.GR : this.dataSourceTVD.GR;
    const name = value ? "MD" : "TVD";
    const minLimit = data.getMinDepth();
    const maxLimit = data.getMaxDepth();
    this.widget.setDataBinding(dataBinding);
    this.widget.setDepthLimits(minLimit, maxLimit);
    this.leftAxis.setName(name);
    this.rightAxis.setName(name);
  }
}
export { IndexWidget };

createScene();