This tutorial describes how to customize geotoolkit/welllog/multiwell/MultiWellWidget. It displays three well tracks and correlation panels added in between tracks. The wells are displayed with different depth scales and offsets. Please refer to Multi Well Correlation tutorial for more details.
# Specify headers alignment
After creating MultiWellWidget you can specify header alignment.
# Header Alignment Result
This example displays how to specify header alignment.
import { Plot } from "@int/geotoolkit/plot/Plot.ts";
import { MultiWellWidget } from "@int/geotoolkit/welllog/multiwell/MultiWellWidget.ts";
import { TrackType as MultiWellTrackType } from "@int/geotoolkit/welllog/multiwell/TrackType.ts";
import { TrackType as WellLogTrackType } from "@int/geotoolkit/welllog/TrackType.ts";
import { LogData } from "@int/geotoolkit/welllog/data/LogData.ts";
import { LogCurve } from "@int/geotoolkit/welllog/LogCurve.ts";
import { LogMarker } from "@int/geotoolkit/welllog/LogMarker.ts";
import { CorrelationMarker } from "@int/geotoolkit/welllog/multiwell/correlation/CorrelationMarker.ts";
import { LineStyle } from "@int/geotoolkit/attributes/LineStyle.ts";
import { KnownColors } from "@int/geotoolkit/util/ColorUtil.ts";
import { AlignmentStyle, TextStyle } from "@int/geotoolkit/attributes/TextStyle.ts";
import { AnchorType } from "@int/geotoolkit/util/AnchorType.ts";
import { Range } from "@int/geotoolkit/util/Range.ts";
import { MathUtil } from "@int/geotoolkit/util/MathUtil.ts";
import curvesData from "/src/code/WellLog/MultiWell/data/data.json?import";
function createWidget() {
const widget = new MultiWellWidget({
"verticalscrollable": "floating",
"horizontalscrollable": "floating",
"tools": {
"cursortracking": {
"tooltip": {
"enabled": true
}
}
}
});
const well1 = widget.addTrack(MultiWellTrackType.WellTrack, {
"range": new Range(0, 500),
"welllog": {
"range": new Range(4500, 5e3)
},
"name": "Well #1",
"title": '${name}<br/><span style="color: gray">1 ${deviceUnit} : ${scaleValue} ${scaleUnit}</span>'
});
const correlationTrack1 = widget.addTrack(MultiWellTrackType.CorrelationTrack, {
"width": 50
});
const well2 = widget.addTrack(MultiWellTrackType.WellTrack, {
"range": new Range(50, 300),
"welllog": {
"range": new Range(2500, 5e3)
},
"name": "Well #2",
"title": '${name}<br/><span style="color: gray">1 ${deviceUnit} : ${scaleValue} ${scaleUnit}</span>'
});
const correlationTrack2 = widget.addTrack(MultiWellTrackType.CorrelationTrack, {
"width": 50
});
const well3 = widget.addTrack(MultiWellTrackType.WellTrack, {
"range": new Range(25, 400),
"welllog": {
"range": new Range(4700, 5e3)
},
"name": "Well #3",
"title": '${name}<br/><span style="color: gray">1 ${deviceUnit} : ${scaleValue} ${scaleUnit}</span>'
});
addWellData(well1, 4500, ["CALI", "GR", "DLT", "SP"]);
addWellData(well2, 2500, ["CALI"]);
addWellData(well3, 4700);
function addWellData(well, startDepth, curves) {
curves = curves || ["GR", "CALI"];
const colors = [KnownColors.Green, KnownColors.Orange, KnownColors.Red, KnownColors.Blue];
well.addTrack(WellLogTrackType.IndexTrack);
well.addTrack(WellLogTrackType.LinearTrack).addChild(
curves.map((curve, index) => createCurve(createTestData(startDepth, 10, curve), colors[index]))
);
}
addTops(well1, "Tarbert", 4750, KnownColors.DarkRed);
addTops(well2, "Tarbert", 3e3, KnownColors.DarkRed);
addTops(well3, "Tarbert", 4800, KnownColors.DarkRed);
function addTops(well, name, depth, color) {
const top = new LogMarker(depth);
top.setLineStyle(LineStyle.fromObject({ "color": color }));
top.setTextStyle(TextStyle.fromObject({
"color": color,
"alignment": AlignmentStyle.Left,
"font": "12px sans-serif"
}));
top.setNameLabel(name);
top.setNameLabelPosition(AnchorType.TopCenter);
top.setDepthLabel(depth.toFixed());
top.setDepthLabelPosition(AnchorType.BottomCenter);
well.getMarkerLayer().addChild(top);
}
addTopsCorrelation(correlationTrack1, 4750, 3e3, KnownColors.DarkRed);
addTopsCorrelation(correlationTrack2, 3e3, 4800, KnownColors.DarkRed);
function addTopsCorrelation(track, leftDepth, rightDepth, color) {
track.addChild(new CorrelationMarker({
"linestyle": {
"color": color,
"width": 2,
"pixelsnapmode": true
},
"leftdepth": leftDepth,
"rightdepth": rightDepth
}));
}
return widget;
}
function createCurve(dataSource, color) {
const limits = MathUtil.calculateNeatLimits(dataSource.getMinValue(), dataSource.getMaxValue(), false, false);
return new LogCurve(dataSource).setLineStyle(color).setNormalizationLimits(limits.getLow(), limits.getHigh());
}
function createScene(canvas) {
const widget = createWidget();
const plot = new Plot({
"canvaselement": canvas,
"root": widget
});
widget.setHeaderHeight("auto");
widget.setCss(`
.geotoolkit.welllog.header.LogTrackHeader {
firsttolast: true;
toptobottom: false;
}
.geotoolkit.welllog.multiwell.WellTrackHeader {
layout-direction: bottomtotop;
holdtitle: top;
}
`);
return plot;
}
function getCurveData(curveMnemonic) {
const curveNames = curvesData.curveNames;
const curveData = curvesData.curveData;
for (let i = 0; i < curveNames.length; i++) {
if (curveNames[i] === curveMnemonic)
return curveData[i];
}
return null;
}
function createTestData(from, step, curveMnemonic) {
const depths = [];
const values = [];
const curveData = getCurveData(curveMnemonic);
const amountOfPoints = curveData.length;
for (let i = 0; i < amountOfPoints; i++) {
depths.push(i * step + from);
values.push(curveData[i]);
}
return new LogData({
"name": curveMnemonic,
"depths": depths,
"values": values
});
}
export { createScene };
createScene(document.querySelector('[ref="plot"]'));
# Customise Widget with CSS
After creating MultiWellWidget you can customize look and fill with CSS same as WellLog Widget.
# Connected Headers Result
This example displays how to specify header alignment.
import { Plot } from "@int/geotoolkit/plot/Plot.ts";
import { MultiWellWidget } from "@int/geotoolkit/welllog/multiwell/MultiWellWidget.ts";
import { TrackType as MultiWellTrackType } from "@int/geotoolkit/welllog/multiwell/TrackType.ts";
import { TrackType as WellLogTrackType } from "@int/geotoolkit/welllog/TrackType.ts";
import { LogData } from "@int/geotoolkit/welllog/data/LogData.ts";
import { LogCurve } from "@int/geotoolkit/welllog/LogCurve.ts";
import { LogMarker } from "@int/geotoolkit/welllog/LogMarker.ts";
import { CorrelationMarker } from "@int/geotoolkit/welllog/multiwell/correlation/CorrelationMarker.ts";
import { LineStyle } from "@int/geotoolkit/attributes/LineStyle.ts";
import { KnownColors } from "@int/geotoolkit/util/ColorUtil.ts";
import { AlignmentStyle, TextStyle } from "@int/geotoolkit/attributes/TextStyle.ts";
import { AnchorType } from "@int/geotoolkit/util/AnchorType.ts";
import { Range } from "@int/geotoolkit/util/Range.ts";
import { MathUtil } from "@int/geotoolkit/util/MathUtil.ts";
import curvesData from "/src/code/WellLog/MultiWell/data/data.json?import";
function createWidget() {
const widget = new MultiWellWidget({
"verticalscrollable": "floating",
"horizontalscrollable": "floating",
"tools": {
"cursortracking": {
"tooltip": {
"enabled": true
}
}
}
});
const well1 = widget.addTrack(MultiWellTrackType.WellTrack, {
"range": new Range(0, 500),
"welllog": {
"range": new Range(4500, 5e3)
},
"name": "Well #1",
"title": '${name}<br/><span style="color: gray">1 ${deviceUnit} : ${scaleValue} ${scaleUnit}</span>'
});
const correlationTrack1 = widget.addTrack(MultiWellTrackType.CorrelationTrack, {
"width": 50
});
const well2 = widget.addTrack(MultiWellTrackType.WellTrack, {
"range": new Range(50, 300),
"welllog": {
"range": new Range(2500, 5e3)
},
"name": "Well #2",
"title": '${name}<br/><span style="color: gray">1 ${deviceUnit} : ${scaleValue} ${scaleUnit}</span>'
});
const correlationTrack2 = widget.addTrack(MultiWellTrackType.CorrelationTrack, {
"width": 50
});
const well3 = widget.addTrack(MultiWellTrackType.WellTrack, {
"range": new Range(25, 400),
"welllog": {
"range": new Range(4700, 5e3)
},
"name": "Well #3",
"title": '${name}<br/><span style="color: gray">1 ${deviceUnit} : ${scaleValue} ${scaleUnit}</span>'
});
addWellData(well1, 4500, ["CALI", "GR", "DLT", "SP"]);
addWellData(well2, 2500, ["CALI"]);
addWellData(well3, 4700);
function addWellData(well, startDepth, curves) {
curves = curves || ["GR", "CALI"];
const colors = [KnownColors.Green, KnownColors.Orange, KnownColors.Red, KnownColors.Blue];
well.addTrack(WellLogTrackType.IndexTrack);
well.addTrack(WellLogTrackType.LinearTrack).addChild(
curves.map((curve, index) => createCurve(createTestData(startDepth, 10, curve), colors[index]))
);
}
addTops(well1, "Tarbert", 4750, KnownColors.DarkRed);
addTops(well2, "Tarbert", 3e3, KnownColors.DarkRed);
addTops(well3, "Tarbert", 4800, KnownColors.DarkRed);
function addTops(well, name, depth, color) {
const top = new LogMarker(depth);
top.setLineStyle(LineStyle.fromObject({ "color": color }));
top.setTextStyle(TextStyle.fromObject({
"color": color,
"alignment": AlignmentStyle.Left,
"font": "12px sans-serif"
}));
top.setNameLabel(name);
top.setNameLabelPosition(AnchorType.TopCenter);
top.setDepthLabel(depth.toFixed());
top.setDepthLabelPosition(AnchorType.BottomCenter);
well.getMarkerLayer().addChild(top);
}
addTopsCorrelation(correlationTrack1, 4750, 3e3, KnownColors.DarkRed);
addTopsCorrelation(correlationTrack2, 3e3, 4800, KnownColors.DarkRed);
function addTopsCorrelation(track, leftDepth, rightDepth, color) {
track.addChild(new CorrelationMarker({
"linestyle": {
"color": color,
"width": 2,
"pixelsnapmode": true
},
"leftdepth": leftDepth,
"rightdepth": rightDepth
}));
}
return widget;
}
function createCurve(dataSource, color) {
const limits = MathUtil.calculateNeatLimits(dataSource.getMinValue(), dataSource.getMaxValue(), false, false);
return new LogCurve(dataSource).setLineStyle(color).setNormalizationLimits(limits.getLow(), limits.getHigh());
}
function createScene(canvas) {
const widget = createWidget();
const plot = new Plot({
"canvaselement": canvas,
"root": widget
});
widget.setHeaderHeight("auto").setProperties({
"header": {
"connected": true
}
});
widget.setCss(`
geotoolkit.welllog.multiwell.WellTrack {
fillstyle: rgba(100, 100, 100, 0.05);
border-linestyle: 2px solid blue;
border-z-index: 1;
border-borderstyle: VisibleBounds;
border-left: true;
border-top: false;
border-right: true;
border-bottom: true;
}
.geotoolkit.welllog.multiwell.WellTrackHeader {
fillstyle: rgba(100, 100, 100, 0.05);
border-linestyle: 2px solid blue;
border-left: true;
border-top: true;
border-right: true;
border-bottom: false;
}
geotoolkit.welllog.multiwell.WellTrack:hover {
border-linestyle-width: 2px;
border-linestyle-shadow-enable: true;
border-linestyle-shadow-blur: 2;
border-linestyle-shadow-offsetx: 0;
border-linestyle-shadow-offsety: 0;
}
.geotoolkit.welllog.multiwell.WellTrackHeader:hover {
border-linestyle-width: 2px;
border-linestyle-shadow-enable: true;
border-linestyle-shadow-blur: 2;
border-linestyle-shadow-offsetx: 0;
border-linestyle-shadow-offsety: 0;
}
.geotoolkit.welllog.multiwell.WellTrack:highlight {
border-linestyle-width: 2px;
border-linestyle-shadow-enable: true;
border-linestyle-shadow-blur: 2;
border-linestyle-shadow-offsetx: 0;
border-linestyle-shadow-offsety: 0;
}
.geotoolkit.welllog.multiwell.WellTrackHeader:highlight {
border-linestyle-width: 2px;
border-linestyle-shadow-enable: true;
border-linestyle-shadow-blur: 2;
border-linestyle-shadow-offsetx: 0;
border-linestyle-shadow-offsety: 0;
}
.geotoolkit.welllog.LogCurve:hover {
linestyle-shadow-enable: true;
linestyle-shadow-blur: 2;
linestyle-shadow-offsetx: 0;
linestyle-shadow-offsety: 0;
}
`);
return plot;
}
function getCurveData(curveMnemonic) {
const curveNames = curvesData.curveNames;
const curveData = curvesData.curveData;
for (let i = 0; i < curveNames.length; i++) {
if (curveNames[i] === curveMnemonic)
return curveData[i];
}
return null;
}
function createTestData(from, step, curveMnemonic) {
const depths = [];
const values = [];
const curveData = getCurveData(curveMnemonic);
const amountOfPoints = curveData.length;
for (let i = 0; i < amountOfPoints; i++) {
depths.push(i * step + from);
values.push(curveData[i]);
}
return new LogData({
"name": curveMnemonic,
"depths": depths,
"values": values
});
}
export { createScene };
createScene(document.querySelector('[ref="plot"]'));