{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-guides/sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":["tabs","tab"]},"type":"markdown"},"seo":{"title":"Seismic Movie Mode","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-movie-mode","__idx":0},"children":["Seismic Movie Mode"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This example shows movie mode. It is possible to navigate forwad or backward slice by slice or start automatically loading slices. \"freezeupdate\" mode in seismic widget allows keeping the current image during loading the next one. In \"Play\" mode seismic data is requested each 3 seconds."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"result","__idx":1},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"#/Seismic/Movie/movie#General"},"children":["#"]}," Result"]},{"$$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 { SeismicWidget } from \"@int/geotoolkit/seismic/widgets/SeismicWidget.ts\";\nimport { SeismicColors } from \"@int/geotoolkit/seismic/util/SeismicColors.ts\";\nimport { NormalizationType } from \"@int/geotoolkit/seismic/pipeline/NormalizationType.ts\";\nimport { SeismicPipeline } from \"@int/geotoolkit/seismic/pipeline/SeismicPipeline.ts\";\nimport { RemoteSeismicDataSource } from \"@int/geotoolkit/seismic/data/RemoteSeismicDataSource.ts\";\nimport { Events } from \"@int/geotoolkit/scene/shapes/tiledshape/Events.ts\";\nconst FrameTimeInterval = 3e3;\nconst createSectionQuery = (position, key, oppositeKey) => {\n  const selectKeys = [];\n  selectKeys[0] = {\n    \"name\": key[\"key\"],\n    \"min\": position,\n    \"max\": position,\n    \"step\": key[\"increment\"],\n    \"order\": \"asc\"\n  };\n  selectKeys[1] = {\n    \"name\": oppositeKey[\"key\"],\n    \"min\": oppositeKey[\"min\"],\n    \"max\": oppositeKey[\"max\"],\n    \"step\": oppositeKey[\"increment\"],\n    \"order\": \"asc\"\n  };\n  return {\n    \"keys\": selectKeys,\n    \"options\": null,\n    \"emptyTracesKey\": {\n      \"name\": oppositeKey[\"key\"],\n      \"min\": oppositeKey[\"min\"],\n      \"max\": oppositeKey[\"max\"]\n    }\n  };\n};\nconst createDataSource = async () => {\n  const host = \"https://demo.int.com/INTGeoServer/json\";\n  return new Promise((resolve, reject) => {\n    const data = new RemoteSeismicDataSource({\n      \"host\": host,\n      \"file\": \"data/seismic/Gullfaks_Amplitude.xgy\",\n      \"version\": 2\n    });\n    data.open(() => {\n      resolve(data);\n    }, (err) => {\n      reject(err);\n    });\n  });\n};\nconst createReader = async (data, position) => {\n  const keys = data.getKeys();\n  const key = keys[0];\n  const oppositeKey = keys[1];\n  const query = createSectionQuery(position, key, oppositeKey);\n  return new Promise((resolve, reject) => {\n    data.select(query, (reader) => {\n      resolve(reader);\n    });\n  });\n};\nconst createPipeline = function(reader) {\n  const pipeline = new SeismicPipeline({\n    \"name\": \"Seismic\",\n    \"reader\": reader,\n    \"statistics\": reader.getStatistics()\n  });\n  pipeline.setOptions({\n    \"normalization\": {\n      \"type\": NormalizationType.RMS,\n      \"scale\": 1\n    },\n    \"plot\": {\n      \"type\": {\n        \"wiggle\": false,\n        \"interpolateddensity\": true\n      },\n      \"decimationspacing\": 5\n    },\n    \"colors\": {\n      \"colormap\": SeismicColors.getDefault().createNamedColorMap(\"WhiteBlack\", 32)\n    }\n  });\n  return pipeline;\n};\nclass SeismicMovie {\n  constructor(canvas, errorObj) {\n    this.errorObj = errorObj;\n    this.lastTileRendered = true;\n    this.widget = new SeismicWidget({\n      \"colorbar\": {\n        \"axis\": {\n          \"tickgenerator\": {\n            \"edge\": {\n              \"tickvisible\": false,\n              \"labelvisible\": false\n            }\n          }\n        }\n      },\n      \"layouttype\": \"inside\",\n      \"statusbar\": {\n        \"visible\": false\n      },\n      \"table\": {\n        \"size\": 100,\n        \"visible\": false\n      },\n      \"freezeupdate\": true\n    });\n    this.plot = new Plot({\n      \"canvaselement\": canvas,\n      \"root\": this.widget\n    });\n  }\n  async create() {\n    try {\n      this.data = await createDataSource();\n      const keys = this.data.getKeys();\n      this.key = keys[0];\n      this.position = this.key[\"min\"];\n      const reader = await createReader(this.data, this.position);\n      const pipeline = createPipeline(reader);\n      this.widget.setPipeline(pipeline);\n      this.widget.on(Events.LastTileRendered, () => {\n        this.lastTileRendered = true;\n      });\n      this.widget.setScaleOptions({\n        \"tracescale\": 20,\n        \"samplescale\": 200,\n        \"deviceunit\": \"in\",\n        \"sampleunit\": \"ft\"\n      });\n      const headerFields = pipeline.getReader().getTraceHeaderFields();\n      let headerInfo;\n      for (let i = 0; i < headerFields.length; i++) {\n        const header = headerFields[i];\n        if (header.getName() === \"INLINE\" || header.getName() === \"XLINE\") {\n          this.widget.setTraceHeaderVisible(header, true);\n        } else if (header.getName() === \"TraceNumber\") {\n          this.widget.setTraceHeaderVisible(header, false);\n        }\n        headerInfo = this.widget.getTraceHeaderAxis(header);\n        if (headerInfo) {\n          headerInfo[\"label\"].getTextStyle().setColor(\"#6b6b6b\");\n        }\n      }\n    } catch (err) {\n      this.showError(err);\n    }\n  }\n  async forward() {\n    try {\n      const keys = this.data.getKeys();\n      const key = keys[0];\n      if (this.position + 1 <= key[\"max\"]) {\n        const reader = await createReader(this.data, this.position + 1);\n        const pipeline = createPipeline(reader);\n        this.lastTileRendered = false;\n        this.widget.setPipeline(pipeline, false);\n        this.position++;\n      }\n    } catch (err) {\n      this.stop();\n      this.showError(err);\n    }\n  }\n  async backward() {\n    try {\n      const keys = this.data.getKeys();\n      const key = keys[0];\n      if (this.position - 1 >= key[\"min\"]) {\n        const reader = await createReader(this.data, this.position - 1);\n        const pipeline = createPipeline(reader);\n        this.lastTileRendered = false;\n        this.widget.setPipeline(pipeline, false);\n        this.position--;\n      }\n    } catch (err) {\n      this.stop();\n      this.showError(err);\n    }\n  }\n  async play() {\n    if (!this.intervalId) {\n      this.intervalId = window.setInterval(() => {\n        if (this.lastTileRendered) {\n          const keys = this.data.getKeys();\n          const key = keys[0];\n          if (this.position + 1 > key[\"max\"]) {\n            this.position = key[\"min\"];\n          }\n          this.forward();\n        }\n      }, FrameTimeInterval);\n    }\n  }\n  async stop() {\n    if (this.intervalId) {\n      clearInterval(this.intervalId);\n      this.intervalId = null;\n    }\n  }\n  dispose() {\n    this.plot.dispose();\n  }\n  showError(error) {\n    this.errorObj.show = true;\n    this.errorObj.text = typeof error === \"object\" || error.name ? error.name : error;\n  }\n}\nfunction createScene(canvas, errorObj) {\n  const movie = new SeismicMovie(canvas, errorObj);\n  movie.create();\n  return movie;\n}\nexport { createScene };\n\ncreateScene(document.querySelector('[ref=\"plot\"]'), this.error);\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/Movie/movie?section=General&extract=true","width":"100%","height":"548.5px","style":{"border":"none"}},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Close"]}]},"headings":[{"value":"Seismic Movie Mode","id":"seismic-movie-mode","depth":1},{"value":"Result","id":"result","depth":3}],"frontmatter":{"title":"Seismic Movie Mode","seo":{"title":"Seismic Movie Mode"}},"lastModified":"2026-02-11T19:54:32.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/solutions/geotoolkit/tutorials/seismic/movie","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}