Last updated

Seismic Layers

This tutorial provides a way to compare two different seismic layers on the same plot using the Comparator tool geotoolkit/seismic/widgets/tools/Comparator.

# Creating Layers

This tutorial shows how to create different layers within a plot. The following example uses geotoolkit/scene/Group to group layers as necessary. The position of the images can be changed with changeChildOrder() which organizes all the indexes of a group.

# Comparing Seismic Plots using Layers

The following example uses RemoteSeismicReader to read data from the server. It retrieves a slice of one inline data set from the server and displays it with SeismicWidget. To display a second seismic plot in the widget, create an additional pipeline by using the clone() method. The Comparator tool is then initialized for the widget.

# Layer Orientation

The layer orientation can be specified using the setOrientation method.

# Layer Transparency

The layer transparency can be specified using the setOptions method on the pipeline.

# Source code

import { Orientation } from "@int/geotoolkit/util/Orientation.ts";
import { NodeOrder } from "@int/geotoolkit/scene/CompositeNode.ts";
import { SeismicImage } from "@int/geotoolkit/seismic/image/SeismicImage.ts";
import { Plot } from "@int/geotoolkit/plot/Plot.ts";
import { SeismicWidget } from "@int/geotoolkit/seismic/widgets/SeismicWidget.ts";
import { SeismicColors } from "@int/geotoolkit/seismic/util/SeismicColors.ts";
import { NormalizationType } from "@int/geotoolkit/seismic/pipeline/NormalizationType.ts";
import { SeismicPipeline } from "@int/geotoolkit/seismic/pipeline/SeismicPipeline.ts";
import { RemoteSeismicDataSource } from "@int/geotoolkit/seismic/data/RemoteSeismicDataSource.ts";
const plots = [];
function createSectionQuery(position, key, oppositeKey) {
  const selectKeys = [];
  selectKeys[0] = {
    "name": key["key"],
    "min": position,
    "max": position,
    "step": key["increment"],
    "order": "asc"
  };
  selectKeys[1] = {
    "name": oppositeKey["key"],
    "min": oppositeKey["min"],
    "max": oppositeKey["max"],
    "step": oppositeKey["increment"],
    "order": "asc"
  };
  return {
    "keys": selectKeys,
    "options": null,
    "emptyTracesKey": {
      "name": oppositeKey["key"],
      "min": oppositeKey["min"],
      "max": oppositeKey["max"]
    }
  };
}
const createReader = function(options, onready, onfailure) {
  const data = new RemoteSeismicDataSource({
    "host": options["host"],
    "file": options["source"],
    "version": 2
  });
  data.open(
    () => {
      const keys = data.getKeys();
      const key = keys[0];
      const oppositeKey = keys[1];
      const query = createSectionQuery(options["inline"], key, oppositeKey);
      data.select(query, onready, onfailure);
    },
    onfailure
  );
};
const createPipeline = function(reader) {
  return new SeismicPipeline({
    "name": "Seismic",
    "reader": reader,
    "statistics": reader.getStatistics()
  }).setOptions({
    "normalization": {
      "type": NormalizationType.RMS,
      "scale": 0.4
    },
    "plot": {
      "type": {
        "wiggle": false,
        "interpolateddensity": true
      },
      "decimationspacing": 5
    },
    "colors": {
      "colormap": SeismicColors.getDefault().createNamedColorMap("WhiteBlack", 32)
    }
  });
};
function initializeLayerTool(widget, pipeline) {
  pipeline = pipeline.clone().setOptions({
    "normalization": {
      "type": NormalizationType.RMS,
      "scale": 0.4
    },
    "plot": {
      "type": {
        "wiggle": false,
        "interpolateddensity": true
      },
      "decimationspacing": 5
    },
    "colors": {
      "colormap": SeismicColors.getDefault().createNamedColorMap("BlackRedYellowWhite", 32),
      "opacity": 1
    }
  });
  return widget.getToolByName("comparator").setEnabled(true).setPipeline(pipeline);
}
function createWidget(canvas, pipeline, secondPipeline) {
  const widget = new SeismicWidget({
    "pipeline": pipeline,
    "colorbar": {
      "axis": {
        "tickgenerator": {
          "edge": {
            "tickvisible": false,
            "labelvisible": false
          }
        }
      }
    },
    "layouttype": "inside",
    "statusbar": {
      "visible": false
    }
  }).setScaleOptions({
    "tracescale": 20,
    "samplescale": 200,
    "deviceunit": "in",
    "sampleunit": "ft"
  });
  const headerFields = pipeline.getReader().getTraceHeaderFields();
  let header, headerInfo;
  for (let i = 0; i < headerFields.length; i++) {
    header = headerFields[i];
    if (header.getName() === "XLINE") {
      widget.setTraceHeaderVisible(header, true);
    } else if (header.getName() === "TraceNumber") {
      widget.setTraceHeaderVisible(header, false);
    }
    headerInfo = widget.getTraceHeaderAxis(header);
    if (headerInfo) {
      headerInfo["label"].getTextStyle().setColor("#6b6b6b");
    }
  }
  if (secondPipeline) {
    initializeLayerTool(widget, secondPipeline);
  }
  plots.push(new Plot({
    "canvaselement": canvas,
    "root": widget
  }));
  return widget;
}
let firstSeismicImage, secondSeismicImage, layeredWidget;
function createSeismicLayers(reader, canvas) {
  const pipeline = createPipeline(reader);
  pipeline.setOptions({ "colors": {
    "colormap": SeismicColors.getDefault().createNamedColorMap("BlackRedYellowWhite", 32)
  } });
  const secondPipeline = createPipeline(reader);
  secondPipeline.setOptions({ "plot": {
    "type": {
      "wiggle": true,
      "interpolateddensity": false,
      "simpledensity": false
    },
    "decimationspacing": 5
  } });
  const modelLimits = secondPipeline.getModelLimits();
  layeredWidget = createWidget(canvas, pipeline);
  layeredWidget.setOptions({
    "autoseismiclimits": false
  });
  layeredWidget.setSeismicModelLimits(modelLimits);
  firstSeismicImage = layeredWidget.getSeismicImage();
  firstSeismicImage.setBounds(modelLimits);
  const parentSeismicGroup = layeredWidget.getSeismicModel();
  secondSeismicImage = new SeismicImage(secondPipeline);
  secondSeismicImage.setBounds(modelLimits);
  parentSeismicGroup.addChild(secondSeismicImage);
}
function toggleOrder() {
  if (firstSeismicImage && secondSeismicImage) {
    const parentSeismicGroup = layeredWidget.getSeismicModel();
    parentSeismicGroup.changeChildOrder(
      firstSeismicImage,
      parentSeismicGroup.indexOfChild(secondSeismicImage) > parentSeismicGroup.indexOfChild(firstSeismicImage) ? NodeOrder.Forward : NodeOrder.Backward
    );
  }
}
function initialize(transparentLayer, verticalComparison, horizontalComparison, transparentComparison) {
  const MAJOR_INLINE = 1;
  const MINOR_INLINE = 25;
  const DATA_HOST = "https://demo.int.com/INTGeoServer/json";
  const DATA_SOURCE = "data/seismic/Gullfaks_Amplitude.xgy";
  createReader({
    "host": DATA_HOST,
    "source": DATA_SOURCE,
    "inline": MAJOR_INLINE
  }, (reader) => {
    createReader({
      "host": DATA_HOST,
      "source": DATA_SOURCE,
      "inline": MINOR_INLINE
    }, (secondReader) => {
      let pipeline = createPipeline(reader);
      const secondPipeline = createPipeline(secondReader);
      createSeismicLayers(reader, transparentLayer);
      createWidget(verticalComparison, pipeline, secondPipeline);
      createWidget(horizontalComparison, pipeline, secondPipeline).getToolByName("comparator").setOrientation(Orientation.Horizontal);
      const widget = createWidget(transparentComparison, pipeline, secondPipeline);
      pipeline = widget.getPipeline().clone().setOptions({
        "colors": {
          "colormap": SeismicColors.getDefault().createNamedColorMap("RedWhiteBlack", 32)
        }
      });
      widget.setPipeline(pipeline);
      const comparator = widget.getToolByName("comparator").setSplit(false).setContinuous(true);
      comparator.getPipeline().setOptions({
        "plot": {
          "type": {
            "wiggle": true,
            "interpolateddensity": false
          }
        },
        "colors": {
          "colormap": SeismicColors.getDefault().createNamedColorMap("BlackRedYellowWhite", 32),
          "opacity": 0.5
        }
      });
    }, (error) => {
      alert(error);
    });
  }, (error) => {
    alert(error);
  });
}
function dispose() {
  plots.forEach((plot) => plot.dispose());
}
export { dispose, initialize, toggleOrder };

createScene();