This tutorial demonstrates how to embed a seismic image into the WellLog widget. The seismic pipeline uses trace processors to process each trace. The processed seismic data is then used to render the LogSeismicVisual which is added to the track as a child. Normally traces are located vertically in LogSeismicVisual, but you can change orientation to horizontal using visual.setPlotType(PlotType.Wave). In additional position of each trace can be controlled with variable trace spacing mapping VSTraceMapping
# Seismic Log Visual
The example below demonstrates how to create a widget, insert it into a plot, and add the seismic image to the track.
import { Plot } from "@int/geotoolkit/plot/Plot.ts";
import { SeismicPipeline } from "@int/geotoolkit/seismic/pipeline/SeismicPipeline.ts";
import { MemoryReader } from "@int/geotoolkit/seismic/data/MemoryReader.ts";
import { TrackType } from "@int/geotoolkit/welllog/TrackType.ts";
import { HeaderType } from "@int/geotoolkit/welllog/header/LogAxisVisualHeader.ts";
import { SeismicColors } from "@int/geotoolkit/seismic/util/SeismicColors.ts";
import { Rect } from "@int/geotoolkit/util/Rect.ts";
import { LogSeismicVisual } from "@int/geotoolkit/seislog/LogSeismicVisual.ts";
import { createWellLogWidget } from "/src/code/WellLog/utils/common.ts";
function createMemorySeismic(traceCount, sampleCount, sampleRate) {
const reader = new MemoryReader({
"numberoftraces": traceCount,
"numberofsamples": sampleCount,
"samplerate": sampleRate
});
let stats = null;
reader.setTraceProcessor({
"getTraceData": function(reader2, trace, traceId) {
const thickness = 36;
const start = 80;
let stepper = 0.05;
for (let i = start; i < start + thickness; i++) {
trace[i + Math.round(2 * Math.cos(traceId))] = Math.cos(i / 2) * stepper;
stepper += 0.05;
if (stepper > 1) {
stepper = 1;
}
}
},
"getDataStatistics": function() {
stats = {
"average": 0,
"min": -1,
"max": 1,
"rms": Math.sqrt(2)
};
return stats;
}
});
reader.readDataSetStatistics((reader2, statistics) => {
stats = statistics;
});
return {
"reader": reader,
"stats": stats
};
}
function createSeismicPipeline(plotType) {
const sampleRate = 1;
const sampleCount = 150;
const traceCount = 20;
const seismic = createMemorySeismic(traceCount, sampleCount, sampleRate);
const seismicReader = seismic["reader"];
const seismicStats = seismic["stats"];
const colorProvider = SeismicColors.getDefault();
return new SeismicPipeline({
"name": "MemorySeismic",
"reader": seismicReader,
"statistics": seismicStats
}).setColorMap(colorProvider.createNamedColorMap("WhiteBlack", 32)).setPlotType(plotType || {
"wiggle": true,
"interpolateddensity": true
});
}
function createLogSeismicVisual(plotType) {
const pipeline = createSeismicPipeline(plotType);
return new LogSeismicVisual({
"pipeline": pipeline
});
}
function createScene(canvas) {
const widget = createWellLogWidget().setAxisHeaderType(HeaderType.Simple).setDepthLimits(4500, 5500).scale(0.5);
widget.addTrack(TrackType.IndexTrack);
widget.addTrack(TrackType.LinearTrack).addChild([
createLogSeismicVisual({
"wiggle": true,
"interpolateddensity": true
}).setName("Regular Seismic").setBounds(new Rect(0, 4600, 1, 5e3))
]);
return new Plot({
"canvaselement": canvas,
"root": widget
});
}
export { createScene };
createScene(document.querySelector('[ref="plot"]'));
Close
# Wave Log Visual
The example below demonstrates how to add the wave visual to the widget.
import { Plot } from "@int/geotoolkit/plot/Plot.ts";
import { SeismicPipeline } from "@int/geotoolkit/seismic/pipeline/SeismicPipeline.ts";
import { MemoryReader } from "@int/geotoolkit/seismic/data/MemoryReader.ts";
import { NormalizationType } from "@int/geotoolkit/seismic/pipeline/NormalizationType.ts";
import { SeismicColors } from "@int/geotoolkit/seismic/util/SeismicColors.ts";
import { TrackType } from "@int/geotoolkit/welllog/TrackType.ts";
import { HeaderType } from "@int/geotoolkit/welllog/header/LogAxisVisualHeader.ts";
import { LogSeismicVisual, PlotType } from "@int/geotoolkit/seislog/LogSeismicVisual.ts";
import { Rect } from "@int/geotoolkit/util/Rect.ts";
import { initWaveConfiguration } from "/src/code/WellLog/SeismicInWelllog/common.ts";
import { createWellLogWidget } from "/src/code/WellLog/utils/common.ts";
function createWaveImage(config) {
const input = config["data"];
const minDepth = config["mindepth"];
const maxDepth = config["maxdepth"];
const min = config["colormapmin"];
const max = config["colormapmax"];
const colorMap = config["colormapname"];
const colorCount = config["colorcount"];
const interpolate = config["interpolated"];
const wiggle = config["wiggle"] === true;
const sampleRate = 1;
const sampleCount = input[0].length;
const traceCount = input.length;
const reader = new MemoryReader({
"numberoftraces": traceCount,
"numberofsamples": sampleCount,
"samplerate": sampleRate
});
reader.setTraceProcessor({
"getTraceData": function(reader2, trace, traceId) {
for (let i = 0; i < reader2.getNumberOfSamples(); i++) {
trace[i] = input[traceId][reader2.getNumberOfSamples() - i];
}
},
"getDataStatistics": function() {
return {
"average": max - min / 2,
"min": -1,
"max": 1,
"rms": Math.sqrt(2)
};
}
});
let stats = null;
reader.readDataSetStatistics((reader2, statistics) => {
stats = statistics;
});
const colorProvider = SeismicColors.getDefault();
const pipeline = new SeismicPipeline({
"name": "MemorySeismic",
"reader": reader,
"statistics": stats
}).setColorMap(colorProvider.createNamedColorMap(colorMap, colorCount)).setPlotType({
"wiggle": wiggle,
"interpolateddensity": interpolate ? true : false,
"simpledensity": interpolate ? false : true
}).setOptions({
"normalization": {
"type": NormalizationType.Limits,
"limits": {
min,
max
}
}
});
return new LogSeismicVisual({
"name": config["name"],
"pipeline": pipeline,
"bounds": new Rect(0, minDepth, 1, maxDepth),
"plottype": PlotType.Wave
});
}
function createScene(canvas) {
const configurations = initWaveConfiguration();
const widget = createWellLogWidget().setAxisHeaderType(HeaderType.Simple);
widget.addTrack(TrackType.IndexTrack);
let minDepth = Number.MAX_VALUE;
let maxDepth = -Number.MAX_VALUE;
for (let i = 0; i < configurations.length; i++) {
const config = configurations[i];
minDepth = Math.min(minDepth, config["mindepth"]);
maxDepth = Math.max(maxDepth, config["maxdepth"]);
widget.addTrack(TrackType.LinearTrack).addChild([
createWaveImage(configurations[i])
]);
}
widget.setDepthLimits(minDepth - (maxDepth - minDepth) / 10, maxDepth + (maxDepth - minDepth) / 10).scale(30);
return new Plot({
"canvaselement": canvas,
"root": widget
});
}
export { createScene };
createScene(document.querySelector('[ref="plot"]'));
Close
# Wave Form Pattern
In addition, the wave form visual can display patterns for positive and negative fills, as shown in the example below.
import { Plot } from "@int/geotoolkit/plot/Plot.ts";
import { SeismicPipeline } from "@int/geotoolkit/seismic/pipeline/SeismicPipeline.ts";
import { MemoryReader } from "@int/geotoolkit/seismic/data/MemoryReader.ts";
import { PatternFactory } from "@int/geotoolkit/attributes/PatternFactory.ts";
import { NormalizationType } from "@int/geotoolkit/seismic/pipeline/NormalizationType.ts";
import { SeismicColors } from "@int/geotoolkit/seismic/util/SeismicColors.ts";
import { TrackType } from "@int/geotoolkit/welllog/TrackType.ts";
import { HeaderType } from "@int/geotoolkit/welllog/header/LogAxisVisualHeader.ts";
import { LogSeismicVisual, PlotType } from "@int/geotoolkit/seislog/LogSeismicVisual.ts";
import { Rect } from "@int/geotoolkit/util/Rect.ts";
import { initWaveConfiguration } from "/src/code/WellLog/SeismicInWelllog/common.ts";
import { createWellLogWidget } from "/src/code/WellLog/utils/common.ts";
function createWavePatternImage(config) {
const input = config["data"];
const minDepth = config["mindepth"];
const maxDepth = config["maxdepth"];
const min = config["colormapmin"];
const max = config["colormapmax"];
const sampleRate = 1;
const sampleCount = input[0].length;
const traceCount = input.length;
const reader = new MemoryReader({
"numberoftraces": traceCount,
"numberofsamples": sampleCount,
"samplerate": sampleRate
});
reader.setTraceProcessor({
"getTraceData": function(reader2, trace, traceId) {
for (let i = 0; i < reader2.getNumberOfSamples(); i++) {
trace[i] = input[traceId][reader2.getNumberOfSamples() - i];
}
},
"getDataStatistics": function() {
return {
"average": max - min / 2,
"min": -1,
"max": 1,
"rms": Math.sqrt(2)
};
}
});
let stats = null;
reader.readDataSetStatistics((reader2, statistics) => {
stats = statistics;
});
const colorProvider = SeismicColors.getDefault();
const colorMap = colorProvider.createNamedColorMap("RedWhiteBlack");
const pattern = PatternFactory.getInstance().createPattern(
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwgAADsIBFShKgAAAAF5JREFUWEftlDEOACAIA/n/p1USNYisdDoTHexQqQdmZmMtP77tWrvuxpVJvOvUb9Uqw1zwE7sk8vTlZfyHB8mDYCC2nyRyGNgD77Q9c4A5AAMwAAMwAAMwAAMwAAMTIjn2iP6kzQIAAAAASUVORK5CYII="
);
colorMap.setPositiveFillStyle({
"pattern": pattern,
"foreground": "grey"
});
colorMap.setNegativeFillStyle({
"pattern": pattern,
"foreground": "grey"
});
colorMap.setTraceLineStyle("red");
const pipeline = new SeismicPipeline({
"name": "MemorySeismic",
"reader": reader,
"statistics": stats
}).setColorMap(colorMap).setOptions({
"normalization": {
"type": NormalizationType.Limits,
"limits": {
min: 2 * min,
max: 2 * max
}
},
"plot": {
"type": {
"wiggle": true,
"negativefill": true,
"positivefill": true,
"negativecolorfill": false,
"positivecolorfill": false
}
}
});
return new LogSeismicVisual({
"name": config["name"],
"pipeline": pipeline,
"bounds": new Rect(0, minDepth, 1, maxDepth),
"plottype": PlotType.Wave
});
}
function createScene(canvas) {
const config = initWaveConfiguration()[1];
const widget = createWellLogWidget().setAxisHeaderType(HeaderType.Simple);
widget.addTrack(TrackType.IndexTrack);
widget.addTrack(TrackType.LinearTrack).addChild([
createWavePatternImage(config)
]);
let minDepth = Number.MAX_VALUE;
let maxDepth = -Number.MAX_VALUE;
minDepth = Math.min(minDepth, config["mindepth"]);
maxDepth = Math.max(maxDepth, config["maxdepth"]);
widget.setDepthLimits(minDepth - (maxDepth - minDepth) / 10, maxDepth + (maxDepth - minDepth) / 10).scale(150);
return new Plot({
"canvaselement": canvas,
"root": widget
});
}
export { createScene };
createScene(document.querySelector('[ref="plot"]'));
Close
# Align Traces by Depth
To align traces with exact depth values, you should use geotoolkit/seismic/data/VSTraceMapping. It requires to pass depths or times for all traces starting from zero.
import { Plot } from "@int/geotoolkit/plot/Plot.ts";
import { SeismicPipeline } from "@int/geotoolkit/seismic/pipeline/SeismicPipeline.ts";
import { MemoryReader } from "@int/geotoolkit/seismic/data/MemoryReader.ts";
import { NumericalDataSeries } from "@int/geotoolkit/data/NumericalDataSeries.ts";
import { VSTraceMapping } from "@int/geotoolkit/seismic/data/VSTraceMapping.ts";
import { Range } from "@int/geotoolkit/util/Range.ts";
import { NormalizationType } from "@int/geotoolkit/seismic/pipeline/NormalizationType.ts";
import { SeismicColors } from "@int/geotoolkit/seismic/util/SeismicColors.ts";
import { TrackType } from "@int/geotoolkit/welllog/TrackType.ts";
import { HeaderType } from "@int/geotoolkit/welllog/header/LogAxisVisualHeader.ts";
import { LogSeismicVisual, PlotType } from "@int/geotoolkit/seislog/LogSeismicVisual.ts";
import { Rect } from "@int/geotoolkit/util/Rect.ts";
import { WaveVisualHeader } from "/src/code/WellLog/SeismicInWelllog/waveheader.ts";
import { createWellLogWidget } from "/src/code/WellLog/utils/common.ts";
function createWaveFormVisual(depths, values) {
const sampleRate = 1;
let i, j;
const sampleCount = values[0].length;
const traceCount = depths.length;
const reader = new MemoryReader({
"numberoftraces": traceCount,
"numberofsamples": sampleCount,
"samplerate": sampleRate
});
let minDepth = Number.MAX_VALUE;
let maxDepth = -Number.MAX_VALUE;
let min = Number.MAX_VALUE;
let max = -Number.MAX_VALUE;
for (i = 0; i < depths.length; ++i) {
if (depths[i] < minDepth)
minDepth = depths[i];
if (depths[i] > maxDepth)
maxDepth = depths[i];
for (j = 0; j < sampleCount; ++j) {
if (values[i][j] < min)
min = values[i][j];
if (values[i][j] > max)
max = values[i][j];
}
}
if (min === 0 || max === 0) {
min === 0 ? min = -max : max = -min;
}
if (min === max) {
min = min - 1;
max = max + 1;
}
reader.setTraceProcessor({
"getTraceData": function(reader2, trace, traceId) {
for (let i2 = 0; i2 < reader2.getNumberOfSamples(); i2++) {
trace[i2] = values[traceId][i2];
}
},
"getDataStatistics": function() {
return {
"average": (max - min) / 2,
"min": min,
"max": max,
"rms": Math.sqrt(2)
};
}
});
let stats = null;
reader.readDataSetStatistics((reader2, statistics) => {
stats = statistics;
});
const colorProvider = SeismicColors.getDefault();
const colorMap = colorProvider.createNamedColorMap("RedGreenBlue").setNegativeFillStyle("rgba(0,255,0,0.5)").setPositiveFillStyle("green").setTraceLineStyle("black");
const pipeline = new SeismicPipeline({
"name": "MemorySeismic",
"reader": reader,
"statistics": stats
}).setColorMap(colorMap).setPlotType({
"wiggle": true,
"interpolateddensity": false,
"negativefill": true,
"positivefill": true,
"reversed": true
}).setNormalization({
"type": NormalizationType.Limits,
"limits": {
"min": min,
"max": max
}
});
const positions = new NumericalDataSeries({ "data": depths });
const traceSpacing = 20;
const traceModel = new Range(minDepth - traceSpacing, maxDepth + traceSpacing);
const mapping = new VSTraceMapping(pipeline, positions, traceSpacing, traceModel);
pipeline.setTraceMapping(mapping);
const imageModelLimits = pipeline.getModelLimits();
return new LogSeismicVisual({
"name": "Depth wave visual",
"pipeline": pipeline,
"bounds": new Rect(0, imageModelLimits.getLeft(), 1, imageModelLimits.getRight()),
"plottype": PlotType.Wave
}).setTag({
"depths": new Range(minDepth, maxDepth),
"unit": "ft3/ft3"
});
}
function createScene(canvas) {
let minDepth = 4500;
const maxDepth = 6e3;
const depthStep = 20;
const widget = createWellLogWidget().setAxisHeaderType(HeaderType.Simple).setDepthLimits(minDepth, maxDepth);
widget.addTrack(TrackType.IndexTrack);
widget.getHeaderContainer().getHeaderProvider().registerHeaderProvider(LogSeismicVisual.getClassName(), new WaveVisualHeader());
const depths = [];
const values = [];
minDepth = 4600;
const tracesCount = 20;
const samplesCount = 200;
for (let i = 0; i < tracesCount; i++) {
const samples = [];
for (let j = 0; j < samplesCount; j++) {
samples[j] = 0;
if (j > 50 && j < 100)
samples[j] = j - 50;
if (j >= 100 && j < 150)
samples[j] = 150 - j;
}
values.push(samples);
depths.push(minDepth + i * depthStep);
if (depths[depths.length - 1] > maxDepth) {
break;
}
}
widget.addTrack(TrackType.LinearTrack).addChild([
createWaveFormVisual(depths, values)
]);
return new Plot({
"canvaselement": canvas,
"root": widget
});
}
export { createScene };
createScene(document.querySelector('[ref="plot"]'));
Close
# Real-Time Wave Log Visual
The following example shows how to add a Wave Visual to a Widget in real-time.
import { Plot } from "@int/geotoolkit/plot/Plot.ts";
import { WellLogWidget } from "@int/geotoolkit/welllog/widgets/WellLogWidget.ts";
import { SeismicPipeline } from "@int/geotoolkit/seismic/pipeline/SeismicPipeline.ts";
import { MemoryReader } from "@int/geotoolkit/seismic/data/MemoryReader.ts";
import { NormalizationType } from "@int/geotoolkit/seismic/pipeline/NormalizationType.ts";
import { TrackType } from "@int/geotoolkit/welllog/TrackType.ts";
import { HeaderType } from "@int/geotoolkit/welllog/header/LogAxisVisualHeader.ts";
import { SeismicColors } from "@int/geotoolkit/seismic/util/SeismicColors.ts";
import { interpolate } from "/src/code/WellLog/SeismicInWelllog/common.ts";
import { CEMODCF } from "/src/code/WellLog/SeismicInWelllog/data/CEMO_m331dR01_DCF.ts";
import { WAVEDCF } from "/src/code/WellLog/SeismicInWelllog/data/WAVE_m331dR01_DCF.ts";
import { from } from "@int/geotoolkit/selection/from.ts";
import { LogSeismicVisual, PlotType } from "@int/geotoolkit/seislog/LogSeismicVisual.ts";
import { Rect } from "@int/geotoolkit/util/Rect.ts";
import { createWellLogWidget } from "/src/code/WellLog/utils/common.ts";
let WaveSeislogImages;
function initWaveConfiguration() {
SeismicColors.getDefault().register("d1", (map) => {
const colors = [];
interpolate(colors, 0, 255, {
A: 255,
R: 102,
G: 0,
B: 0
}, {
A: 255,
R: 254,
G: 253,
B: 223
});
map.setColors(colors);
}).register("Cool", (map) => {
const colors = [];
interpolate(colors, 0, 127, {
A: 255,
R: 153,
G: 255,
B: 255
}, {
A: 255,
R: 80,
G: 80,
B: 180
});
interpolate(colors, 127, 255, {
A: 255,
R: 80,
G: 80,
B: 180
}, {
A: 255,
R: 102,
G: 29,
B: 111
});
map.setColors(colors);
}).register("d2", (map) => {
const colors = [];
interpolate(colors, 0, 18, {
A: 255,
R: 255,
G: 252,
B: 158
}, {
A: 255,
R: 56,
G: 12,
B: 11
});
map.setColors(colors);
});
return [{
data: WAVEDCF,
startdepth: 3060,
step: 1,
colormapmin: 2,
colormapmax: 25,
colormapname: "Cool",
colorcount: 255,
interpolated: true,
wiggle: true
}, {
data: CEMODCF,
startdepth: 3060,
step: 1,
colormapmin: 56.58,
colormapmax: 135,
colormapname: "d2",
colorcount: 18,
interpolated: true,
wiggle: true
}];
}
function createWaveImage(config) {
const input = config["data"];
const amountOfTraces = 5;
const minDepth = config["startdepth"];
const maxDepth = minDepth + amountOfTraces * config["step"];
const colorMap = config["colormapname"];
const colorCount = config["colorcount"];
const interpolate2 = config["interpolated"];
const wiggle = config["wiggle"] === true;
const sampleRate = 1;
const sampleCount = input[0].length;
const reader = new MemoryReader({
"numberoftraces": amountOfTraces,
"numberofsamples": sampleCount,
"samplerate": sampleRate
});
let min = Number.POSITIVE_INFINITY;
let max = Number.NEGATIVE_INFINITY;
let rms = 0;
let average = 0;
for (let traceId = 0; traceId < input.length; traceId++) {
const trace = input[traceId];
for (let i = 0; i < trace.length; i++) {
const sample = trace[i];
min = Math.min(min, sample);
max = Math.max(max, sample);
average += sample < 0 ? -sample : sample;
average += sample;
rms += sample * sample;
}
}
reader.setTraceProcessor({
"getTraceData": function(reader2, trace, traceId) {
const samplesCount = reader2.getNumberOfSamples();
for (let i = 0; i < samplesCount; i++) {
if (traceId >= input.length) {
traceId -= input.length;
}
trace[i] = input[traceId][i];
}
},
"getDataStatistics": function(reader2) {
const samplesAmount = amountOfTraces * reader2.getNumberOfSamples();
return {
"min": min,
"max": max,
"average": average / samplesAmount,
"rms": Math.sqrt(rms / samplesAmount)
};
}
});
let stats = null;
reader.readDataSetStatistics((reader2, statistics) => {
stats = statistics;
});
const colorProvider = SeismicColors.getDefault();
const pipeline = new SeismicPipeline({
"name": "MemorySeismic",
"reader": reader,
"statistics": stats
}).setColorMap(colorProvider.createNamedColorMap(colorMap, colorCount)).setPlotType({
"wiggle": wiggle,
"interpolateddensity": interpolate2,
"simpledensity": !interpolate2
}).setOptions({
"normalization": {
"type": NormalizationType.Limits,
"limits": {
min,
max
}
}
});
const waveSeislogImage = new LogSeismicVisual({
"pipeline": pipeline,
"plottype": PlotType.Wave,
"bounds": new Rect(0, minDepth, 1, maxDepth),
"timetowaitchanges": 0
});
WaveSeislogImages.push({
"pipeline": pipeline,
"image": waveSeislogImage,
"data": input,
"traces": amountOfTraces,
"step": config["step"]
});
return waveSeislogImage;
}
function getWidget(plot) {
return from(plot.getRoot()).where((node) => node instanceof WellLogWidget).selectFirst();
}
function zoomIn(plot) {
getWidget(plot).scale(5 / 4);
}
function zoomOut(plot) {
getWidget(plot).scale(4 / 5);
}
function fitToHeight(plot) {
getWidget(plot).fitToHeight();
}
function run(plot) {
return window.setInterval(() => {
addTraces(1, plot);
}, 100);
}
function stop(interval) {
if (interval != null) {
clearInterval(interval);
}
}
function addTraces(traceAmount, plot) {
const widget = getWidget(plot);
for (let i = 0; i < WaveSeislogImages.length; i++) {
const waveInfo = WaveSeislogImages[i];
const pipeline = waveInfo["pipeline"];
const reader = pipeline.getReader();
let numberOfTraces = reader.getNumberOfTraces();
numberOfTraces += traceAmount;
if (numberOfTraces > 100) {
numberOfTraces = 5;
}
const bounds = waveInfo["image"].getBounds().clone().setHeight(numberOfTraces * waveInfo["step"]);
const seismicModelLimits = waveInfo["image"].getModelLimits().clone().setWidth(numberOfTraces);
reader.setNumberOfTraces(numberOfTraces);
pipeline.resetModelLimits();
waveInfo["image"].setModelLimits(seismicModelLimits).setBounds(bounds);
widget.setDepthLimits(widget.getDepthLimits().getLow(), waveInfo["image"].getBounds().getBottom() + 2).scrollToIndex(waveInfo["image"].getBounds().getBottom() + 2);
waveInfo["traces"] = numberOfTraces;
}
}
function createScene(canvas) {
WaveSeislogImages = [];
const configurations = initWaveConfiguration();
const widget = createWellLogWidget().setAxisHeaderType(HeaderType.Simple);
widget.addTrack(TrackType.IndexTrack);
let minDepth = Number.MAX_VALUE;
let maxDepth = -Number.MAX_VALUE;
for (let i = 0; i < configurations.length; i++) {
const waveImage = createWaveImage(configurations[i]);
minDepth = Math.min(minDepth, waveImage.getBounds().getTop());
maxDepth = Math.max(maxDepth, waveImage.getBounds().getBottom());
widget.addTrack(TrackType.LinearTrack).addChild([waveImage]);
}
widget.setDepthLimits(minDepth - (maxDepth - minDepth) / 4, maxDepth + (maxDepth - minDepth) / 4).scale(10);
const plot = new Plot({
"canvaselement": canvas,
"root": widget,
"autosize": false,
"autorootbounds": true
});
return plot;
}
export { createScene, fitToHeight, run, stop, zoomIn, zoomOut };
createScene(document.querySelector('[ref="plot"]'));
Close