Last updated

IVAAP Backend Data

This tutorial shows how to request well data from IVAAP backend. This tutorial creates geotoolkit.ivaapbackend.well.RemoteWellLogDataSource datasource to control data requests.

# Log Curve Data

The canvas below shows how Log Curve data can be requested from the server.

import { Plot } from "@int/geotoolkit/plot/Plot.ts";
import { LogCurve } from "@int/geotoolkit/welllog/LogCurve.ts";
import { LogCurveDataSource } from "@int/geotoolkit/welllog/data/LogCurveDataSource.ts";
import { TrackType } from "@int/geotoolkit/welllog/TrackType.ts";
import { HeaderType } from "@int/geotoolkit/welllog/header/LogAxisVisualHeader.ts";
import { Orientation } from "@int/geotoolkit/util/Orientation.ts";
import { RemoteWellLogDataSource } from "@int/geotoolkit/ivaapbackend/well/RemoteWellLogDataSource.ts";
import { UnitFactory } from "@int/geotoolkit/util/UnitFactory.ts";
import { KnownColors } from "@int/geotoolkit/util/ColorUtil.ts";
import { MathUtil } from "@int/geotoolkit/util/MathUtil.ts";
import { log, warn } from "@int/geotoolkit/base.js";
import { authorize, headers } from "/src/helpers/IvaapAutorize.ts";
import { createWellLogWidget } from "/src/code/WellLog/utils/common.ts";
const unitFactory = UnitFactory.getInstance();
unitFactory.addUnit("0.1 in", ["length"], "0.1inch", "m", 0, 254e-5, 1, 0);
const ERROR_LOAD_WELLS = "Cannot load wells from ivaap server";
function isCurveData(data) {
  return data != null && data.length > 0 && typeof data[0] === "number";
}
function generateData(scaleUnit) {
  return getLogCurvesData().then(
    (result) => result.map((data) => {
      let values = data.values;
      if (!isCurveData(values)) {
        return null;
      }
      const depthUnit = unitFactory.getUnit(data.indexUnit);
      values = values.map(
        (value) => MathUtil.equals(value, data.emptyValue) || MathUtil.equals(value, data.nullValue) ? Number.NaN : value
      );
      const depths = data.depths.map((depth) => depthUnit.convert(depth, scaleUnit));
      return new LogCurveDataSource({
        "depths": depths,
        "values": values,
        "name": data.name
      });
    })
  );
}
function getLogCurvesData() {
  const wellsServiceUrl = "https://pub.ivaap.int.com/ivaap/api/ds/mongo/v1/sources/e7b82fa5-6186-404f-994a-d50c18bb23ec/wells";
  const wellsServiceDataSource = new RemoteWellLogDataSource();
  let logDataset = null;
  return authorize().then(
    () => wellsServiceDataSource.setProperties({ "requestheaders": headers }).loadWellsMeta(wellsServiceUrl).then((wellCollection) => {
      const wellMeta = wellCollection.items.find((wellMeta2) => wellMeta2.content.name === "15/9-F-5");
      return wellsServiceDataSource.loadWellData(wellMeta);
    }).then((wellData) => wellsServiceDataSource.loadLogsMeta(wellData)).then((logsCollection) => {
      const logMeta = logsCollection.items.find(
        (meta) => meta.content.name === "QC Data/15/9-F-5/&0&B34604_2"
      );
      return wellsServiceDataSource.loadLogData(logMeta);
    }).then((logData) => {
      logDataset = logData;
      const curveInfoList = logData.content.curveInfoList;
      const logCurves = curveInfoList.filter(
        (info) => info.numColumns === 1 && info.name !== logData.content.indexInfo.indexName
      );
      return Promise.all(logCurves.map((curveInfo) => {
        const curveIds = [curveInfo.dataUID];
        const minIndex = curveInfo.minIndex;
        const maxIndex = curveInfo.maxIndex;
        const indexType = logData.content.indexInfo.indexType;
        return wellsServiceDataSource.loadLogCurveValues(logData, curveIds, minIndex, maxIndex, indexType);
      }));
    }).then(
      (dataArray) => dataArray.map((curvesData) => {
        const indexName = logDataset.content.indexInfo.indexName;
        const depthsData = curvesData.map(
          (curveData) => isCurveData(curveData.data) && curveData.name === indexName ? {
            name: curveData.name,
            depths: curveData.data
          } : null
        ).find((data) => data != null);
        const valuesData = curvesData.map(
          (curveData) => isCurveData(curveData.data) && curveData.name !== indexName ? {
            name: curveData.name,
            values: curveData.data
          } : null
        ).find((data) => data != null);
        const curveInfoList = logDataset.content.curveInfoList;
        const curveInfo = curveInfoList.find((info) => info.name === valuesData.name);
        return {
          name: valuesData.name,
          depths: depthsData.depths,
          values: valuesData.values,
          emptyValue: curveInfo.emptyValue,
          nullValue: curveInfo.nullValue,
          indexUnit: logDataset.content.indexInfo.unitName
        };
      })
    )
  ).catch((error) => {
    log(error);
    throw new Error(ERROR_LOAD_WELLS);
  });
}
function createScene(canvas) {
  const widget = createWellLogWidget().setOrientation(Orientation.Vertical).setAxisHeaderType(HeaderType.Simple).scale(2);
  generateData(widget.getTrackContainer().getIndexUnit()).then((dataSources) => {
    if (widget.isDisposed())
      return;
    let minDepth = Number.POSITIVE_INFINITY;
    let maxDepth = Number.NEGATIVE_INFINITY;
    widget.addTrack(TrackType.IndexTrack);
    dataSources.forEach((dataSource) => {
      if (minDepth > dataSource.getMinDepth()) {
        minDepth = dataSource.getMinDepth();
      }
      if (maxDepth < dataSource.getMaxDepth()) {
        maxDepth = dataSource.getMaxDepth();
      }
      widget.addTrack(TrackType.LinearTrack).addChild([
        new LogCurve(dataSource).setLineStyle(KnownColors.Red)
      ]);
      widget.addTrack(TrackType.IndexTrack);
    });
    widget.setDepthLimits(minDepth, maxDepth);
  }).catch((error) => {
    warn(error);
  });
  return new Plot({
    "canvaselement": canvas,
    "root": widget
  });
}
export { createScene };

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

# Array Log Data

The canvas below shows how Array Log data can be requested from the server.

import { Log2DVisual, PlotTypes } from "@int/geotoolkit/welllog/Log2DVisual.ts";
import { TrackType } from "@int/geotoolkit/welllog/TrackType.ts";
import { HeaderType } from "@int/geotoolkit/welllog/header/LogAxisVisualHeader.ts";
import { Orientation } from "@int/geotoolkit/util/Orientation.ts";
import { CompositeLog2DVisualHeader } from "@int/geotoolkit/welllog/header/CompositeLog2DVisualHeader.ts";
import { ArrayLogDataSource } from "@int/geotoolkit/welllog/data/ArrayLogDataSource.ts";
import { DataTable } from "@int/geotoolkit/data/DataTable.ts";
import { Plot } from "@int/geotoolkit/plot/Plot.ts";
import { RemoteWellLogDataSource } from "@int/geotoolkit/ivaapbackend/well/RemoteWellLogDataSource.ts";
import { UnitFactory } from "@int/geotoolkit/util/UnitFactory.ts";
import { MathUtil } from "@int/geotoolkit/util/MathUtil.ts";
import { log, warn } from "@int/geotoolkit/base.js";
import { create2DVisual } from "/src/code/WellLog/utils/util.ts";
import { authorize, headers } from "/src/helpers/IvaapAutorize.ts";
import { createWellLogWidget } from "/src/code/WellLog/utils/common.ts";
const unitFactory = UnitFactory.getInstance();
unitFactory.addUnit("0.1 in", ["length"], "0.1inch", "m", 0, 254e-5, 1, 0);
const ERROR_LOAD_WELLS = "Cannot load wells from ivaap server";
function isArrayData(data) {
  return data != null && data.length > 0 && Array.isArray(data[0]);
}
function generateData(scaleUnit) {
  return getLogArrayData().then(
    (result) => result.map((data) => {
      const table = new DataTable({
        "cols": [
          { "name": "depth", "type": "number", "unit": scaleUnit.getSymbol() },
          ...data.angles.map((v) => ({ "name": v + "", "type": "number" }))
        ],
        "colsdata": []
      });
      const depthUnit = unitFactory.getUnit(data.indexUnit);
      for (let i = 0; i < data.depths.length; i++) {
        let row = data.values[i];
        if (!Array.isArray(row))
          continue;
        row = row.map(
          (value) => MathUtil.equals(value, data.emptyValue) || MathUtil.equals(value, data.nullValue) ? Number.NaN : value
        );
        const depth = depthUnit.convert(data.depths[i], scaleUnit);
        table.addRow([depth, ...row]);
      }
      return new ArrayLogDataSource({
        "name": data["name"],
        "datatable": table,
        "angles": {
          "values": data["angles"]
        }
      });
    })
  );
}
function generateAngles(values) {
  return values[0].map((v, i, arr) => Math.PI * 2 / (arr.length - 1) * i);
}
function getLogArrayData() {
  const wellsServiceUrl = "https://pub.ivaap.int.com/ivaap/api/ds/mongo/v1/sources/e7b82fa5-6186-404f-994a-d50c18bb23ec/wells";
  const wellsServiceDataSource = new RemoteWellLogDataSource();
  let logDataset = null;
  return authorize().then(
    () => wellsServiceDataSource.setProperties({ "requestheaders": headers }).loadWellsMeta(wellsServiceUrl).then((wellCollection) => {
      const wellMeta = wellCollection.items.find((wellMeta2) => wellMeta2.content.name === "15/9-F-5");
      return wellsServiceDataSource.loadWellData(wellMeta);
    }).then((wellData) => wellsServiceDataSource.loadLogsMeta(wellData)).then((logsCollection) => {
      const logMeta = logsCollection.items.find(
        (meta) => meta.content.name === "QC Data/15/9-F-5/&0&B34604_2"
      );
      return wellsServiceDataSource.loadLogData(logMeta);
    }).then((logData) => {
      logDataset = logData;
      const curveInfoList = logData.content.curveInfoList;
      const logArrays = curveInfoList.filter((info) => info.numColumns > 1);
      return Promise.all(logArrays.map((curveInfo) => {
        const curveIds = [curveInfo.dataUID];
        const minIndex = curveInfo.minIndex;
        const maxIndex = curveInfo.maxIndex;
        const indexType = logData.content.indexInfo.indexType;
        return wellsServiceDataSource.loadLogCurveValues(logData, curveIds, minIndex, maxIndex, indexType);
      }));
    }).then(
      (dataArray) => dataArray.map((curvesData) => {
        const depthsData = curvesData.map(
          (curveData) => !isArrayData(curveData.data) ? {
            name: curveData.name,
            depths: curveData.data
          } : null
        ).find((data) => data != null);
        const valuesData = curvesData.map(
          (curveData) => isArrayData(curveData.data) ? {
            name: curveData.name,
            values: curveData.data
          } : null
        ).find((data) => data != null);
        const angles = generateAngles(valuesData.values);
        const curveInfoList = logDataset.content.curveInfoList;
        const curveInfo = curveInfoList.find((info) => info.name === valuesData.name);
        return {
          name: valuesData.name,
          depths: depthsData.depths,
          values: valuesData.values,
          angles,
          emptyValue: curveInfo.emptyValue,
          nullValue: curveInfo.nullValue,
          indexUnit: logDataset.content.indexInfo.unitName
        };
      })
    )
  ).catch((error) => {
    log(error);
    throw new Error(ERROR_LOAD_WELLS);
  });
}
function createScene(canvas) {
  const widget = createWellLogWidget().setOrientation(Orientation.Vertical).setAxisHeaderType(HeaderType.Simple).scale(2);
  const headerProvider = widget.getHeaderContainer().getHeaderProvider();
  headerProvider.registerHeaderProvider(Log2DVisual.getClassName(), new CompositeLog2DVisualHeader());
  generateData(widget.getTrackContainer().getIndexUnit()).then((dataSources) => {
    if (widget.isDisposed())
      return;
    let minDepth = Number.MAX_VALUE;
    let maxDepth = Number.MIN_VALUE;
    widget.addTrack(TrackType.IndexTrack);
    dataSources.forEach((dataSource) => {
      if (minDepth > dataSource.getMinDepth()) {
        minDepth = dataSource.getMinDepth();
      }
      if (maxDepth < dataSource.getMaxDepth()) {
        maxDepth = dataSource.getMaxDepth();
      }
      widget.addTrack(TrackType.LinearTrack).addChild([
        create2DVisual(dataSource, dataSource.getName(), 0, "#fff9c4", true).setPlotType(PlotTypes.Linear)
      ]);
      widget.addTrack(TrackType.IndexTrack);
    });
    widget.setDepthLimits(minDepth, maxDepth);
  }).catch((error) => {
    warn(error);
  });
  return new Plot({
    "canvaselement": canvas,
    "root": widget
  });
}
export { createScene };

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