Skip to main content

Example: Ore control

Compute tasks are building blocks. You can use each one by itself, but you can also combine them to build workflows. In this example, you'll build an ore control workflow that goes like this:

  1. Break ties in the data.
  2. Calculate declustering weights.
  3. Calculate a CDF for the data.
  4. Run conditional block turning-bands simulation.
  5. Visualize the result.
  6. Use a profit function to classify blocks as ore or waste.

Starting objects

You'll need a few objects in your workspace to start with:

  1. A pointset or downhole-intervals object with drillhole data.
  2. A regular-3d-grid or regular-masked-3d-grid to hold the simulation results.
  3. A variogram model fitted to the drillhole data.

You can create those objects with the Geoscience Objects API.

This example uses a pointset called composites.json with one attribute called gold-ppm. It uses a variogram model called gold-ppm-variogram.json, targets a regular-3d-grid called simulation-grid.json.

Break ties

Start with the break ties task.

execution_response = requests.post(
"https://{hub}.api.seequent.com/compute/orgs/{org_id}/geostat/break-ties",
headers={"Authorization": "Bearer {token}"},
allow_redirects=False,
json={
"parameters": {
"composites": {
"type": "geoscience-object-reference",
"object_reference": "https://{hub}.api.seequent.com/geoscience-object/orgs/{org_id}/workspaces/{workspace_id}/objects/path/composites.json",
"object_element": [
{
"type": "element",
"path": "/locations/attributes/@name=gold-ppm",
},
],
},
"target": {
"type": "geoscience-object-reference",
"object_reference": "https://{hub}.api.seequent.com/geoscience-object/orgs/{org_id}/workspaces/{workspace_id}/objects/path/composites.json",
"object_element": [
{
"type": "element",
"path": "/locations/attributes/@name=gold-ppm-without-ties",
},
],
},
},
},
)

After starting the task, you need to wait for it to finish.

status = None
while status not in {"failed", "cancelled", "succeeded"}:
polling_response = requests.get(
"https://{hub}.api.seequent.com" + execution_response.headers["Location"],
headers={"Authorization": "Bearer {token}"},
)
status = polling_response.json()["status"]
time.sleep(1)
if status == "succeeded":
break_ties_result = requests.get(
polling_response.json()["links"]["result"],
headers={"Authorization": "Bearer {token}"},
).json()

When it's done, the result looks like this:

{
"message": "Breaking ties completed.",
"object_modified": {
"type": "geoscience-object-reference",
"object_reference": "https://{hub}.api.seequent.com/geoscience-object/orgs/{org_id}/workspaces/{workspace_id}/objects/path/composites.json",
"object_element": [
{
"type": "element",
"path": "/locations/attributes/@name=my-data-without-ties",
},
],
},
}

The next steps won't show the polling code, but you can repeat the same pattern for each task.

Declustering

Next, you'll make declustering weights with the declustering task. The break-ties task gave you a geoscience object reference to the pointset attribute it created, and you can pop that straight into the declustering request.

execution_response = requests.post(
"https://{hub}.api.seequent.com/compute/orgs/{org_id}/geostat/declustering",
headers={"Authorization": "Bearer {token}"},
allow_redirects=False,
json={
"parameters": {
"composites": break_ties_result["object_modified"],
"target": {
"type": "geoscience-object-reference",
"object_reference": "https://{hub}.api.seequent.com/geoscience-object/orgs/{org_id}/workspaces/{workspace_id}/objects/path/composites.json",
"object_element": [
{
"type": "element",
"path": "/locations/attributes/@name=gold-ppm-declustering-weights",
},
],
},
"cell_sizes": {
"min_size": 1,
"max_size": 10,
"n_sizes": 3,
"y_anisotropy": 1.0,
"z_anisotropy": 1.0,
"n_offsets": 3,
},
},
},
)

After waiting for the task to finish, the result looks like this:

{
"message": "Declustering completed",
"object_modified": {
"type": "geoscience-object-reference",
"object_reference": "https://{hub}.api.seequent.com/geoscience-object/orgs/{org_id}/workspaces/{workspace_id}/objects/path/my-pointset.json",
"object_element": [
{
"type": "element",
"path": "/locations/attributes/@name=gold-ppm-declustering-weights",
},
],
},
}

Continuous distribution

Now, you'll make a non-parametric continuous cumulative distribution with the continuous distribution task, using your tiebroken data and declustering weights.

execution_response = requests.post(
"https://{hub}.api.seequent.com/compute/orgs/{org_id}/geostat/continuous-distribution",
headers={"Authorization": "Bearer {token}"},
allow_redirects=False,
json={
"parameters": {
"composites": break_ties_result["object_modified"],
"weights": declustering_result["object_modified"],
"target": {
"type": "geoscience-object-reference",
"object_reference": "https://{hub}.api.seequent.com/geoscience-object/orgs/{org_id}/workspaces/{workspace_id}/objects/path/gold-ppm-distribution.json",
},
"tail_extrapolations": {
"upper": {
"power_model": {
"power": 1.1,
"min": 0,
},
},
"lower": {
"power_model": {
"power": 1.2,
"max": 99,
},
},
},
"replace": True,
},
},
)

The result looks like this:

{
"message": "Success.",
"object_modified": {
"type": "geoscience-object-reference",
"object_reference": "https://{hub}.api.seequent.com/geoscience-object/orgs/{org_id}/workspaces/{workspace_id}/objects/path/gold-ppm-distribution.json",
},
}

Conditional tbsim

Time to simulate! You'll use the conditional tbsim task with the tiebroken data and distribution you just made.

This time, put the task's parameters into a variable. You'll need them again later.

simulation_parameters = {
"composites": break_ties_result["object_modified"],
"target": {
"type": "geoscience-object-reference",
"object_reference": "https://{hub}.api.seequent.com/geoscience-object/orgs/{org_id}/workspaces/{workspace_id}/objects/path/simulation-grid.json",
"object_element": [
{
"type": "element",
"path": "/cell_attributes/@name=gold-ppm-simulation",
},
],
},
"distribution": continuous_distribution_result["object_modified"],
"variogram_model": {
"type": "geoscience-object-reference",
"object_reference": "https://{hub}.api.seequent.com/geoscience-object/orgs/{org_id}/workspaces/{workspace_id}/objects/path/gold-ppm-variogram.json",
},
"search_neighborhood": {
"max-samples": 40,
"anisotropy": {
"ellipsoid_ranges": {
"major": 70,
"semi_major": 70,
"minor": 5,
},
"rotation": {
"dip_azimuth": 0,
"dip": 0,
"pitch": 0,
},
},
},
"block_discretization": {
"nx": 1,
"ny": 1,
"nz": 1,
},
"number_of_lines": 500,
"random_seed": 123,
"n_sim": 10,
"kriging_method": "simple",
"variogram_reproduction": True,
"normalize_variogram_model": True,
}
execution_response = requests.post(
"https://{hub}.api.seequent.com/compute/orgs/{org_id}/geostat/conditional-tbsim",
headers={"Authorization": "Bearer {token}"},
allow_redirects=False,
json={
"parameters": simulation_parameters,
},
)

The result looks like this:

{
"message": "10 conditional simulations succeeded.",
"target": {
"type": "geoscience-object-reference",
"object_reference": "https://{hub}.api.seequent.com/geoscience-object/orgs/{org_id}/workspaces/{workspace_id}/objects/path/simulation-grid.json",
"object_element": [
{
"type": "element",
"path": "/cell_attributes/@name=gold-ppm-simulation",
},
],
},
}

Simulation report

Now you can make a simulation report to visualize the simulation results.

requests.post(
"https://{hub}.api.seequent.com/compute/orgs/{org_id}/geostat/simulation-report",
headers={"Authorization": "Bearer {token}"},
json={
"parameters": {
"simulation_parameters": simulation_parameters,
"target": "https://{hub}.api.seequent.com/file/v2/orgs/{org_id}/workspaces/{workspace_id}/files/path/gold-ppm-simulation-report.json",
},
},
)

The result looks like this:

{
"message": "Success",
"links": {
"report": "https://{hub}.api.seequent.com/file/v2/orgs/{org_id}/workspaces/{workspace_id}/files/path/gold-ppm-simulation-report.json",
"dashboard": "https://simval.seequent.com/orgs/{org_id}/workspaces/{hub}/{workspace_id}/reports/{report_id}/original",
}
}

The report link points to a File URL with the report data, and the dashboard link points to the Simulation Validation Dashboard where you can visualize the simulation results.

Profit calculation

Finally, you can classify the blocks as ore or waste with the profit calc task.

requests.post(
"https://{hub}.api.seequent.com/compute/orgs/{org_id}/geostat/profit-calc",
headers={"Authorization": "Bearer {token}"},
json={
"parameters": {
"source": simulation_result["object_modified"],
"target": {
"type": "geoscience-object-reference",
"object_reference": "https://{hub}.api.seequent.com/geoscience-object/orgs/{org_id}/workspaces/{workspace_id}/objects/path/simulation-grid.json",
"object_element": [
{
"type": "element",
"path": "/cell_attributes/@name=gold-classification",
},
],
},
"material_categories": [
{"cutoff_grade": 0.50, "metal_price": 1.0, "label": "waste"},
{"cutoff_grade": 5.00, "metal_price": 3.0, "label": "ore"},
],
"processing_cost": 30.00,
"mining_waste_cost": 20.00,
"mining_ore_cost": 20.00,
"metal_recovery_fraction": 0.4,
},
},
)

The result looks like this:

{
"message": "Calculation completed",
"object_modified": {
"type": "geoscience-object-reference",
"object_reference": "https://{hub}.api.seequent.com/geoscience-object/orgs/{org_id}/workspaces/{workspace_id}/objects/path/simulation-grid.json",
"object_element": [
{
"type": "element",
"path": "/cell_attributes/@name=gold-classification",
},
],
},
}

Now you have a classification of the blocks as ore or waste in the gold-classification attribute of the simulation-grid.json object.