In the WellLogJS introduction. Log Curves are log visuals, graphical representations of log data, added to the Log Tracks. In this WellLog – Log Curve tutorial, create a geotoolkit/welllog/LogCurve, set its attributes and add it to the Track.
Log Curves must be constructed with a datasource, which includes an easily modified default geotoolkit/attributes/LineStyle and InterpolationType. Several display options/modes can be modified and symbols or curve point values can be added to the Log Curve.
# Create Curve
The following example shows how to create a log curve.
import { Plot } from "@int/geotoolkit/plot/Plot.ts";
import { TrackType } from "@int/geotoolkit/welllog/TrackType.ts";
import { createCurve } from "/src/code/WellLog/Basics/LogCurve/data.ts";
import { createWellLogWidget } from "/src/code/WellLog/utils/common.ts";
function createScene(canvas) {
const widget = createWellLogWidget();
widget.addTrack(TrackType.IndexTrack);
const linearTrack = widget.addTrack(TrackType.LinearTrack);
const logCurve = createCurve("#ef6c00");
linearTrack.addChild(logCurve);
widget.addTrack(TrackType.IndexTrack);
widget.setDepthLimits(0, 75);
const plot = new Plot({
"canvaselement": canvas,
"root": widget
});
widget.fitToHeight();
return plot;
}
export { createScene };
createScene(document.querySelector('[ref="plot"]'));
# Interpolation Types
The following example shows how to choose a Log Curve interpolation type. Four interpolation types can be selected for the Log Curve: linear (orange), startstep (blue), middlestep (green) and endstep (yellow).
import { Plot } from "@int/geotoolkit/plot/Plot.ts";
import { InterpolationType } from "@int/geotoolkit/data/DataStepInterpolation.ts";
import { TrackType } from "@int/geotoolkit/welllog/TrackType.ts";
import { createCurve } from "/src/code/WellLog/Basics/LogCurve/data.ts";
import { createWellLogWidget } from "/src/code/WellLog/utils/common.ts";
function createScene(canvas) {
const widget = createWellLogWidget().setDepthLimits(10, 75);
widget.addTrack(TrackType.IndexTrack);
widget.addTrack(TrackType.LinearTrack).addChild(createCurve("#ef6c00"));
widget.addTrack(TrackType.IndexTrack);
widget.addTrack(TrackType.LinearTrack).addChild([
createCurve("#2196f3").setInterpolationType(InterpolationType.StartStep),
createCurve("#bbdefb")
]);
widget.addTrack(TrackType.IndexTrack);
widget.addTrack(TrackType.LinearTrack).addChild([
createCurve("#7cb342").setInterpolationType(InterpolationType.MiddleStep),
createCurve("#dcedc8")
]);
widget.addTrack(TrackType.IndexTrack);
widget.addTrack(TrackType.LinearTrack).addChild([
createCurve("#fdd835").setInterpolationType(InterpolationType.EndStep),
createCurve("#fff9c4")
]);
widget.addTrack(TrackType.IndexTrack);
const plot = new Plot({
"canvaselement": canvas,
"root": widget
});
widget.fitToHeight().fitToWidth();
return plot;
}
export { createScene };
createScene(document.querySelector('[ref="plot"]'));
# Display Types
The following example shows how to choose a Log Curve display type. Four display types can be selected for the Log Curve: default curve, symbols, bar and values.
import { Plot } from "@int/geotoolkit/plot/Plot.ts";
import { AnchorType } from "@int/geotoolkit/util/AnchorType.ts";
import { DiamondPainter } from "@int/geotoolkit/scene/shapes/painters/DiamondPainter.ts";
import { CirclePainter } from "@int/geotoolkit/scene/shapes/painters/CirclePainter.ts";
import { TrackType } from "@int/geotoolkit/welllog/TrackType.ts";
import { createCurve, createSymbol } from "/src/code/WellLog/Basics/LogCurve/data.ts";
import { createWellLogWidget } from "/src/code/WellLog/utils/common.ts";
function createScene(canvas) {
const widget = createWellLogWidget();
widget.addTrack(TrackType.IndexTrack);
widget.addTrack(TrackType.LinearTrack).addChild(createCurve("#ef6c00"));
widget.addTrack(TrackType.IndexTrack);
widget.addTrack(TrackType.LinearTrack).addChild(
createCurve("#ef6c00").setSymbol(createSymbol("#2196f3", CirclePainter)).setDisplayMode(["line", "symbol"]).setSymbolDecimationStep(1)
);
widget.addTrack(TrackType.IndexTrack);
widget.addTrack(TrackType.LinearTrack).addChild(
createCurve("#ef6c00").setSymbol(createSymbol("#7cb342", DiamondPainter)).setDisplayMode(["bar", "symbol"]).setSymbolDecimationStep(1)
);
widget.addTrack(TrackType.IndexTrack);
widget.addTrack(TrackType.LinearTrack).addChild(
createCurve("#ef6c00").setVisibleValue(true).setTextAnchorType(AnchorType.RightCenter).setTextDecimationStep(1)
);
widget.addTrack(TrackType.IndexTrack);
const plot = new Plot({
"canvaselement": canvas,
"root": widget
});
widget.setDepthLimits(10, 75).fitToHeight().fitToWidth();
return plot;
}
export { createScene };
createScene(document.querySelector('[ref="plot"]'));
# Curve Limits
By default, the Log Curve will use all available space. The following code shows how to normalize the curve or set the clipping limits. Wrapping can be enabled to see the clipped part of the curve.
The following example shows how to choose a Log Curve limit. There are four curve limit types: default (uses all available space), normalize (to fit within limits), edit visible limits (data out of range is not displayed), and wrapping (display missing data).
import { Plot } from "@int/geotoolkit/plot/Plot.ts";
import { TrackType } from "@int/geotoolkit/welllog/TrackType.ts";
import { LimitsType, LogCurve } from "@int/geotoolkit/welllog/LogCurve.ts";
import { AdaptiveLogCurveVisualHeader, Elements } from "@int/geotoolkit/welllog/header/AdaptiveLogCurveVisualHeader.ts";
import { BorderStrategy } from "@int/geotoolkit/welllog/BorderStrategy.ts";
import { InterpolationEdge } from "@int/geotoolkit/data/DataLimitsInterpolation.ts";
import { LineStyle } from "@int/geotoolkit/attributes/LineStyle.ts";
import { Sections } from "@int/geotoolkit/welllog/header/AdaptiveLogVisualHeader.ts";
import { createCurve } from "/src/code/WellLog/Basics/LogCurve/data.ts";
import { createWellLogWidget } from "/src/code/WellLog/utils/common.ts";
function initializeHeaderProvider(widget) {
const curveHeader = new AdaptiveLogCurveVisualHeader().setElement({
[Elements.ScaleFrom]: {
"section": Sections.Middle
},
[Elements.ScaleTo]: {
"section": Sections.Middle
},
[Elements.Description]: {
"updatemethod": function(header) {
const visual = header.getVisual();
if (visual.isWrapping()) {
return "Wrapp limits";
} else if (visual.isClippingEnabled()) {
return "Clipp limits";
} else if (visual.getLimitsType() !== LimitsType.Auto) {
if (visual.getInterpolationEdge() === InterpolationEdge.Cut) {
return "Cut limits";
}
return "Interpolate limits";
}
return "Auto limits";
}
}
});
widget.getHeaderContainer().getHeaderProvider().registerHeaderProvider(LogCurve.getClassName(), curveHeader);
}
function createScene(canvas) {
const widget = createWellLogWidget({
"trackcontainer": {
"track": {
"borderstrategy": BorderStrategy.BorderAtBottom
}
}
});
initializeHeaderProvider(widget);
widget.addTrack(TrackType.IndexTrack);
widget.addTrack(TrackType.LinearTrack).addChild(createCurve("gray"));
widget.addTrack(TrackType.IndexTrack);
widget.addTrack(TrackType.LinearTrack).enableClipping(false).addChild(
createCurve("#ef6c00").setNormalizationLimits(60, 90, InterpolationEdge.Cut)
);
widget.addTrack(TrackType.IndexTrack);
widget.addTrack(TrackType.LinearTrack).enableClipping(false).addChild(
createCurve("#2196f3").setNormalizationLimits(60, 90)
);
widget.addTrack(TrackType.IndexTrack);
widget.addTrack(TrackType.LinearTrack).addChild(
createCurve("#7cb342").setClippingLimits(60, 90)
);
widget.addTrack(TrackType.IndexTrack);
const BLUE_STYLE = new LineStyle("blue");
const RED_STYLE = new LineStyle("red");
widget.addTrack(TrackType.LinearTrack).addChild(
createCurve("#fdd835").setClippingLimits(60, 90).setWrapping(true).setMaxWraps(1).setWrapLineStyleHandler((sender, wrapLevel) => {
if (wrapLevel < 0) {
return BLUE_STYLE;
}
if (wrapLevel > 0) {
return RED_STYLE;
}
return null;
})
);
widget.addTrack(TrackType.IndexTrack);
const plot = new Plot({
"canvaselement": canvas,
"root": widget
});
widget.setDepthLimits(10, 75).fitToHeight().fitToWidth();
return plot;
}
export { createScene };
createScene(document.querySelector('[ref="plot"]'));
# NaN Values and Cut-Off Values
The following code shows how to create a log curve with NaN (Not a Number) values and cut-off values.
- The orange curve is displayed without NaN values. The other curves have NaN values in depths: 27, 30, 35 and the GapFillCutoffValue is specified as 20.
- The blue curve displays NaN values as gap.
- The green curve has an option to show the first and the last real values between gap as a symbol.
- The yellow curve enables an option to specify cutoff for NaN values by depths. If depth interval is less than specified cutoff value, which is 20 in this example, then interpolation is applied in such a way that the interval is connected and NaN values between are removed.
import { Plot } from "@int/geotoolkit/plot/Plot.ts";
import { TrackType } from "@int/geotoolkit/welllog/TrackType.ts";
import { CirclePainter } from "@int/geotoolkit/scene/shapes/painters/CirclePainter.ts";
import { createCurve, createSymbol } from "/src/code/WellLog/Basics/LogCurve/data.ts";
import { createWellLogWidget } from "/src/code/WellLog/utils/common.ts";
function createScene(canvas) {
const widget = createWellLogWidget();
widget.addTrack(TrackType.IndexTrack);
widget.addTrack(TrackType.LinearTrack).addChild(createCurve("#ef6c00"));
widget.addTrack(TrackType.IndexTrack);
widget.addTrack(TrackType.LinearTrack).addChild(createCurve("#2196f3", true));
widget.addTrack(TrackType.IndexTrack);
widget.addTrack(TrackType.LinearTrack).addChild(
createCurve("#7cb342", true).setNullValueSymbol(createSymbol("#7cb342", CirclePainter)).setVisibleNullValueSymbol(true)
);
widget.addTrack(TrackType.IndexTrack);
widget.addTrack(TrackType.LinearTrack).addChild(
createCurve("#fdd835", true).setGapFillCutoffValue(20).setGapFillCutoffUnit("ft")
);
widget.addTrack(TrackType.IndexTrack);
const plot = new Plot({
"canvaselement": canvas,
"root": widget
});
widget.setDepthLimits(10, 75).fitToHeight().fitToWidth();
return plot;
}
export { createScene };
createScene(document.querySelector('[ref="plot"]'));
# Interpolation Based on Gap Value
The following example shows how to support a gap between values in a log curve. If the gap between two samples in depth or time is more than the specified gap value, interpolation is not applied to the curve and the disconnect between the samples is displayed as a gap or disconnect in the curve.
import { Plot } from "@int/geotoolkit/plot/Plot.ts";
import { TrackType } from "@int/geotoolkit/welllog/TrackType.ts";
import { createCurve } from "/src/code/WellLog/Basics/LogCurve/data.ts";
import { createWellLogWidget } from "/src/code/WellLog/utils/common.ts";
function createScene(canvas) {
const widget = createWellLogWidget();
widget.addTrack(TrackType.IndexTrack);
widget.addTrack(TrackType.LinearTrack).addChild(
createCurve("#fdd835").setGapValue(7).setGapUnit("ft")
);
widget.addTrack(TrackType.IndexTrack);
const plot = new Plot({
"canvaselement": canvas,
"root": widget
});
widget.setDepthLimits(10, 75).fitToHeight();
return plot;
}
export { createScene };
createScene(document.querySelector('[ref="plot"]'));
# Curve Limits Strategy
The following example shows how to create a log curve with custom curve limits strategy.
import { obfuscate } from "@int/geotoolkit/lib.js";
import { Plot } from "@int/geotoolkit/plot/Plot.ts";
import { TrackType } from "@int/geotoolkit/welllog/TrackType.ts";
import { LogCurveLimitsStrategy } from "@int/geotoolkit/welllog/LogCurveLimitsStrategy.ts";
import { LimitsType, LogCurve } from "@int/geotoolkit/welllog/LogCurve.ts";
import { AdaptiveLogCurveVisualHeader, Elements } from "@int/geotoolkit/welllog/header/AdaptiveLogCurveVisualHeader.ts";
import { Sections } from "@int/geotoolkit/welllog/header/AdaptiveLogVisualHeader.ts";
import { createCurve } from "/src/code/WellLog/Basics/LogCurve/data.ts";
import { createWellLogWidget } from "/src/code/WellLog/utils/common.ts";
function initializeHeaderProvider(widget) {
const curveHeader = new AdaptiveLogCurveVisualHeader().setElement({
[Elements.ScaleFrom]: {
"section": Sections.Middle
},
[Elements.ScaleTo]: {
"section": Sections.Middle
},
[Elements.Description]: {
"section": Sections.Bottom,
"updatemethod": function(header) {
const visual = header.getVisual();
if (visual.getLimitsType() === LimitsType.Auto && visual.getAutoLimitsStrategy()) {
return "Custom limits";
}
return "Auto limits";
}
}
});
widget.getHeaderContainer().getHeaderProvider().registerHeaderProvider(LogCurve.getClassName(), curveHeader);
}
class CustomCurveLimitsStrategy extends LogCurveLimitsStrategy {
constructor(extendInPercent) {
super();
this.extendInPercent = extendInPercent;
}
getLimits(data, unit) {
if (!data)
return [0, 0];
let min = data.getMinValue();
let max = data.getMaxValue();
const extend = this.extendInPercent * (max - min) / 100;
min -= extend;
max += extend;
if (unit != null) {
min = isFinite(min) ? data.getValueUnit().convert(min, unit) : min;
max = isFinite(max) ? data.getValueUnit().convert(max, unit) : max;
}
return [min, max];
}
}
obfuscate(CustomCurveLimitsStrategy);
function createScene(canvas) {
const widget = createWellLogWidget();
initializeHeaderProvider(widget);
widget.addTrack(TrackType.IndexTrack);
widget.addTrack(TrackType.LinearTrack).addChild(
createCurve("#ef6c00")
);
widget.addTrack(TrackType.LinearTrack).addChild(
createCurve("#2196f3").setAutoLimitsStrategy(new CustomCurveLimitsStrategy(10))
);
widget.addTrack(TrackType.IndexTrack);
const plot = new Plot({
"canvaselement": canvas,
"root": widget
});
widget.setDepthLimits(0, 75).fitToHeight();
return plot;
}
export { createScene };
createScene(document.querySelector('[ref="plot"]'));