Skip to content

Commit

Permalink
Generated test data is written to tmp directory, added subscript doc …
Browse files Browse the repository at this point in the history
…minimum version
  • Loading branch information
oddvarlia committed Sep 26, 2024
1 parent 627e13d commit 3a9d197
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 56 deletions.
8 changes: 8 additions & 0 deletions docs/scripts/field_statistics.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
FIELD_STATISTICS
=================

.. argparse::
:module: subscript.field_statistics.field_statistics
:func: get_parser
:prog: field_statistics

86 changes: 64 additions & 22 deletions src/subscript/field_statistics/field_statistics.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@
import sys
from pathlib import Path

import ert
import fmu.config.utilities as utils
import numpy as np
import xtgeo
import yaml
from ert.config import ErtScript

import subscript

Expand Down Expand Up @@ -139,7 +141,8 @@
"Volon": ["phit"]
# Size of ertbox grid for (nx, ny, nz)
# Required.
# Required if the ERTBOX grid is not found as a file
# under rms/output/aps/ERTBOX.EGRID
ertbox_size: [92, 146, 66]
# Standard deviation estimator.
Expand All @@ -163,16 +166,21 @@
LOAD_WORKFLOW ../../bin/workflows/wf_field_param_statistics
-- The workflow file to be located under ert/bin/workflows:
WF_FIELD_PARAM_STATISTICS <FIELD_STAT_CONFIG_FILE> <CONFIG_PATH> <SCRATCH>/<USER>/<CASE_DIR>
-- The workflow job file to be located under ert/bin/jobs:
-- Workflow job for ERT to calculate
-- - mean and stdev of ensemble of continuous 3D parameters with name <name> saved for geogrid
-- under <ensemble_path>/realization-*/iter-*/share/results/grids/geogrid--<name>.roff
-- - estimate facies probabilities of discrete 3D parameters with name <name> saved for geogrid
-- under <ensemble_path>/realization-*/iter-*/share/results/grids/geogrid--<name>.roff
FIELD_STATISTICS -c <FIELD_STAT_CONFIG_FILE>
-p <CONFIG_PATH>
-e <SCRATCH>/<USER>/<CASE_DIR>
-r <RESULT_PATH>
-- Workflow job for ERT to calculate:
-- Mean and standard deviatons of specified continuous 3D parameters.
-- Estimate of facies probabilities from discrete 3D parameter for facies.
-- The input realizations are found under:
-- <ensemble_path>/realization-*/iter-*/share/results/grids/geogrid--<name>.roff
-- The output mean and standard deviations and facies probability estimates are saved
-- under a directory specified by the user.
-- The first three command line arguments are required, the last one (<RESULT_PATH>)
-- has default 'share/grid_statistics' under <ensemble_path>.
INTERNAL False
EXECUTABLE ../scripts/wf_field_param_statistics.py
EXECUTABLE ../scripts/field_statistics.py
MIN_ARG 6
ARG_TYPE 0 STRING
Expand All @@ -187,14 +195,18 @@
""" # noqa

DEFAULT_RELATIVE_RESULT_PATH = "share/grid_statistics"
GLOBAL_VARIABLES_FILE = "/../../fmuconfig/output/global_variables.yml"

def main():
"""Invocated from the command line, parsing command line arguments"""
parser = get_parser()
args = parser.parse_args()

logger.setLevel(logging.INFO)
field_stat(args)


def field_stat(args):

# parse the config file for this script
if not Path(args.configfile).exists():
Expand All @@ -214,16 +226,14 @@ def main():
sys.exit("No such file:" + args.ensemblepath)
ens_path = args.ensemblepath

# Relative path for result of ensemble statistics calculations
# relative to ensemble path on scratch disk
# Path for result of ensemble statistics calculations
# Default path is defined.
result_path = "share/grid_statistics"
relative_result_path = DEFAULT_RELATIVE_RESULT_PATH
if Path(args.resultpath).exists():
result_path = args.resultpath
relative_result_path = args.resultpath
result_path = ens_path + "/" + relative_result_path
glob_var_config_path = Path(ert_config_path) / Path(GLOBAL_VARIABLES_FILE)

glob_var_config_path = (
ert_config_path + "/../../fmuconfig/output/global_variables.yml"
)
cfg_global = utils.yaml_load(glob_var_config_path)["global"]
keyword = "FACIES_ZONE"
if keyword in cfg_global:
Expand All @@ -236,7 +246,7 @@ def main():
ertbox_size = get_ertbox_size(ertbox_path)
logger.info(f"Config path to FMU project: {ert_config_path}")
logger.info(f"Ensemble path on scratch disk: {ens_path}")
logger.info(f"Result relative path on scratch disk: {result_path}")
logger.info(f"Result path on scratch disk: {result_path}")
logger.info(f"ERTBOX size: {ertbox_size}")

calc_stats(
Expand Down Expand Up @@ -414,7 +424,7 @@ def write_mean_stdev_nactive(
ncount_active_values,
result_path,
):
output_path = ensemble_path / Path(result_path)
output_path = result_path
if not output_path.exists():
# Create the directory
output_path.mkdir()
Expand Down Expand Up @@ -466,7 +476,7 @@ def write_fraction_nactive(
result_path,
ncount_active_values=None,
):
output_path = ensemble_path / Path(result_path)
output_path = result_path
if not output_path.exists():
# Create the directory
output_path.mkdir()
Expand Down Expand Up @@ -881,5 +891,37 @@ def calc_stats(
logger.info(txt)


class FieldStatistics(ErtScript):
"""This class defines the ERT workflow hook.
It is constructed to work identical to the command line except
* field_statistics is upper-cased to FIELD_STATISTICS
* All option names with double-dash must be enclosed in "" to avoid
interference with the ERT comment characters "--".
"""

# pylint: disable=too-few-public-methods
def run(self, *args):
# pylint: disable=no-self-use
"""Pass the ERT workflow arguments on to the same parser as the command
line."""
parser = get_parser()
parsed_args = parser.parse_args(args)
field_stat(parsed_args)


@ert.plugin(name="subscript")
def legacy_ertscript_workflow(config):
"""A hook for usage of this script in an ERT workflow,
using the legacy hook format."""

workflow = config.add_workflow(FieldStatistics, "FIELD_STATISTICS")
workflow.parser = get_parser
workflow.description = DESCRIPTION
workflow.examples = EXAMPLES
workflow.category = CATEGORY


if __name__ == "__main__":
main()
1 change: 0 additions & 1 deletion src/subscript/field_statistics/wf_field_param_statistics

This file was deleted.

2 changes: 2 additions & 0 deletions src/subscript/field_statistics/wf_field_statistics
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
FIELD_STATISTICS -c <FIELD_STAT_CONFIG_FILE> -p <CONFIG_PATH> -e <SCRATCH>/<USER>/<CASE_DIR> -r <RESULT_PATH>

83 changes: 50 additions & 33 deletions tests/test_field_statistics.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# import logging
import os
from pathlib import Path
import shutil

import fmu.config.utilities as utils
import numpy as np
Expand All @@ -21,12 +23,13 @@
# logger = subscript.getLogger(__name__)
# logger.setLevel(logging.INFO)

TESTDATA = Path(__file__).absolute().parent / "testdata_field_statistics"
ENS_PATH = Path(__file__).absolute().parent / "testdata_field_statistics" / "ensemble"
ERT_CONFIG_PATH = (
Path(__file__).absolute().parent / "testdata_field_statistics" / "ert" / "model"
)
TESTDATA = Path("testdata_field_statistics")
ENSEMBLE = Path("ensemble")
RESULT_PATH = Path("share/grid_statistics")
ERT_CONFIG_PATH = Path("ert/model")
DATADIR = Path(__file__).absolute().parent / TESTDATA
GLOBAL_VARIABLES_FILE = Path("../../fmuconfig/output/global_variables.yml")


CONFIG_DICT = {
"nreal": 10,
Expand Down Expand Up @@ -55,22 +58,21 @@
"ertbox_size": [5, 6, 5],
"use_population_stdev": False,
}
GLOB_VAR_CFG_PATH = ERT_CONFIG_PATH / Path(
"../../fmuconfig/output/global_variables.yml"
)
CFG_GLOBAL = utils.yaml_load(GLOB_VAR_CFG_PATH)["global"]
KEYWORD = "FACIES_ZONE"
if KEYWORD in CFG_GLOBAL:
FACIES_PER_ZONE = CFG_GLOBAL[KEYWORD]
else:
raise KeyError(f"Missing keyword: {KEYWORD} in {GLOB_VAR_CFG_PATH}")


def make_box_grid(dimensions, grid_name, ens_path):
filename = ens_path / Path("share/grid_statistics") / Path(grid_name + ".roff")
filename_egrid = (
ens_path / Path("share/grid_statistics") / Path(grid_name.upper() + ".EGRID")
)
#GLOB_VAR_CFG_PATH = ERT_CONFIG_PATH / Path(
# "../../fmuconfig/output/global_variables.yml"
#)
#CFG_GLOBAL = utils.yaml_load(GLOB_VAR_CFG_PATH)["global"]
#KEYWORD = "FACIES_ZONE"
#if KEYWORD in CFG_GLOBAL:
# FACIES_PER_ZONE = CFG_GLOBAL[KEYWORD]
#else:
# raise KeyError(f"Missing keyword: {KEYWORD} in {GLOB_VAR_CFG_PATH}")


def make_box_grid(dimensions, grid_name, result_path):
filename = result_path / Path(grid_name + ".roff")
filename_egrid = result_path / Path(grid_name.upper() + ".EGRID")

grid = xtgeo.create_box_grid(dimensions)
grid.name = grid_name
print(f"Grid name: {grid.name}")
Expand Down Expand Up @@ -116,7 +118,6 @@ def make_ensemble_test_data(

iteration_list = [0, 3]
zone_code_names = config_dict["zone_code_names"]
facies_per_zone = facies_per_zone
discrete_param_name_per_zone = config_dict["discrete_property_param_per_zone"]
param_name_per_zone = config_dict["continuous_property_param_per_zone"]
nreal = 10
Expand Down Expand Up @@ -434,30 +435,46 @@ def compare_with_referencedata(ens_path, result_path, print_check=False):


@pytest.mark.parametrize(
"config_dict, ens_path, ert_config_path, facies_per_zone, result_path",
[(CONFIG_DICT, ENS_PATH, ERT_CONFIG_PATH, FACIES_PER_ZONE, RESULT_PATH)],
"config_dict",
[CONFIG_DICT],
)
def test_calc_statistics(
tmp_path,
config_dict,
ens_path,
ert_config_path,
facies_per_zone,
result_path,
ertbox_size=None,
):
"""Main test script"""
tmp_testdata_path = tmp_path / TESTDATA
shutil.copytree(DATADIR, tmp_testdata_path)

ens_path = tmp_testdata_path / ENSEMBLE
ert_config_path = tmp_testdata_path / ERT_CONFIG_PATH
result_path = ens_path / RESULT_PATH

glob_cfg_path = ert_config_path / GLOBAL_VARIABLES_FILE
cfg_global = utils.yaml_load(glob_cfg_path)["global"]
keyword = "FACIES_ZONE"
if keyword in cfg_global:
facies_per_zone = cfg_global[keyword]
else:
raise KeyError(f"Missing keyword: {keyword} in {glob_cfg_path}")

print(tmp_testdata_path)
print(ens_path)
print(ert_config_path)
print(result_path)

(nx, ny, nz) = config_dict["ertbox_size"]

# Write file with ERTBOX grid for the purpose to import to visualize
# the test data in e.g. RMS. Saved in share directory at
# top of ensemble directory
make_box_grid((nx, ny, nz), "ERTBOX", ens_path)
make_box_grid((nx, ny, nz), "ERTBOX", result_path)

# Write file with geogrid for the purpose to import to visualize
# the test data in e.g. RMS". Geogrid for the test data has 3 zones,
# each with 5 layers. Saved in share directory at top of ensemble directory
make_box_grid((nx, ny, nz * 3), "Geogrid", ens_path)
make_box_grid((nx, ny, nz * 3), "Geogrid", result_path)

# Make ensemble of test data
make_ensemble_test_data(config_dict, facies_per_zone, nx, ny, nz, ens_path)
Expand Down Expand Up @@ -873,7 +890,7 @@ def test_get_specification(
Path(__file__).absolute().parent
/ "testdata_field_statistics"
/ "config_example.yml",
ENS_PATH,
DATADIR / ENSEMBLE,
)
],
)
Expand All @@ -900,8 +917,8 @@ def test_main(config_path, ens_path, print_info=True):
"-p",
ERT_CONFIG_PATH,
"-e",
ENS_PATH,
DATADIR / ENSEMBLE,
]
)

assert compare_with_referencedata(ENS_PATH, RESULT_PATH, print_check=True)
assert compare_with_referencedata(DATADIR / ENSEMBLE, RESULT_PATH, print_check=True)

0 comments on commit 3a9d197

Please sign in to comment.