Seismic sections
Variable density with wiggle traces, across a fault. Well A runs through it.
Ten gigabytes. Thirty milliseconds. One browser tab.
Drag it, zoom it, switch its colormap.Every tile you see was fetched for the view you are looking at, nearest the centre first.
Fetching a whole SEG-Y file before drawing it stalls exploration.A 1 GB file took tens of seconds to arrive and left the tab unresponsive; real files are 5 to 10 GB, reached over the internet. Outkrop asks only for what the pane can show.
Server time no longer grows with file size.Measured on real files read cold from disk: the same actions, against whole-file fetching and against Outkrop with and without its cache.
A 1,600-pixel pane can't show more than 1,600 traces. Outkrop picks the coarsest level that still fills the pane's pixels, and the whole line arrives in a handful of tiles.
Every step in halves the cells per tile. Tiles nearest the centre come first. Until they land, the coarser parent stands in, so the view sharpens instead of flashing.
At level zero you are reading the file's own samples. Once the traces are far enough apart, wiggles join the variable density.
The dispatcher keeps each file as a pyramid.Levels zero to three are read from the file itself; level four and up come from a cache it builds beside it, where one cell stands for 256 of the file's. The transfer follows the extent and resolution in view, not the size of the file.
| lvl | traces × samples | size | read from |
|---|
For a 6 GB line, around the spot the dive above ended on. Each step halves the traces and the samples, so the bytes fall by four.
Images, wiggles, curves, points, markers, axes and colorbars are layers in the same engine.So a section, the well that crosses it and the crossplot of that well can share a page without fighting over the GPU.
Variable density with wiggle traces, across a fault. Well A runs through it.
Well A's curves in depth tracks, on linear and logarithmic scales.
Density against neutron around well A, coloured by gamma ray.
A camera move, a tile arriving, a style change: each asks for a frame.Every ask before the next animation frame draws once. An idle view costs nothing.
Views read --outkrop-* custom properties from any ancestor and follow them when a class, attribute or the system appearance changes.What the page leaves unset comes from the text colour the view inherits.
:root { --outkrop-text: var(--gray-12); --outkrop-grid: var(--gray-a4); --outkrop-font: 10px monospace; } :root.dark { --outkrop-plot: #111; } /* or one view at a time */ <CrossplotView theme={{ text: '#222' }} />
An engine owns panes; panes own a camera, layers and overlays. The data worker decodes off the main thread, and the React surface handles the canvas, resizing and the WebGL fallback.
import { AxesOverlay, Camera, DataWorker, HttpDataSource, ImageTileLayer, seismicImage, type Engine } from '@bs/outkrop-core' import { OutkropSurface } from '@bs/outkrop-react' // A section from a dispatcher const source = new HttpDataSource({ baseUrl: '/services/dispatcher' }) const worker = new DataWorker() async function setup(engine: Engine) { const info = await source.seismicInfo('/data/line.sgy') const camera = new Camera({ x: [0, info.traces], y: [0, info.samples] }) const pane = engine.addPane({ id: 'section', rect: { x: 48, y: 8, width: 600, height: 400 }, camera }) pane.add(new ImageTileLayer({ image: seismicImage(source, info, { worker }), clip: [-1, 1], colormap: 'Seismic', })) pane.add(new AxesOverlay({ x: { title: 'Trace' }, y: { title: 'Sample' } })) } export const Section = () => <OutkropSurface setup={(engine) => void setup(engine)} />
<OutkropSurface ref={handle} // engine, controls, exportPng() setup={(engine) => { /* panes and layers; return a cleanup */ }} layout={(size, engine) => { /* pane rects, in CSS pixels */ }} controls={{ mode: 'pan', wheel: 'y' }} // or false background={[1, 1, 1, 1]} onFrame={(stats) => {}} fallback={<p>This browser has no WebGL2.</p>} > {/* toolbars and readouts, drawn over the surface */} </OutkropSurface> // setup runs once per engine, on the client. // On the server the surface renders an empty box.
Bring your own SEG-Y. Explore it on your device.No install. No sign-in. No upload. Drop it in, zoom to the last sample, export what you see.
More in the usage guide and the documentation index.
HttpDataSource talks to a dispatcher, and an application can supply its own data source instead. The data worker decodes and processes either way./domain/v2 routes frozen in domain-v2.openapi.json. It reads levels zero to three from the file and builds level four and up in a cache under .derived/viz.OutkropSurface renders an empty box on the server and is marked 'use client', so a Next.js server component can render it.@bs/outkrop-core as a peer dependency of @bs/outkrop-react.fallback you give it. If the browser takes the context away later, the engine waits for it to come back and every layer rebuilds on its next draw.$ npm install @bs/outkrop-core @bs/outkrop-react