Last updated

Variable Trace Spacing

This Seismic Variable Trace Spacing tutorial demonstrates how to integrate variable trace spacing into the Seismic Pipeline.
The first step is to initialize the Seismic Widget. In the example below, variable trace spacing is checked.

# Create a Trace Mapping

To visualize variable trace spacing, the data series with the position of each trace in the model coordinates of the pipeline must be passed. The data series should be passed to the pipeline via the setOptions orsetTraceMapping method after initialization. If trace spacing is enabled, trace decimation is automatically disabled.

# Result

import { AnnotationLocation } from "@int/geotoolkit/layout/AnnotationLocation.ts";
import { DisplayValueType } from "@int/geotoolkit/seismic/axis/IndexTickGenerator.ts";
import { ManipulatorType } from "@int/geotoolkit/seismic/widgets/SeismicViewWidget.ts";
import { SeismicWidget } from "@int/geotoolkit/seismic/widgets/SeismicWidget.ts";
import { InterpolationEdge } from "@int/geotoolkit/seismic/pipeline/InterpolationEdge.ts";
import { InterpolationType } from "@int/geotoolkit/seismic/pipeline/InterpolationType.ts";
import { NormalizationType } from "@int/geotoolkit/seismic/pipeline/NormalizationType.ts";
import { SeismicColors } from "@int/geotoolkit/seismic/util/SeismicColors.ts";
import { VSTraceMapping } from "@int/geotoolkit/seismic/data/VSTraceMapping.ts";
import { NumericalDataSeries } from "@int/geotoolkit/data/NumericalDataSeries.ts";
import { SeismicPipeline } from "@int/geotoolkit/seismic/pipeline/SeismicPipeline.ts";
import { MemoryReader } from "@int/geotoolkit/seismic/data/MemoryReader.ts";
import { Plot } from "@int/geotoolkit/plot/Plot.ts";
import { Events as RubberBandEvents } from "@int/geotoolkit/controls/tools/RubberBand.ts";
const traceCount = 500;
let mapping;
const createReader = function() {
  const sampleRate = 1;
  const sampleCount = 600;
  const reader = new MemoryReader({
    "numberoftraces": traceCount,
    "numberofsamples": sampleCount,
    "samplerate": sampleRate
  }).setTraceProcessor({
    "getTraceData": function(reader2, trace, traceId) {
      for (let i = 0; i < sampleCount; i++) {
        trace[i] = Math.sin((i / 10 + traceId / 4) * Math.PI) * 0.5;
      }
    },
    "getDataStatistics": function() {
      return {
        "average": 0,
        "min": -0.5,
        "max": 0.5,
        "rms": Math.sqrt(2) / 2
      };
    }
  });
  return reader;
};
const createPipeline = function(reader) {
  const pipeline = new SeismicPipeline({
    "name": "MemorySeismic",
    "reader": reader,
    "statistics": reader.getStatistics()
  });
  const positions = new NumericalDataSeries();
  let pos = 15;
  for (let i = 0; i < traceCount; i++) {
    positions.addValue(pos);
    if (i !== 0 && i % 10 === 0) {
      pos += 5.5;
    } else {
      pos += 1.1;
    }
    pos = Math.round(pos * 10) / 10;
  }
  mapping = new VSTraceMapping(pipeline, positions, 0.4);
  const colorProvider = SeismicColors.getDefault();
  pipeline.setOptions({
    "colors": {
      "colormap": colorProvider.createNamedColorMap("RedWhiteBlack")
    },
    "normalization": {
      "scale": 1,
      "type": NormalizationType.Limits,
      "limits": {
        "min": -0.5,
        "max": 0.5
      }
    },
    "plot": {
      "type": {
        "wiggle": true,
        "negativecolorfill": false,
        "positivecolorfill": false,
        "interpolateddensity": true,
        "simpledensity": false
      },
      "decimationspacing": 1
    },
    "tracemapping": mapping,
    "traceoffset": 10,
    "interpolation": {
      "samples": {
        "type": InterpolationType.Quadratic,
        "edge": InterpolationEdge.Duplicate
      },
      "traces": {
        "type": InterpolationType.Quadratic,
        "edge": InterpolationEdge.Duplicate
      }
    }
  });
  return pipeline;
};
function createWidget(pipeline) {
  const widget = new SeismicWidget({
    "pipeline": pipeline,
    "colorbar": {
      "axis": {
        "tickgenerator": {
          "edge": {
            "tickvisible": false,
            "labelvisible": false
          }
        }
      }
    },
    "layouttype": "inside",
    "statusbar": {
      "visible": true
    }
  }).setScaleOptions({
    "tracescale": 3,
    "samplescale": 30,
    "deviceunit": "in",
    "sampleunit": "ms"
  });
  return widget;
}
function setVariableTraceMappingEnabled(plot, enable) {
  const widget = plot.getRoot();
  const modelLimits = widget.getSeismicModelLimits();
  const visibleModelLimits = widget.getVisibleSeismicModelLimits();
  const pipeline = widget.getPipeline();
  pipeline.setTraceMapping(enable ? mapping : null);
  if (modelLimits.getLeft() === visibleModelLimits.getLeft()) {
    const adjustLimits = widget.getVisibleSeismicModelLimits().clone().setX(widget.getSeismicModelLimits().getLeft());
    widget.setVisibleSeismicModelLimits(adjustLimits);
  }
}
function setDistanceInsteadNumberEnabled(plot, enable) {
  const widget = plot.getRoot();
  const axisInfo = widget.getTraceHeaderAxis("TraceNumber");
  if (axisInfo == null)
    return;
  if (enable) {
    axisInfo["axis"].getTickGenerator().setDisplayValueType(DisplayValueType.Mapped);
    axisInfo["label"].setText("Distance");
  } else {
    axisInfo["axis"].getTickGenerator().setDisplayValueType(DisplayValueType.Original);
    axisInfo["label"].setText("Trace #");
  }
  axisInfo["axis"].invalidate();
}
function setTracePositionsOnlyEnabled(plot, enable) {
  const widget = plot.getRoot();
  widget.getPipeline().setOptions({
    "normalization": {
      "scale": enable ? 0 : 1
    }
  });
  widget.setOptions({
    "colorbar": {
      "visible": !enable
    },
    "annotationssizes": {
      "west": enable ? widget.getAnnotation(AnnotationLocation.West).getBounds().getWidth() : "auto"
    }
  });
}
function activateRubberBandZoom(plot) {
  const widget = plot.getRoot();
  widget.setManipulatorType(ManipulatorType.RubberBand);
}
function resetRubberBandZoom(plot) {
  const widget = plot.getRoot();
  widget.resetZoom();
  widget.setScaleOptions({
    "tracescale": 3,
    "samplescale": 30,
    "deviceunit": "in",
    "sampleunit": "ms"
  });
  widget.setManipulatorType(ManipulatorType.Panning);
}
function createScene(canvas, cb) {
  const reader = createReader();
  const pipeline = createPipeline(reader);
  const widget = createWidget(pipeline);
  widget.getToolByName("rubberband").on(RubberBandEvents.onZoomEnd, cb);
  if (widget.getTraceHeaderAxis("TraceNumber") != null) {
    widget.getTraceHeaderAxis("TraceNumber")["axis"].getTickGenerator().setMinimumSpan(30);
  }
  return new Plot({
    "canvaselement": canvas,
    "root": widget
  });
}
export {
  activateRubberBandZoom,
  createScene,
  resetRubberBandZoom,
  setDistanceInsteadNumberEnabled,
  setTracePositionsOnlyEnabled,
  setVariableTraceMappingEnabled
};

createScene(document.querySelector('[ref="plot"]'), () => {
            this.setRubberBandEnabled(false);
        });