Shale volume from gamma ray
Shale volume is calculated from a gamma-ray curve in two steps. The gamma-ray index places each sample between a clean value (index 0) and a shale value (index 1), clipped to 0-1; a method then bends that index. Ophiolite lists five methods, with one set of constants used by the server, the browser and the Python SDK alike:
| Method | Shale volume from the index x |
|---|---|
| Linear (simple) | x |
| Larionov, Tertiary rocks | 0.083 (2^(3.7 x) - 1) |
| Larionov, older rocks | 0.33 (2^(2 x) - 1) |
| Clavier | 1.7 - sqrt(3.38 - (x + 0.7)^2) |
| Steiber | x / (3 - 2 x) |
Missing samples stay missing. The log you calculate from is never changed: the result is a new well log with one curve,
VSH in V/V, that records the method, the picks and the exact version of the log it was built on.
The examples use an excerpt of the HON-GT-01 composite log from NLOG.NL (gamma ray from 2466.0 to 2621.0 m; only the depth rows and the DEPTH and GR curves were kept). Over the Rodenrijs Claystone (2466.86 to 2557.9 m) and the Delft Sandstone (2557.9 to 2620.22 m) it gives the numbers shown below.
In the browser
Section titled “In the browser”You need the project permission to run calculations, and permission to build on the log (its owner allows reuse).
- Open the log in Data and press Calculate shale volume….
- In Inputs, choose the Input curve. When Ophiolite only suggests that a curve is a gamma ray, tick This is a gamma-ray curve. Choose the Method (Linear by default) and the Zone: the whole log, or a formation when tops are shown on the log.
- The clean and shale values start at the 5th and 95th percentile of the zone, marked automatic. Drag the clean and shale lines on the Histogram, move them with the arrow keys, or type GR clean and GR shale. Set from the 5th and 95th percentile goes back to the automatic values. The Log view redraws as you change them and says how many samples are at 1 and at 0 after clipping and how many missing samples stay missing.
- Press Save…. Under Who sees it choose Only me or Me and people I choose in this project; under Save as, a new result. Ophiolite answers “Published. It is in Results; its author can share it.” Press Open the result.
- The result shows How it was made in words (method, picks, clipping and the log it was built on) and which version you are looking at. As its author you choose who may read and build on it there.
- To change the picks, open the result and press Change the picks. The window opens on the exact version of the log it was built on, filled in. Save it as Replace: Replace adds a new version of your result and keeps the previous one; nothing is overwritten. Settings that are already a version are not saved twice: “These settings are already version 1 of this result.” with Open version 1.
A colleague who may read the result sees the same words and “Only the author can add a version to this result. You can run the same calculation on the log and publish your own result.” with Calculate my own, which opens the window filled in and publishes a new result in their name.
When the log the result was built on has a newer version, the result says so and offers Calculate again; nothing is recalculated by itself.
In Python
Section titled “In Python”client is an ophiolite.Client for your project; see Build on Ophiolite for a key and the SDK.
Read the gamma ray of the log at the exact version listed:
from ophiolite import petrophysics as pp
log = next(a for a in client.assets() if a["name"] == "HON-GT-01 gamma ray")gr = client.read(log["asset_id"], log["revision"], ["GR"]).curves[0]depth, values, depth_unit = gr.axis, gr.values, gr.context.depth_unitprint(len(values), "samples of GR in", gr.unit, "from", depth[0], "to", depth[-1], depth_unit)Calculate shale volume with typed picks, and its mean over each formation. An interval includes its top and not its base:
vsh = pp.shale_volume(values, method="larionov-older", clean=30, shale=150)
def mean_between(top, base): inside = [v for d, v in zip(depth, vsh) if top <= round(d, 3) < base and v is not None] return sum(inside) / len(inside)
print(f"Rodenrijs Claystone {mean_between(2466.86, 2557.9):.3f}, Delft Sandstone {mean_between(2557.9, 2620.22):.3f}")This prints Rodenrijs Claystone 0.623, Delft Sandstone 0.087.
Publish the result. The file carries the calculation in its ~Other section, and the method record names the method,
the picks and the digest of the method table, so anyone who may read the result sees how it was made:
import uuidfrom ophiolite.writers import write_curves
picks = pp.typed_picks(30, 150)written = write_curves(depth, {"VSH": ("V/V", vsh)}, depth_unit=depth_unit, notes=[pp.calculation_record("larionov-older", picks, gr.unit, depth_unit)])result = client.publish_derived(written, name="Shale volume, Larionov older rocks", from_=[(log["asset_id"], log["revision"])], method=pp.shale_volume_method(method="larionov-older", picks=picks, unit=gr.unit), command_id=str(uuid.uuid4()))print("Published", result.asset_id, "version", result.revision_number)The result is private to you until you share it. Picks taken from the log instead (the 5th and 95th percentile between two depths) are a new version of the same result; the first version is kept with its own picks:
changed = pp.picks_from_percentiles(depth, values, top=2466.86, base=2620.22, depth_unit=depth_unit)volume = pp.shale_volume(values, method="larionov-older", clean=changed["clean"], shale=changed["shale"])written = write_curves(depth, {"VSH": ("V/V", volume)}, depth_unit=depth_unit, notes=[pp.calculation_record("larionov-older", changed, gr.unit, depth_unit)])second = client.publish_derived(written, name="Shale volume, Larionov older rocks", from_=[(log["asset_id"], log["revision"])], method=pp.shale_volume_method(method="larionov-older", picks=changed, unit=gr.unit), command_id=str(uuid.uuid4()), new_version_of=result.asset_id, expected_parent=result.revision)for row in client.history(second).revisions: print("version", row.number, row.calculation)The picks are 30.94 and 150.84 gAPI here. The history names each version and its method in words; the picks of a
version are in its method record (client.read(...).descriptors[0].derivation).
A refusal says what to do. PermissionRefused: you may read the log but not build on it (ask its owner to allow
reuse). IntegrityConflict on a new version: the result changed since you read it; read its history again.
ValidationFailed from ophiolite.petrophysics: a shale value not above the clean value, a depth range with no samples,
a curve whose unit is not stated as gAPI, or a method Ophiolite does not list; nothing was published.
To try the same steps without a project, download the Shale volume from gamma ray notebook: it runs on a synthetic log on your own computer.
