-
Notifications
You must be signed in to change notification settings - Fork 32
Expand file tree
/
Copy pathtest_designmatrix.py
More file actions
154 lines (124 loc) · 5.63 KB
/
Copy pathtest_designmatrix.py
File metadata and controls
154 lines (124 loc) · 5.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
"""Testing generating design matrices from dictionary input"""
import re
import shutil
import subprocess
from pathlib import Path
import pandas as pd
import pytest
from semeio.fmudesign import DesignMatrix
def matches(pattern: str, text: str) -> bool:
"""Match text against a pattern where <ANY> acts as a wildcard.
Examples
--------
>>> matches("my name is <ANY>!", "my name is John!")
True
>>> matches("my <ANY> is <ANY>!", "my name is John!")
True
matches("my <ANY> is <ANY>!", "my name are John!")
False
"""
regex_pattern = re.escape(pattern)
regex_pattern = regex_pattern.replace("<ANY>", ".+?")
regex_pattern = f"^{regex_pattern}$"
return bool(re.match(regex_pattern, text))
def valid_designmatrix(dframe):
"""Performs general checks on a design matrix, that should always be valid"""
assert "REAL" in dframe
# REAL always starts at 0 and is consecutive
assert dframe["REAL"][0] == 0
assert dframe["REAL"].diff().dropna().unique() == 1
assert "SENSNAME" in dframe.columns
assert "SENSCASE" in dframe.columns
# There should be no empty cells in the dataframe:
assert not dframe.isna().sum().sum()
def test_designmatrix():
"""Test the DesignMatrix class"""
design = DesignMatrix()
mock_dict = {
"designtype": "onebyone",
"seeds": "default",
"repeats": 10,
"distribution_seed": 42,
"defaultvalues": {},
"sensitivities": {
"rms_seed": {
"seedname": "RMS_SEED",
"senstype": "seed",
"parameters": None,
"dependencies": {},
}
},
}
design.generate(mock_dict)
valid_designmatrix(design.designvalues)
assert len(design.designvalues) == 10
assert isinstance(design.defaultvalues, dict)
@pytest.mark.integration_test
def test_endpoint(tmpdir, monkeypatch, fmudesign_test_data):
"""Test the installed endpoint
Will write generated design matrices to the pytest tmpdir directory,
usually /tmp/pytest-of-<username>/
"""
designfile = fmudesign_test_data / "config/design_input_onebyone.xlsx"
# The xlsx file contains a relative path, relative to the input design sheet:
dependency = (
pd.read_excel(designfile, header=None, engine="openpyxl")
.set_index([0])[1]
.to_dict()["background"]
)
tmpdir.chdir()
monkeypatch.chdir(tmpdir)
# Copy over input files:
shutil.copy(str(designfile), ".")
shutil.copy(Path(designfile).parent / dependency, ".")
result = subprocess.run(
["fmudesign", str(designfile)], check=True, capture_output=True, text=True
)
# Use <ANY> in the string below to match anything in CLI output
expected_output = """Reading file: <ANY>design_input_onebyone.xlsx'
Reading background values from: <ANY>doe1.xlsx
Generating sensitivity : seed
Generating sensitivity : faults
Generating sensitivity : velmodel
Generating sensitivity : contacts
Generating sensitivity : multz
Generating sensitivity : sens6
Generating sensitivity : sens7
Sampling 4 parameters in correlation group 'corr1'
Warning: Correlation matrix 'corr1' is inconsistent
Requirements:
- All diagonal elements must be 1
- All elements must be between -1 and 1
- The matrix must be positive semi-definite
Input correlation matrix:
| | (1) | (2) | (3) | (4) |
|:------------|------:|------:|------:|------:|
| (1) PARAM9 | 1.00 | | | |
| (2) PARAM10 | 0.90 | 1.00 | | |
| (3) PARAM11 | 0.00 | 0.90 | 1.00 | |
| (4) PARAM12 | 0.00 | 0.00 | 0.00 | 1.00 |
Adjusted to nearest consistent correlation matrix:
| | (1) | (2) | (3) | (4) |
|:------------|------:|------:|------:|------:|
| (1) PARAM9 | 1.00 | | | |
| (2) PARAM10 | 0.74 | 1.00 | | |
| (3) PARAM11 | 0.11 | 0.74 | 1.00 | |
| (4) PARAM12 | 0.00 | 0.00 | 0.00 | 1.00 |
Generating sensitivity : sens8
Provided number of background values (11) is smaller than number of realisations for sensitivity ('sens7', 'p10_p90') and parameter PARAM13. Will be filled with default values.
Provided number of background values (11) is smaller than number of realisations for sensitivity ('sens7', 'p10_p90') and parameter PARAM14. Will be filled with default values.
Provided number of background values (11) is smaller than number of realisations for sensitivity ('sens7', 'p10_p90') and parameter PARAM15. Will be filled with default values.
Provided number of background values (11) is smaller than number of realisations for sensitivity ('sens7', 'p10_p90') and parameter PARAM16. Will be filled with default values.
Design matrix of shape (91, 22) written to: 'generateddesignmatrix.xlsx'
Thank you for using fmudesign <ANY>
- Documentation: https://equinor.github.io/fmu-tools/fmudesign.html
- Course docs: https://fmu-docs.equinor.com/docs/fmu-coursedocs/fmu-howto/sensitivities/index.html
- Issues/feature requests: https://github.com/equinor/semeio/issues""" # ruff: ignore[line-too-long]
for stdout_line, expected_line in zip(
result.stdout.split(), expected_output.split(), strict=False
):
assert matches(expected_line, stdout_line)
assert Path("generateddesignmatrix.xlsx").exists # Default output file
valid_designmatrix(pd.read_excel("generateddesignmatrix.xlsx", engine="openpyxl"))
subprocess.run(["fmudesign", str(designfile), "anotheroutput.xlsx"], check=True)
assert Path("anotheroutput.xlsx").exists