{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-guides/sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":["tabs","tab"]},"type":"markdown"},"seo":{"title":"Seismic Map Image","description":"Accelerate E&P application development and protect your innovation by consuming our Data and Domain APIs / Platform APIs.","lang":"en-US","meta":[{"name":"robots","content":"noindex"}],"llmstxt":{"hide":true,"excludeFiles":[]}},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"seismic-map-image","__idx":0},"children":["Seismic Map Image"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This tutorial demonstrates how to create a basemap display using ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SeismicImage"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["AnnotatedWidget"]},". The seismic image is a shape that represents a result of seismic data processing and is used as a part of ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SeismicViewWidget"]},". In most cases it is enough to use widget directly, but sometimes it is necessary to create a more complex display like base map, where seismic can be located at some angle and position inside the display."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"creating-a-seismic-image","__idx":1},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"#/Seismic/ImagesAndLayers/seismicMapImage#Image"},"children":["#"]}," Creating a Seismic Image"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The first step is to create an image with empty pipeline. The data and pipeline will be set later. Instructions on how to initialize a pipeline and connect a reader can be found in ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"#/Seismic/gettingStarted"},"children":["Seismic Widget"]}," tutorial. The seismic image is created using ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"#/doc/classes/geotoolkit.seismic.image.seismicimage.seismicimage.html"},"children":["geotoolkit/seismic/image/SeismicImage()"]}," and ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"#/doc/classes/geotoolkit.seismic.data.memoryreader.memoryreader.html"},"children":["geotoolkit/seismic/data/MemoryReader()"]},". The code below creates an empty image with a background and outlines. Here, the seismic image uses data limits from 0 to 1 in both directions as placeholders which are updated later to the real data limits."]},{"$$mdtype":"Tag","name":"Tabs","attributes":{"size":"medium"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"creating-a-seismic-layer","__idx":2},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"#/Seismic/ImagesAndLayers/seismicMapImage#Layer"},"children":["#"]}," Creating a Seismic Layer"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The next step is to add the created image to a group with axes and specify its location in the basemap. The code below shows the initialization of the group. The image and axes are added to this group with inner limits equal to seismic data limits (using the method setModelLimits) and outer limits in the basemap coordinates (using the method setBounds). The last line of code rotates the image and axes about 11 degrees (0.2 radians)."]},{"$$mdtype":"Tag","name":"Tabs","attributes":{"size":"medium"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"creating-a-widget","__idx":3},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"#/Seismic/ImagesAndLayers/seismicMapImage#Widget"},"children":["#"]}," Creating a Widget"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The next step is to create a widget with a seismic layer. An ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["AnnotatedWidget"]}," is used, which has a center part to display a seismic layer and other possible layers and a set of annotations on each side to display axes, titles, or a colorbar. The following code demonstrates this step of adding an image as a layer to the model and passing this model to a new instance of the widget."]},{"$$mdtype":"Tag","name":"Tabs","attributes":{"size":"medium"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"set-seismic-data","__idx":4},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"#/Seismic/ImagesAndLayers/seismicMapImage#Data"},"children":["#"]}," Set Seismic Data"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The next step is to load seismic data and set it to the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SeismicImage"]}," created before, using a reader and pipeline. Pass the created memory reader, which loads meta data and statistics and sets the real trace and samples count to image. This code also modifies axes limits to reflect seismic data limits."]},{"$$mdtype":"Tag","name":"Tabs","attributes":{"size":"medium"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"result","__idx":5},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"#/Seismic/ImagesAndLayers/seismicMapImage#Result"},"children":["#"]}," Result"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The canvas below shows a result of the visualization."]},{"$$mdtype":"Tag","name":"Tabs","attributes":{"size":"medium"},"children":[{"$$mdtype":"Tag","name":"div","attributes":{"label":"main","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"ts","header":{"controls":{"copy":{}}},"source":"import { Plot } from \"@int/geotoolkit/plot/Plot.ts\";\nimport { SeismicImage } from \"@int/geotoolkit/seismic/image/SeismicImage.ts\";\nimport { AnchorType } from \"@int/geotoolkit/util/AnchorType.ts\";\nimport { Orientation } from \"@int/geotoolkit/util/Orientation.ts\";\nimport { LabelPosition, TickPosition } from \"@int/geotoolkit/axis/TickInfo.ts\";\nimport { Axis } from \"@int/geotoolkit/axis/Axis.ts\";\nimport { AnnotatedWidget } from \"@int/geotoolkit/widgets/AnnotatedWidget.ts\";\nimport { Group } from \"@int/geotoolkit/scene/Group.ts\";\nimport { SeismicColors } from \"@int/geotoolkit/seismic/util/SeismicColors.ts\";\nimport { SeismicPipeline } from \"@int/geotoolkit/seismic/pipeline/SeismicPipeline.ts\";\nimport { Rect } from \"@int/geotoolkit/util/Rect.ts\";\nimport { MemoryReader } from \"@int/geotoolkit/seismic/data/MemoryReader.ts\";\nimport { MathUtil } from \"@int/geotoolkit/util/MathUtil.ts\";\nclass Plasma {\n  constructor() {\n  }\n  getPoints(width, height, rough) {\n    const p1 = MathUtil.getSeededRandom(0, 1, 16), p2 = MathUtil.getSeededRandom(0, 1, 16), p3 = MathUtil.getSeededRandom(0, 1, 16), p4 = MathUtil.getSeededRandom(0, 1, 16);\n    const points = [];\n    for (let x = 0; x < width; x++) {\n      points[x] = [];\n    }\n    this.roughness = rough;\n    this.totalSize = width + height;\n    this.splitRect(points, 0, 0, width, height, p1, p2, p3, p4);\n    return points;\n  }\n  splitRect(points, x, y, width, height, p1, p2, p3, p4) {\n    let side1, side2, side3, side4, center;\n    const transWidth = ~~(width / 2);\n    const transHeight = ~~(height / 2);\n    if (width > 1 || height > 1) {\n      center = (p1 + p2 + p3 + p4) / 4;\n      center += this.shift(transWidth + transHeight);\n      side1 = (p1 + p2) / 2;\n      side2 = (p2 + p3) / 2;\n      side3 = (p3 + p4) / 2;\n      side4 = (p4 + p1) / 2;\n      center = this.normalize(center);\n      side1 = this.normalize(side1);\n      side2 = this.normalize(side2);\n      side3 = this.normalize(side3);\n      side4 = this.normalize(side4);\n      this.splitRect(points, x, y, transWidth, transHeight, p1, side1, center, side4);\n      this.splitRect(points, x + transWidth, y, width - transWidth, transHeight, side1, p2, side2, center);\n      this.splitRect(points, x + transWidth, y + transHeight, width - transWidth, height - transHeight, center, side2, p3, side3);\n      this.splitRect(points, x, y + transHeight, transWidth, height - transHeight, side4, center, side3, p4);\n    } else {\n      points[x][y] = (p1 + p2 + p3 + p4) / 4;\n    }\n  }\n  normalize(val) {\n    return val < 0 ? 0 : val > 1 ? 1 : val;\n  }\n  shift(smallSize) {\n    return (MathUtil.getSeededRandom(0, 1, 16) - 0.5) * smallSize / this.totalSize * this.roughness;\n  }\n}\nlet seismicImage = null;\nlet xLineAxis = null;\nlet inLineAxis = null;\nclass PlasmaProcessor {\n  constructor(tracesCount, samplesPerTrace) {\n    this.plasma = new Plasma();\n    this.points = this.plasma.getPoints(tracesCount, samplesPerTrace, 10);\n    this.min = Number.POSITIVE_INFINITY;\n    this.max = Number.NEGATIVE_INFINITY;\n    this.average = 0;\n    this.rms = 0;\n    for (let x = 0; x < tracesCount; x++) {\n      for (let y = 0; y < samplesPerTrace; y++) {\n        const value = this.points[x][y];\n        this.average += value;\n        this.rms += value * value;\n        this.min = Math.min(this.min, value);\n        this.max = Math.max(this.max, value);\n      }\n    }\n    this.average = this.average / (tracesCount * samplesPerTrace);\n    this.rms = Math.sqrt(this.rms / (tracesCount * samplesPerTrace));\n  }\n  getDataStatistics(reader) {\n    return {\n      \"average\": this.average,\n      \"min\": this.min,\n      \"max\": this.max,\n      \"rms\": this.rms\n    };\n  }\n  getTraceData(reader, samples, traceId) {\n    for (let i = 0; i < reader.getNumberOfSamples(); i++) {\n      samples[i] = this.points[traceId][i];\n    }\n  }\n}\nfunction getPlasmaMemoryReader(tracesCount, samplesPerTrace, height) {\n  return new MemoryReader({\n    \"numberoftraces\": tracesCount,\n    \"numberofsamples\": samplesPerTrace,\n    \"samplerate\": height / samplesPerTrace\n  }).setTraceProcessor(new PlasmaProcessor(tracesCount, samplesPerTrace));\n}\nfunction setSeismicData(seismicReader) {\n  seismicReader.loadMetaData((reader) => {\n    reader.readDataSetStatistics((reader2, statistics) => {\n      const deviceBounds = seismicImage.getSceneTransform().transformRect(seismicImage.getBounds());\n      const toTrace = Math.min(deviceBounds.getWidth(), reader2.getNumberOfTraces());\n      const sampleRate = reader2.getSampleRate();\n      const samplesAmount = reader2.getNumberOfSamples();\n      const toSamples = Math.min(2 * deviceBounds.getHeight() * sampleRate, samplesAmount * sampleRate);\n      xLineAxis.setModelLimits(xLineAxis.getModelLimits().clone().setHeight(toSamples - 1).setY(1));\n      inLineAxis.setModelLimits(inLineAxis.getModelLimits().clone().setWidth(toTrace - 1).setX(1));\n      seismicImage.setModelLimits(new Rect(0, 0, toTrace, toSamples)).setPipeline(new SeismicPipeline({\n        \"name\": \"seismic\",\n        \"reader\": reader2,\n        \"statistics\": statistics\n      }).setColorMap(SeismicColors.getDefault().createNamedColorMap(\"Saddleback\", 32)).setOptions({\n        \"plot\": {\n          \"type\": {\n            \"wiggle\": false,\n            \"interpolateddensity\": true\n          }\n        },\n        \"colors\": {\n          \"opacity\": 0.5\n        }\n      }));\n    });\n  });\n}\nfunction createWidget(image, limits) {\n  let axisSouth, axisWest;\n  const model = new Group().addChild([\n    image\n  ]).setModelLimits(limits).setBounds(limits).setVerticalFlip(true);\n  const widget = new AnnotatedWidget({\n    \"model\": model,\n    \"annotationssizes\": {\n      \"north\": \"5\",\n      \"south\": \"60\",\n      \"east\": \"12\",\n      \"west\": \"60\"\n    },\n    \"north\": [],\n    \"east\": [],\n    \"south\": [\n      axisSouth = new Axis({\n        \"tickposition\": TickPosition.Top,\n        \"orientation\": Orientation.Horizontal,\n        \"title\": {\n          \"text\": \"X Axis\",\n          \"visible\": true,\n          \"alignment\": AnchorType.BottomCenter,\n          \"textstyle\": {\n            \"color\": \"#757575\"\n          }\n        }\n      })\n    ],\n    \"west\": [\n      axisWest = new Axis({\n        \"tickposition\": TickPosition.Right,\n        \"labelposition\": LabelPosition.Right,\n        \"orientation\": Orientation.Vertical,\n        \"title\": {\n          \"text\": \"Y Axis\",\n          \"visible\": true,\n          \"alignment\": AnchorType.LeftCenter,\n          \"textstyle\": {\n            \"color\": \"#757575\"\n          }\n        }\n      })\n    ],\n    \"tools\": {\n      \"horizontalscroll\": {\n        \"visible\": false\n      },\n      \"verticalscroll\": {\n        \"visible\": false\n      }\n    }\n  }).connect(axisWest, model).connect(axisSouth, model).refreshLayout();\n  return widget;\n}\nfunction createImage() {\n  return new SeismicImage(null, new Rect(0, 0, 1, 1));\n}\nfunction createMap(bounds) {\n  const center = bounds.getCenter();\n  const seismicBounds = bounds.clone().inflate(-70, -70);\n  const depthAxisBounds = new Rect(seismicBounds.getX() - 50, seismicBounds.getTop(), seismicBounds.getX(), seismicBounds.getBottom());\n  const tickAxisBounds = new Rect(seismicBounds.getLeft(), seismicBounds.getY() - 40, seismicBounds.getRight(), seismicBounds.getX());\n  const group = new Group().setBounds(bounds.clone()).setModelLimits(bounds.clone()).addChild([\n    new Group().setBounds(seismicBounds).setModelLimits(new Rect(0, 0, 1, 1)).addChild([\n      seismicImage = createImage()\n    ]),\n    xLineAxis = new Axis().setBounds(depthAxisBounds).setModelLimits(new Rect(0, 0, 1, 100)).setBaseLineStyle(null).setTickPosition(TickPosition.Right),\n    inLineAxis = new Axis().setBounds(tickAxisBounds).setModelLimits(new Rect(0, 0, 200, 1)).setBaseLineStyle(null).setTickPosition(TickPosition.Bottom).setOrientation(Orientation.Horizontal)\n  ]).rotate(0.2, center.getX(), center.getY());\n  return group;\n}\nfunction createScene(canvas) {\n  const map = createMap(new Rect(0, 0, 500, 450));\n  const widget = createWidget(map, new Rect(0, 0, 800, 450));\n  setSeismicData(getPlasmaMemoryReader(149, 500, 80));\n  const plot = new Plot({\n    \"canvaselement\": canvas,\n    \"infiniteautoupdate\": true,\n    \"root\": widget\n  });\n  return plot;\n}\nexport { createScene };\n\ncreateScene(document.querySelector('[ref=\"plot\"]'));\n\n","lang":"ts"},"children":[]}]},{"$$mdtype":"Tag","name":"div","attributes":{"label":"css","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"css","header":{"controls":{"copy":{}}},"source":"\n.cg-tooltip-holder {\n  position: relative;\n}\n\n.cg-tooltip {\n  position: absolute;\n  display: block;\n  padding: 2px 12px 3px 7px;\n  overflow: visible !important;\n  font-family: Roboto, Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  background: white !important;\n  opacity: 0.9;\n  color: #333333;\n  border: solid 1px gray;\n  border-radius: 5px;\n  text-align: left;\n  box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);\n  border-radius: 5px;\n  margin: 0 !important;\n  z-index: 10000;\n  max-width: 400px;\n  text-wrap: normal !important;\n  white-space: normal !important;\n}\n/* Default setting for tooltip */\n.cg-tooltip-container {\n  position: absolute;\n  display: block;\n  overflow: visible !important;\n  font-family: Roboto, Helvetica, Arial, sans-serif;\n  font-size: 12px;\n  padding: 3px 7px;\n  background: #f7f7f7;\n  color: #333333;\n  border: 1px solid #938e8e;\n  opacity: 0.8;\n  text-align: left;\n  box-shadow: 3px 3px 10px #888;\n  margin: 0 !important;\n  z-index: 10000;\n  max-width: 400px;\n  text-wrap: normal !important;\n  white-space: normal !important;\n  user-select: none;\n}\n@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {\n  .cg-tooltip-container {\n    border-radius: 0;\n  }\n}\n/* Default left arrow for tooltip */\n.cg-tooltip-arrow-left::before {\n  content: '';\n  position: absolute;\n  display: block;\n  width: 0px;\n  left: 0;\n  top: 50%;\n  border: 5px solid transparent;\n  border-left: 0;\n  border-right: 5px solid  #938e8e;\n  transform: translate(calc(-100%), -50%);\n}\n.cg-tooltip-arrow-left::after {\n  content: '';\n  position: absolute;\n  display: block;\n  width: 0px;\n  left: 0;\n  top: 50%;\n  border: 4px solid transparent;\n  border-left: 0;\n  border-right: 4px solid #f7f7f7;\n  transform: translate(calc(-100%), -50%);\n}\n/* Default top arrow for tooltip */\n.cg-tooltip-arrow-top::before {\n  content: '';\n  position: absolute;\n  display: block;\n  width: 0px;\n  left: 50%;\n  top: 0;\n  border: 5px solid transparent;\n  border-top: 0;\n  border-bottom: 5px solid #938e8e;\n  transform: translate(-50%, -100%);\n}\n.cg-tooltip-arrow-top::after {\n  content: '';\n  position: absolute;\n  display: block;\n  width: 0px;\n  left: 50%;\n  top: 0;\n  border: 4px solid transparent;\n  border-top: 0;\n  border-bottom: 4px solid #f7f7f7;\n  transform: translate(-50%, -100%);\n}\n/* Default right arrow for tooltip */\n.cg-tooltip-arrow-right::before {\n  content: '';\n  position: absolute;\n  display: block;\n  width: 0px;\n  right: 0;\n  top: 50%;\n  border: 5px solid transparent;\n  border-right: 0;\n  border-left: 5px solid #938e8e;\n  transform: translate(100%, -50%);\n}\n.cg-tooltip-arrow-right::after {\n  content: '';\n  position: absolute;\n  display: block;\n  width: 0px;\n  right: 0;\n  top: 50%;\n  border: 4px solid transparent;\n  border-right: 0;\n  border-left: 4px solid #f7f7f7;\n  transform: translate(100%, -50%);\n}\n/* Default bottom arrow for tooltip */\n.cg-tooltip-arrow-bottom::before {\n  content: '';\n  position: absolute;\n  display: block;\n  width: 0px;\n  left: 50%;\n  bottom: 0px;\n  border: 5px solid transparent;\n  border-bottom: 0;\n  border-top: 5px solid #938e8e;\n  transform: translate(-50%, 100%);\n  z-index: 10000;\n}\n.cg-tooltip-arrow-bottom::after {\n  content: '';\n  position: absolute;\n  display: block;\n  width: 0px;\n  left: 50%;\n  bottom: 0;\n  border: 4px solid transparent;\n  border-bottom: 0;\n  border-top: 4px solid #f7f7f7;\n  transform: translate(-50%, 100%);\n  z-index: 10000;\n}\n/* Tooltip item name */\n/* Tooltip item value */\n/* .cg-tooltip-item-value */\n/* Tooltip item value */\n.cg-tooltip-item-unit {\n  text-transform: none;\n}\n\n.cg-tooltip-item-name {\n    text-transform: capitalize;\n    white-space: nowrap;\n    vertical-align: middle;\n    font-size: 13px;\n}\n.cg-tooltip-row {\n  display: flex;\n  flex-direction: row;\n  align-items: center;\n  white-space: pre-wrap;\n  font-size: 12px;\n  line-height: 100%;\n  margin: 1px 0;\n}\n.cg-tooltip-title {\n  font-size: 13px;\n  height: 14px;\n  text-transform: capitalize;\n}\n.cg-tooltip-title .cg-tooltip-symbol {\n  margin-right: 0 !important;\n}\n.cg-tooltip-title-name {\n  vertical-align: middle;\n}\n.cg-tooltip-row + .cg-tooltip-row {\n  margin-top: 4px;\n}\n.cg-tooltip-row.cg-tooltip-title + .cg-tooltip-row {\n  margin-top: 5px;\n}\n.cg-tooltip-item-value + .cg-tooltip-item-unit {\n    margin-left: 1px;\n}\n/* Tooltip symbol */\n.cg-tooltip-symbol-cell {\n  display: inline-flex;\n  min-width: 13px; /* 10px size + 3px margin */\n}\n.cg-tooltip-symbol {\n  margin-right: 3px;\n  background-color: transparent;\n  display: block;\n}\n.cg-tooltip-symbol > img {\n  display: block;\n}\n.cg-tooltip-list-cell {\n  display: inline-flex;\n}\n.cg-tooltip-list-symbol {\n  display: block;\n  margin-right: 3px;\n  width: 6px;\n  height: 6px;\n  vertical-align: middle;\n  border-radius: 50%;\n  border: 1px solid rgba(0,0,0,.4);\n}\n.cg-tooltip-symbol-legacy {\n  border-radius: 4px;\n  margin-right: 5px;\n  height: 8px;\n  width: 8px;\n  display: inline-block;\n}\n.cg-tooltip-title-legacy {\n  font-weight: 900;\n}\n\n/* Tooltip symbol circle */\n.cg-tooltip-symbol.circle {\n  height: 10px;\n  width: 10px;\n  display: inline-block;\n  border-radius: 50%;\n  border: 1px solid rgba(0,0,0,.4);\n}\n/* Tooltip symbol line */\n.cg-tooltip-symbol.line {\n    height: 10px;\n    width: 10px;\n    display: inline-block;\n    transform: scale(1.2, 0.2);\n}\n/* Tooltip symbol diamond */\n.cg-tooltip-symbol.diamond {\n    height: 10px;\n    width: 10px;\n    display: inline-block;\n    transform: rotate(45deg);\n    border-radius: 0px;\n}\n/* Tooltip symbol square */\n.cg-tooltip-symbol.square {\n    height: 10px;\n    width: 10px;\n    display: inline-block;\n    border-radius: 0px;\n    border: 1px solid rgba(0,0,0,.4);\n}\n\n","lang":"css"},"children":[]}]}]},{"$$mdtype":"Tag","name":"iframe","attributes":{"src":"https://dc2-documentation.s3.amazonaws.com/documentation/slb-docs-test/5.0/examples/vue/tutorials/index.html#/Seismic/ImagesAndLayers/seismicMapImage?section=Result&extract=true","width":"100%","height":"588.5px","style":{"border":"none"}},"children":[]}]},"headings":[{"value":"Seismic Map Image","id":"seismic-map-image","depth":1},{"value":"Creating a Seismic Image","id":"creating-a-seismic-image","depth":3},{"value":"Creating a Seismic Layer","id":"creating-a-seismic-layer","depth":3},{"value":"Creating a Widget","id":"creating-a-widget","depth":3},{"value":"Set Seismic Data","id":"set-seismic-data","depth":3},{"value":"Result","id":"result","depth":3}],"frontmatter":{"title":"Seismic Map Image","seo":{"title":"Seismic Map Image"}},"lastModified":"2026-02-11T19:54:32.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/solutions/geotoolkit/tutorials/seismic/images-and-layers/seismic-map-image","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}