This tutorial demonstrates how to customize a seismic display by using various options available in the Seismic Pipeline. It shows how to set up different plot types to display wiggles, density plot, and color fill for wiggles.
On a logical level, the pipeline is a container of several trace processes (organized in a certain order) which work on processing trace data (samples). Default trace processes are normalization of data, interpolation of samples, and rasterization based on plot type.
# Displaying Seismic Wiggles Only
The code below shows how to visualize only the wiggles using the setOptions() method on the Seismic Pipeline.
import { NormalizationType } from "@int/geotoolkit/seismic/pipeline/NormalizationType.ts";
import { SeismicPipeline } from "@int/geotoolkit/seismic/pipeline/SeismicPipeline.ts";
import { SeismicColors } from "@int/geotoolkit/seismic/util/SeismicColors.ts";
import { Plot } from "@int/geotoolkit/plot/Plot.ts";
import { createReader, createWidget } from "/src/code/Seismic/Pipeline/common.ts";
function createScene(canvas) {
const reader = createReader();
const colorProvider = SeismicColors.getDefault();
const wigglesOnlyPipeline = new SeismicPipeline({
"name": "WigglesOnlyPipeline",
"reader": reader,
"statistics": reader.getStatistics()
}).setOptions({
"colors": {
"colormap": colorProvider.createNamedColorMap("WhiteBlack")
},
"normalization": {
"type": NormalizationType.Limits,
"limits": {
"min": -1,
"max": 1
}
},
"plot": {
"type": {
"wiggle": true
},
"decimationspacing": 5
}
});
const widget = createWidget(wigglesOnlyPipeline, {
"layouttype": "inside",
"colorbar": {
"visible": false
}
});
return new Plot({
"canvaselement": canvas,
"root": widget
});
}
export { createScene };
createScene(document.querySelector('[ref="plot"]'));
# Displaying Seismic Wiggles with Black Positive Fill
The code below shows how to display the wiggles with black positive and negative fill using the setOptions() method on the Seismic Pipeline.
import { NormalizationType } from "@int/geotoolkit/seismic/pipeline/NormalizationType.ts";
import { SeismicPipeline } from "@int/geotoolkit/seismic/pipeline/SeismicPipeline.ts";
import { SeismicColors } from "@int/geotoolkit/seismic/util/SeismicColors.ts";
import { Plot } from "@int/geotoolkit/plot/Plot.ts";
import { createReader, createWidget } from "/src/code/Seismic/Pipeline/common.ts";
function createScene(canvas) {
const reader = createReader();
const colorProvider = SeismicColors.getDefault();
const positiveFillWigglePipeline = new SeismicPipeline({
"name": "PositiveFillWigglePipeline",
"reader": reader,
"statistics": reader.getStatistics()
}).setOptions({
"colors": {
"colormap": colorProvider.createNamedColorMap("WhiteBlack")
},
"normalization": {
"type": NormalizationType.Limits,
"limits": {
"min": -1,
"max": 1
}
},
"plot": {
"type": {
"wiggle": true,
"positivefill": true
},
"decimationspacing": 5
}
});
const widget = createWidget(positiveFillWigglePipeline, {
"colorbar": {
"visible": false
}
});
return new Plot({
"canvaselement": canvas,
"root": widget
});
}
export { createScene };
createScene(document.querySelector('[ref="plot"]'));
# Displaying a Seismic in Interpolated Density Mode
The code below shows how to display the interpolated density fill using the setOptions() method on the Seismic Pipeline.
.cg-tooltip-holder {
position: relative;
}
.cg-tooltip {
position: absolute;
display: block;
padding: 2px 12px 3px 7px;
overflow: visible !important;
font-family: Roboto, Helvetica, Arial, sans-serif;
font-size: 13px;
background: white !important;
opacity: 0.9;
color: #333333;
border: solid 1px gray;
border-radius: 5px;
text-align: left;
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
border-radius: 5px;
margin: 0 !important;
z-index: 10000;
max-width: 400px;
text-wrap: normal !important;
white-space: normal !important;
}
/* Default setting for tooltip */
.cg-tooltip-container {
position: absolute;
display: block;
overflow: visible !important;
font-family: Roboto, Helvetica, Arial, sans-serif;
font-size: 12px;
padding: 3px 7px;
background: #f7f7f7;
color: #333333;
border: 1px solid #938e8e;
opacity: 0.8;
text-align: left;
box-shadow: 3px 3px 10px #888;
margin: 0 !important;
z-index: 10000;
max-width: 400px;
text-wrap: normal !important;
white-space: normal !important;
user-select: none;
}
@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {
.cg-tooltip-container {
border-radius: 0;
}
}
/* Default left arrow for tooltip */
.cg-tooltip-arrow-left::before {
content: '';
position: absolute;
display: block;
width: 0px;
left: 0;
top: 50%;
border: 5px solid transparent;
border-left: 0;
border-right: 5px solid #938e8e;
transform: translate(calc(-100%), -50%);
}
.cg-tooltip-arrow-left::after {
content: '';
position: absolute;
display: block;
width: 0px;
left: 0;
top: 50%;
border: 4px solid transparent;
border-left: 0;
border-right: 4px solid #f7f7f7;
transform: translate(calc(-100%), -50%);
}
/* Default top arrow for tooltip */
.cg-tooltip-arrow-top::before {
content: '';
position: absolute;
display: block;
width: 0px;
left: 50%;
top: 0;
border: 5px solid transparent;
border-top: 0;
border-bottom: 5px solid #938e8e;
transform: translate(-50%, -100%);
}
.cg-tooltip-arrow-top::after {
content: '';
position: absolute;
display: block;
width: 0px;
left: 50%;
top: 0;
border: 4px solid transparent;
border-top: 0;
border-bottom: 4px solid #f7f7f7;
transform: translate(-50%, -100%);
}
/* Default right arrow for tooltip */
.cg-tooltip-arrow-right::before {
content: '';
position: absolute;
display: block;
width: 0px;
right: 0;
top: 50%;
border: 5px solid transparent;
border-right: 0;
border-left: 5px solid #938e8e;
transform: translate(100%, -50%);
}
.cg-tooltip-arrow-right::after {
content: '';
position: absolute;
display: block;
width: 0px;
right: 0;
top: 50%;
border: 4px solid transparent;
border-right: 0;
border-left: 4px solid #f7f7f7;
transform: translate(100%, -50%);
}
/* Default bottom arrow for tooltip */
.cg-tooltip-arrow-bottom::before {
content: '';
position: absolute;
display: block;
width: 0px;
left: 50%;
bottom: 0px;
border: 5px solid transparent;
border-bottom: 0;
border-top: 5px solid #938e8e;
transform: translate(-50%, 100%);
z-index: 10000;
}
.cg-tooltip-arrow-bottom::after {
content: '';
position: absolute;
display: block;
width: 0px;
left: 50%;
bottom: 0;
border: 4px solid transparent;
border-bottom: 0;
border-top: 4px solid #f7f7f7;
transform: translate(-50%, 100%);
z-index: 10000;
}
/* Tooltip item name */
/* Tooltip item value */
/* .cg-tooltip-item-value */
/* Tooltip item value */
.cg-tooltip-item-unit {
text-transform: none;
}
.cg-tooltip-item-name {
text-transform: capitalize;
white-space: nowrap;
vertical-align: middle;
font-size: 13px;
}
.cg-tooltip-row {
display: flex;
flex-direction: row;
align-items: center;
white-space: pre-wrap;
font-size: 12px;
line-height: 100%;
margin: 1px 0;
}
.cg-tooltip-title {
font-size: 13px;
height: 14px;
text-transform: capitalize;
}
.cg-tooltip-title .cg-tooltip-symbol {
margin-right: 0 !important;
}
.cg-tooltip-title-name {
vertical-align: middle;
}
.cg-tooltip-row + .cg-tooltip-row {
margin-top: 4px;
}
.cg-tooltip-row.cg-tooltip-title + .cg-tooltip-row {
margin-top: 5px;
}
.cg-tooltip-item-value + .cg-tooltip-item-unit {
margin-left: 1px;
}
/* Tooltip symbol */
.cg-tooltip-symbol-cell {
display: inline-flex;
min-width: 13px; /* 10px size + 3px margin */
}
.cg-tooltip-symbol {
margin-right: 3px;
background-color: transparent;
display: block;
}
.cg-tooltip-symbol > img {
display: block;
}
.cg-tooltip-list-cell {
display: inline-flex;
}
.cg-tooltip-list-symbol {
display: block;
margin-right: 3px;
width: 6px;
height: 6px;
vertical-align: middle;
border-radius: 50%;
border: 1px solid rgba(0,0,0,.4);
}
.cg-tooltip-symbol-legacy {
border-radius: 4px;
margin-right: 5px;
height: 8px;
width: 8px;
display: inline-block;
}
.cg-tooltip-title-legacy {
font-weight: 900;
}
/* Tooltip symbol circle */
.cg-tooltip-symbol.circle {
height: 10px;
width: 10px;
display: inline-block;
border-radius: 50%;
border: 1px solid rgba(0,0,0,.4);
}
/* Tooltip symbol line */
.cg-tooltip-symbol.line {
height: 10px;
width: 10px;
display: inline-block;
transform: scale(1.2, 0.2);
}
/* Tooltip symbol diamond */
.cg-tooltip-symbol.diamond {
height: 10px;
width: 10px;
display: inline-block;
transform: rotate(45deg);
border-radius: 0px;
}
/* Tooltip symbol square */
.cg-tooltip-symbol.square {
height: 10px;
width: 10px;
display: inline-block;
border-radius: 0px;
border: 1px solid rgba(0,0,0,.4);
}
# Changing Colormap and Plot Type
The code below shows how to change color map type using setOptions() method on the Seismic Pipeline.
import { NormalizationType } from "@int/geotoolkit/seismic/pipeline/NormalizationType.ts";
import { SeismicPipeline } from "@int/geotoolkit/seismic/pipeline/SeismicPipeline.ts";
import { SeismicColors } from "@int/geotoolkit/seismic/util/SeismicColors.ts";
import { Plot } from "@int/geotoolkit/plot/Plot.ts";
import { Patterns } from "@int/geotoolkit/attributes/LineStyle.ts";
import { createReader, createWidget } from "/src/code/Seismic/Pipeline/common.ts";
function createScene(canvas) {
const reader = createReader();
const colorProvider = SeismicColors.getDefault();
const colorsMapNames = colorProvider.listNameColorMaps();
const colorMapPipeline = new SeismicPipeline({
"name": "ColorMapPipeline",
"reader": reader,
"statistics": reader.getStatistics()
}).setOptions({
"normalization": {
"type": NormalizationType.Limits,
"limits": {
"min": -1,
"max": 1
}
}
});
const colorMap = colorProvider.createNamedColorMap(colorsMapNames[9], 32);
colorMap.setTraceLineStyle({
"color": "green",
"width": 2,
"pattern": Patterns.DashDot
});
colorMapPipeline.setColorMap(colorMap);
colorMapPipeline.setPlotType({
wiggle: true,
interpolateddensity: true
});
const widget = createWidget(colorMapPipeline);
return new Plot({
"canvaselement": canvas,
"root": widget
});
}
export { createScene };
createScene(document.querySelector('[ref="plot"]'));
# Display Wiggles with Positive and Negative Fill
The code below shows how to display wiggles with positive and negative fill using the setOptions() method on the Seismic Pipeline.
.cg-tooltip-holder {
position: relative;
}
.cg-tooltip {
position: absolute;
display: block;
padding: 2px 12px 3px 7px;
overflow: visible !important;
font-family: Roboto, Helvetica, Arial, sans-serif;
font-size: 13px;
background: white !important;
opacity: 0.9;
color: #333333;
border: solid 1px gray;
border-radius: 5px;
text-align: left;
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
border-radius: 5px;
margin: 0 !important;
z-index: 10000;
max-width: 400px;
text-wrap: normal !important;
white-space: normal !important;
}
/* Default setting for tooltip */
.cg-tooltip-container {
position: absolute;
display: block;
overflow: visible !important;
font-family: Roboto, Helvetica, Arial, sans-serif;
font-size: 12px;
padding: 3px 7px;
background: #f7f7f7;
color: #333333;
border: 1px solid #938e8e;
opacity: 0.8;
text-align: left;
box-shadow: 3px 3px 10px #888;
margin: 0 !important;
z-index: 10000;
max-width: 400px;
text-wrap: normal !important;
white-space: normal !important;
user-select: none;
}
@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {
.cg-tooltip-container {
border-radius: 0;
}
}
/* Default left arrow for tooltip */
.cg-tooltip-arrow-left::before {
content: '';
position: absolute;
display: block;
width: 0px;
left: 0;
top: 50%;
border: 5px solid transparent;
border-left: 0;
border-right: 5px solid #938e8e;
transform: translate(calc(-100%), -50%);
}
.cg-tooltip-arrow-left::after {
content: '';
position: absolute;
display: block;
width: 0px;
left: 0;
top: 50%;
border: 4px solid transparent;
border-left: 0;
border-right: 4px solid #f7f7f7;
transform: translate(calc(-100%), -50%);
}
/* Default top arrow for tooltip */
.cg-tooltip-arrow-top::before {
content: '';
position: absolute;
display: block;
width: 0px;
left: 50%;
top: 0;
border: 5px solid transparent;
border-top: 0;
border-bottom: 5px solid #938e8e;
transform: translate(-50%, -100%);
}
.cg-tooltip-arrow-top::after {
content: '';
position: absolute;
display: block;
width: 0px;
left: 50%;
top: 0;
border: 4px solid transparent;
border-top: 0;
border-bottom: 4px solid #f7f7f7;
transform: translate(-50%, -100%);
}
/* Default right arrow for tooltip */
.cg-tooltip-arrow-right::before {
content: '';
position: absolute;
display: block;
width: 0px;
right: 0;
top: 50%;
border: 5px solid transparent;
border-right: 0;
border-left: 5px solid #938e8e;
transform: translate(100%, -50%);
}
.cg-tooltip-arrow-right::after {
content: '';
position: absolute;
display: block;
width: 0px;
right: 0;
top: 50%;
border: 4px solid transparent;
border-right: 0;
border-left: 4px solid #f7f7f7;
transform: translate(100%, -50%);
}
/* Default bottom arrow for tooltip */
.cg-tooltip-arrow-bottom::before {
content: '';
position: absolute;
display: block;
width: 0px;
left: 50%;
bottom: 0px;
border: 5px solid transparent;
border-bottom: 0;
border-top: 5px solid #938e8e;
transform: translate(-50%, 100%);
z-index: 10000;
}
.cg-tooltip-arrow-bottom::after {
content: '';
position: absolute;
display: block;
width: 0px;
left: 50%;
bottom: 0;
border: 4px solid transparent;
border-bottom: 0;
border-top: 4px solid #f7f7f7;
transform: translate(-50%, 100%);
z-index: 10000;
}
/* Tooltip item name */
/* Tooltip item value */
/* .cg-tooltip-item-value */
/* Tooltip item value */
.cg-tooltip-item-unit {
text-transform: none;
}
.cg-tooltip-item-name {
text-transform: capitalize;
white-space: nowrap;
vertical-align: middle;
font-size: 13px;
}
.cg-tooltip-row {
display: flex;
flex-direction: row;
align-items: center;
white-space: pre-wrap;
font-size: 12px;
line-height: 100%;
margin: 1px 0;
}
.cg-tooltip-title {
font-size: 13px;
height: 14px;
text-transform: capitalize;
}
.cg-tooltip-title .cg-tooltip-symbol {
margin-right: 0 !important;
}
.cg-tooltip-title-name {
vertical-align: middle;
}
.cg-tooltip-row + .cg-tooltip-row {
margin-top: 4px;
}
.cg-tooltip-row.cg-tooltip-title + .cg-tooltip-row {
margin-top: 5px;
}
.cg-tooltip-item-value + .cg-tooltip-item-unit {
margin-left: 1px;
}
/* Tooltip symbol */
.cg-tooltip-symbol-cell {
display: inline-flex;
min-width: 13px; /* 10px size + 3px margin */
}
.cg-tooltip-symbol {
margin-right: 3px;
background-color: transparent;
display: block;
}
.cg-tooltip-symbol > img {
display: block;
}
.cg-tooltip-list-cell {
display: inline-flex;
}
.cg-tooltip-list-symbol {
display: block;
margin-right: 3px;
width: 6px;
height: 6px;
vertical-align: middle;
border-radius: 50%;
border: 1px solid rgba(0,0,0,.4);
}
.cg-tooltip-symbol-legacy {
border-radius: 4px;
margin-right: 5px;
height: 8px;
width: 8px;
display: inline-block;
}
.cg-tooltip-title-legacy {
font-weight: 900;
}
/* Tooltip symbol circle */
.cg-tooltip-symbol.circle {
height: 10px;
width: 10px;
display: inline-block;
border-radius: 50%;
border: 1px solid rgba(0,0,0,.4);
}
/* Tooltip symbol line */
.cg-tooltip-symbol.line {
height: 10px;
width: 10px;
display: inline-block;
transform: scale(1.2, 0.2);
}
/* Tooltip symbol diamond */
.cg-tooltip-symbol.diamond {
height: 10px;
width: 10px;
display: inline-block;
transform: rotate(45deg);
border-radius: 0px;
}
/* Tooltip symbol square */
.cg-tooltip-symbol.square {
height: 10px;
width: 10px;
display: inline-block;
border-radius: 0px;
border: 1px solid rgba(0,0,0,.4);
}
# Changing Opacity
The code below shows how to change opacity to specific part of seismic rasterization, in this case we did change Fills opacity with using the setOptions() method on the Seismic Pipeline.
Traces Opacity
255
255
Fills Opacity
153
153
Density Opacity
153
153
import { NormalizationType } from "@int/geotoolkit/seismic/pipeline/NormalizationType.ts";
import { SeismicPipeline } from "@int/geotoolkit/seismic/pipeline/SeismicPipeline.ts";
import { SeismicColors } from "@int/geotoolkit/seismic/util/SeismicColors.ts";
import { Plot } from "@int/geotoolkit/plot/Plot.ts";
import { createReader, createWidget } from "/src/code/Seismic/Pipeline/common.ts";
import { Rect } from "@int/geotoolkit/util/Rect.ts";
function createScene(canvas) {
const reader = createReader();
const opacityPipeline = new SeismicPipeline({
"name": "OpacityPipeline",
"reader": reader,
"statistics": reader.getStatistics()
}).setOptions({
"colors": {
"opacity": {
"traces": 1,
"fills": 0.6,
"density": 0.6
},
"colormap": SeismicColors.getDefault().createNamedColorMap("WhiteBlack").setPositiveFillStyle("blue").setNegativeFillStyle("red")
},
"normalization": {
"type": NormalizationType.Limits,
"limits": {
"min": -0.8,
"max": 0.8
}
},
"plot": {
"wigglesantialiasing": true,
"type": {
"wiggle": true,
"simpledensity": true,
"negativefill": true,
"positivefill": true
},
"decimationspacing": 5
}
});
const widget = createWidget(opacityPipeline);
const plot = new Plot({
"canvaselement": canvas,
"root": widget
});
widget.setVisibleSeismicModelLimits(new Rect(0, 80, 10, 120));
return plot;
}
export { createScene };
createScene(document.querySelector('[ref="plot"]'));
# Trace status
The code below shows how to change the trace status using the setTraceStatus() method on the Seismic Pipeline. To see how it works you can select trace by mouse click.
import { Events as SelectionEvents } from "@int/geotoolkit/controls/tools/Selection.ts";
import { PointerMode } from "@int/geotoolkit/controls/tools/PointerMode.ts";
import { Status } from "@int/geotoolkit/seismic/data/Trace.ts";
import { NormalizationType } from "@int/geotoolkit/seismic/pipeline/NormalizationType.ts";
import { SeismicPipeline } from "@int/geotoolkit/seismic/pipeline/SeismicPipeline.ts";
import { SeismicColors } from "@int/geotoolkit/seismic/util/SeismicColors.ts";
import { Plot } from "@int/geotoolkit/plot/Plot.ts";
import { LineStyle, Patterns } from "@int/geotoolkit/attributes/LineStyle.ts";
import { createReader, createWidget } from "/src/code/Seismic/Pipeline/common.ts";
function createScene(canvas) {
const reader = createReader();
const positiveNegativeWigglePipeline = new SeismicPipeline({
"name": "PositiveNegativeWigglePipeline",
"reader": reader,
"statistics": reader.getStatistics()
}).setOptions({
"colors": {
"colormap": SeismicColors.getDefault().createNamedColorMap("RedWhiteBlue")
},
"normalization": {
"type": NormalizationType.Limits,
"limits": {
"min": -1,
"max": 1
}
},
"plot": {
"type": {
"wiggle": true,
"negativecolorfill": true,
"positivecolorfill": true
},
"decimationspacing": 5
}
});
const widget = createWidget(positiveNegativeWigglePipeline);
const pipeline = widget.getPipeline();
pipeline.getColorMap().setTraceStatusLineStyle(Status.Highlighted, new LineStyle({
"color": "green",
"width": 2,
"pattern": Patterns.DashDot
}));
pipeline.setTraceStatus(5, Status.Highlighted);
widget.getToolByName("pick").setPointerMode(PointerMode.Click).on(SelectionEvents.onPick, (evt, sender, event) => {
const pipeline2 = widget.getPipeline();
const traceId = Math.round(sender.getManipulatorLayer().getSceneTransform().inverseTransform(event.getPlotPoint()).getX()) - 1;
const status = pipeline2.getTraceStatus(traceId);
if (status === Status.Highlighted) {
pipeline2.setTraceStatus(traceId, Status.Normal);
} else {
pipeline2.setTraceStatus(traceId, Status.Highlighted);
}
});
return new Plot({
"canvaselement": canvas,
"root": widget
});
}
export { createScene };
createScene(document.querySelector('[ref="plot"]'));