The StackedLogFill is another log visual (graphical representations of log data) added to the LogTracks. A fill needs a set of geotoolkit/welllog/data/LogData objects passed into the constructor and a fill style assigned before the fill will display. Fills can be solid colors, gradients, or fillstyles (patterns and images).
# Simple StackedLogFill with regular depths and all positive values
In a simple fill case, continuous solid colors, gradient, patterns or images can be used to fill only the space between the reference line and curves. The first track displays a simple fill, in which the fill style is assigned to the space between the log curve and base line.
The second track displays a StackedLogFill in which values for the log curve are aggregated over depth and fill style is assigned between the log curve and baseline for the first curve and between two log curves for the other log curves.
import { Plot } from "@int/geotoolkit/plot/Plot.ts";
import { TrackType } from "@int/geotoolkit/welllog/TrackType.ts";
import { LogReferenceLine } from "@int/geotoolkit/welllog/LogReferenceLine.ts";
import { createCurve, createSelectionTool, createStackedFill, generateData } from "/src/code/WellLog/Visuals/StackedFill/util.ts";
import { SizeConstraint } from "@int/geotoolkit/layout/SizeConstraint.ts";
import { createWellLogWidget } from "/src/code/WellLog/utils/common.ts";
function createScene(canvas) {
const data = generateData(false);
const widget = createWellLogWidget({
"track": {
"header": {
"visibletracktitle": true
}
}
}).setDepthLimits(90, 510);
createSelectionTool(widget);
const microPositionStep = 1 / data.length;
widget.addTrack(TrackType.IndexTrack).setName("");
widget.addTrack(TrackType.LinearTrack).setName("Original curves with microposition").addChild(data.map((src, i) => {
const curve = createCurve(i, src, new LogReferenceLine(microPositionStep * i), new LogReferenceLine(microPositionStep * i)).setNormalizationLimits(0, 100).setMicroPosition(microPositionStep * i, microPositionStep * (i + 1));
return curve;
})).getHeader().setCss([
".geotoolkit.welllog.header.AdaptiveLogCurveVisualHeader {",
" orientation: vertical;",
" layoutstyle-constraint: " + SizeConstraint.NoConstraint + ";",
" layoutstyle-height: 150;",
"}"
].join(""));
const stackedFill = createStackedFill(data).setName("Simple Stacked Fill");
widget.addTrack(TrackType.LinearTrack).setName("Stacked Fill").addChild(stackedFill);
const plot = new Plot({
"canvaselement": canvas,
"root": widget
});
widget.setHeaderHeight("auto");
widget.fitToHeight();
return plot;
}
export { createScene };
createScene(document.querySelector('[ref="plot"]'));
# StackedLogFill support irregular data with Null/NaN and negative values
This section demonstrates how null or NaN values are handled in simple fill and StackedLogFill.
In simple fill cases, fill is applied between log curves and the reference line. In the stackedLogFill, for discontinuity part, fill is applied between previously available log curve value or reference line if the value is not present for any previous logcurves.
The first track displays a simple fill, in which the fill style is assigned to the space between the log curve and base line.
Second track demonstrates fills with reference curves. And the rest of the tracks display StackedLogFill with different Gap stacking mode.
import { Plot } from "@int/geotoolkit/plot/Plot.ts";
import { LogReferenceLine } from "@int/geotoolkit/welllog/LogReferenceLine.ts";
import { TrackType } from "@int/geotoolkit/welllog/TrackType.ts";
import { createCurve, createSelectionTool, createStackedFill, generateData } from "/src/code/WellLog/Visuals/StackedFill/util.ts";
import { GapStackingMode } from "@int/geotoolkit/welllog/StackedLogFill.ts";
import { SizeConstraint } from "@int/geotoolkit/layout/SizeConstraint.ts";
import { createWellLogWidget } from "/src/code/WellLog/utils/common.ts";
function createScene(canvas) {
const data = generateData(true);
const widget = createWellLogWidget({
"track": {
"header": {
"visibletracktitle": true
}
}
}).setDepthLimits(90, 510);
createSelectionTool(widget);
const microPositionStep = 1 / data.length;
widget.addTrack(TrackType.IndexTrack).setName("");
widget.addTrack(TrackType.LinearTrack).setName("Original curves with microposition").addChild(data.map((src, i) => {
let zero2 = microPositionStep * i;
if (src.getMinValue() < 0) {
zero2 += microPositionStep * Math.abs(src.getMinValue()) / (100 - src.getMinValue());
}
const curve = createCurve(i, src, new LogReferenceLine(zero2), new LogReferenceLine(zero2)).setNormalizationLimits(0, 100).setMicroPosition(microPositionStep * i, microPositionStep * (i + 1));
if (src.getMinValue() < 0) {
curve.setNormalizationLimits(src.getMinValue(), 100);
}
return curve;
})).getHeader().setCss([
".geotoolkit.welllog.header.AdaptiveLogCurveVisualHeader {",
" orientation: vertical;",
" layoutstyle-constraint: " + SizeConstraint.NoConstraint + ";",
" layoutstyle-height: 175;",
"}"
].join(""));
const stackedFill1 = createStackedFill(data).setName("Keep Samples mode");
widget.addTrack(TrackType.LinearTrack).setName("Stacked Fill").addChild(stackedFill1);
const stackedFill2 = createStackedFill(data).setGapStackingMode(GapStackingMode.RemoveSamples).setName("Remove Samples mode");
widget.addTrack(TrackType.LinearTrack).setName("Stacked Fill").addChild(stackedFill2);
widget.getHeaderContainer().getHeaderProvider().getHeader(stackedFill2).setVertical(true, 130);
const min = stackedFill1.getMinimumNormalizationLimit();
const max = stackedFill1.getMaximumNormalizationLimit();
const zero = -min / (max - min);
let prevCurve = null;
let leftRef = new LogReferenceLine(zero);
let rightRef = new LogReferenceLine(zero);
const curves = data.map((src, i) => {
const curve = createCurve(i, src, leftRef, rightRef, true).setReferenceCurve(prevCurve).setNormalizationLimits(min, max).setDisplayMode(["line", "symbol", "value"]);
prevCurve = curve;
leftRef = curve;
rightRef = null;
return curve;
});
widget.insertTrack(2, TrackType.LinearTrack).setName("Stacked with using reference").addChild(curves);
const plot = new Plot({
"canvaselement": canvas,
"root": widget
});
widget.setHeaderHeight("auto");
widget.fitToHeight();
return plot;
}
export { createScene };
createScene(document.querySelector('[ref="plot"]'));
# StackedLogFill support irregular data with Gaps
This section demonstrates how Gap value is handled in simple fill and StackedLogFill.
This is almost the same situation like previous, but instead of NaN values we process Gap between indexes.
The first track displays a simple fill, in which the fill style is assigned to the space between the log curve and base line.
Second track demonstrates fills with reference curves. And the rest of the tracks display StackedLogFill with different Gap stacking mode.
import { Plot } from "@int/geotoolkit/plot/Plot.ts";
import { LogReferenceLine } from "@int/geotoolkit/welllog/LogReferenceLine.ts";
import { TrackType } from "@int/geotoolkit/welllog/TrackType.ts";
import { createCurve, createSelectionTool, createStackedFill, generateData } from "/src/code/WellLog/Visuals/StackedFill/util.ts";
import { GapStackingMode } from "@int/geotoolkit/welllog/StackedLogFill.ts";
import { SizeConstraint } from "@int/geotoolkit/layout/SizeConstraint.ts";
import { createWellLogWidget } from "/src/code/WellLog/utils/common.ts";
function createScene(canvas) {
const data = generateData(false, true);
const widget = createWellLogWidget({
"track": {
"header": {
"visibletracktitle": true
}
}
}).setDepthLimits(90, 510);
createSelectionTool(widget);
const microPositionStep = 1 / data.length;
widget.addTrack(TrackType.IndexTrack).setName("");
widget.addTrack(TrackType.LinearTrack).setName("Original curves with microposition").addChild(data.map((src, i) => {
let zero2 = microPositionStep * i;
if (src.getMinValue() < 0) {
zero2 += microPositionStep * Math.abs(src.getMinValue()) / (100 - src.getMinValue());
}
const curve = createCurve(i, src, new LogReferenceLine(zero2), new LogReferenceLine(zero2)).setGapValue(50).setNormalizationLimits(0, 100).setMicroPosition(microPositionStep * i, microPositionStep * (i + 1));
if (src.getMinValue() < 0) {
curve.setNormalizationLimits(src.getMinValue(), 100);
}
return curve;
})).getHeader().setCss([
".geotoolkit.welllog.header.AdaptiveLogCurveVisualHeader {",
" orientation: vertical;",
" layoutstyle-constraint: " + SizeConstraint.NoConstraint + ";",
" layoutstyle-height: 175;",
"}"
].join(""));
const stackedFill1 = createStackedFill(data).setGapValue(50).setName("Keep Samples mode");
widget.addTrack(TrackType.LinearTrack).setName("Stacked Fill").addChild(stackedFill1);
const stackedFill2 = createStackedFill(data).setGapValue(50).setGapStackingMode(GapStackingMode.RemoveSamples).setName("Remove Samples mode");
widget.addTrack(TrackType.LinearTrack).setName("Stacked Fill").addChild(stackedFill2);
widget.getHeaderContainer().getHeaderProvider().getHeader(stackedFill2).setVertical(true, 130);
const min = stackedFill1.getMinimumNormalizationLimit();
const max = stackedFill1.getMaximumNormalizationLimit();
const zero = -min / (max - min);
let prevCurve = null;
let leftRef = new LogReferenceLine(zero);
let rightRef = new LogReferenceLine(zero);
const curves = data.map((src, i) => {
const curve = createCurve(i, src, leftRef, rightRef, true).setGapValue(50).setReferenceCurve(prevCurve).setNormalizationLimits(min, max).setDisplayMode(["line", "symbol", "value"]);
prevCurve = curve;
leftRef = curve;
rightRef = null;
return curve;
});
widget.insertTrack(2, TrackType.LinearTrack).setName("Stacked with using reference").addChild(curves);
const plot = new Plot({
"canvaselement": canvas,
"root": widget
});
widget.setHeaderHeight("auto");
widget.fitToHeight();
return plot;
}
export { createScene };
createScene(document.querySelector('[ref="plot"]'));
# Stacked Curves
This section demonstrates how to stack LogCurves one to another.
The first track displays non stacked curves without fills. The second track contains curves with the same datasources, but stacked one to another.
import { Plot } from "@int/geotoolkit/plot/Plot.ts";
import { LogReferenceLine } from "@int/geotoolkit/welllog/LogReferenceLine.ts";
import { LogData } from "@int/geotoolkit/welllog/data/LogData.ts";
import { CompositeLogCurve } from "@int/geotoolkit/welllog/CompositeLogCurve.ts";
import { TrackType } from "@int/geotoolkit/welllog/TrackType.ts";
import { LogCurve } from "@int/geotoolkit/welllog/LogCurve.ts";
import { getCurveData } from "/src/code/WellLog/utils/stackedCurveData.ts";
import { SizeConstraint } from "@int/geotoolkit/layout/SizeConstraint.ts";
import { createWellLogWidget } from "/src/code/WellLog/utils/common.ts";
const stackedFillColors = [
"rgba(254, 246, 187, 0.5)",
"rgba(242, 220, 215, 0.5)",
"rgba(149, 202, 158, 0.5)",
"rgba(166, 210, 229, 0.5)",
"rgba(61, 55, 229, 0.5)"
];
const lineColors = ["#212121", "#2196f3", "#fdd835", "#e64a19", "#3d37e5"];
function createScene(canvas) {
const curveNames = ["POTA", "SLT", "SLX", "THOR", "URAN"];
const curveValues = curveNames.map((mnemonic) => getCurveData(mnemonic));
const maxIndex = Math.min.apply(null, curveValues.map((values) => values.length));
const depths = [];
const from = 4500, step = 5;
for (let i = 0; i < maxIndex; i++) {
depths.push(i * step + from);
}
const curves = [];
for (let i = 0; i < curveNames.length; i++) {
const dataSource = new LogData({
"name": curveNames[i],
"depths": depths,
"values": curveValues[i]
});
const compositeLogCurve = new CompositeLogCurve(dataSource).setNormalizationLimits(0, 1).setLineStyle(lineColors[i]);
curves.push(compositeLogCurve);
const leftReference = i > 0 ? curves[i - 1] : new LogReferenceLine(0);
compositeLogCurve.setLeftReferencePointSet(leftReference);
if (stackedFillColors[i] != null) {
compositeLogCurve.getLeftFill().setFillStyle(stackedFillColors[i]);
}
if (i > 0) {
compositeLogCurve.setReferenceCurve(leftReference);
}
}
const widget = createWellLogWidget({
"track": {
"header": {
"visibletracktitle": true
}
}
}).setDepthLimits(depths[0], depths[depths.length - 1]);
widget.addTrack(TrackType.IndexTrack).setName("");
widget.addTrack(TrackType.LinearTrack).setName("Regular curves").addChild(curves.map(
(curve) => new LogCurve(curve.getDataSource()).setLineStyle(curve.getLineStyle())
));
const microPositionStep = 1 / curves.length;
widget.addTrack(TrackType.IndexTrack).setName("");
widget.addTrack(TrackType.LinearTrack).setName("Original curves with microposition").addChild(curves.map(
(curve, i) => new LogCurve(curve.getDataSource()).setMicroPosition(microPositionStep * i, microPositionStep * (i + 1)).setLineStyle(curve.getLineStyle())
)).getHeader().setCss([
".geotoolkit.welllog.header.AdaptiveLogCurveVisualHeader {",
" orientation: vertical;",
" layoutstyle-constraint: " + SizeConstraint.NoConstraint + ";",
" layoutstyle-height: 220;",
"}"
].join(""));
widget.addTrack(TrackType.LinearTrack).setName("Stacked with using reference").addChild(curves);
widget.addTrack(TrackType.IndexTrack).setName("");
const plot = new Plot({
"canvaselement": canvas,
"root": widget
});
widget.setHeaderHeight("auto");
widget.fitToHeight();
return plot;
}
export { createScene };
createScene(document.querySelector('[ref="plot"]'));