Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update array write #18

Merged
merged 6 commits into from
Jul 31, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 84 additions & 5 deletions flopy4/array.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ def __init__(
tagged=False,
reader=MFReader.urword,
default_value=None,
extpath=None,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

imo this could be public, an attr or property of type Optional[Path] that has a value if the array is external otherwise None? I'd also vote to call it path

):
MFParam.__init__(
self,
Expand All @@ -227,6 +228,7 @@ def __init__(
self._shape = shape
self._how = how
self._factor = factor
self._extpath = extpath

def __getitem__(self, item):
return self.raw[item]
Expand Down Expand Up @@ -343,8 +345,77 @@ def how(self):
return self._how

def write(self, f, **kwargs):
# todo
pass
PAD = " "
if self.layered:
f.write(f"{PAD}" + f"{self.name.upper()} LAYERED\n")
for mfa in self._value:
values = mfa.raw
if mfa._how == MFArrayType.internal:
if len(values.shape) == 1:
v = f"{PAD*3}"
v += " ".join([str(x) for x in values])
v += "\n"
elif len(values.shape) == 2:
v = f"\n{PAD*3}"
v = v.join(" ".join(str(x) for x in y) for y in values)
elif len(values.shape) == 3:
v = f"{PAD*3}"
for i in range(len(values)):
v += v.join(
" ".join(str(x) for x in y) for y in values[i]
)
v += f"\n{PAD*3}"
lines = f"{PAD*2}" + f"{MFArrayType.to_string(mfa._how)}"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these f-strings could be merged into 1 and likewise below

if mfa._factor:
lines += f" FACTOR {mfa._factor}"
lines += f"\n{PAD*3}" + f"{v}\n"
elif mfa._how == MFArrayType.external:
lines = (
f"{PAD*2}" + f"{MFArrayType.to_string(mfa._how)} "
f"{mfa._extpath}\n"
)
elif mfa._how == MFArrayType.constant:
lines = (
f"{PAD*2}" + f"{MFArrayType.to_string(mfa._how)} "
f"{str(mfa._value)}\n"
)
f.write(lines)
else:
values = self.raw
if self._how == MFArrayType.internal:
if len(values.shape) == 1:
v = f"{PAD*3}"
v += " ".join([str(x) for x in values])
elif len(values.shape) == 2:
v = f"\n{PAD*3}"
v = v.join(" ".join(str(x) for x in y) for y in values)
elif len(values.shape) == 3:
v = f"{PAD*3}"
for i in range(len(values)):
v += v.join(
" ".join(str(x) for x in y) for y in values[i]
)
v += f"\n{PAD*3}"
lines = (
f"{PAD}" + f"{self.name.upper()}\n"
f"{PAD*2}" + f"{MFArrayType.to_string(self._how)}"
)
if self._factor:
lines += f" FACTOR {self._factor}"
lines += f"\n{v}\n"
elif self._how == MFArrayType.external:
lines = (
f"{PAD}" + f"{self.name.upper()}\n"
f"{PAD*2}"
+ f"{MFArrayType.to_string(self._how)} {self._extpath}\n"
)
elif self._how == MFArrayType.constant:
lines = (
f"{PAD}" + f"{self.name.upper()}\n"
f"{PAD*2}" + f"{MFArrayType.to_string(self._how)} "
f"{str(self._value)}\n"
)
f.write(lines)

@classmethod
def load(cls, f, cwd, shape, header=True, **kwargs):
Expand Down Expand Up @@ -391,6 +462,7 @@ def _load(cls, f, cwd, shape, layered=False, **kwargs):
control_line.pop(idx)

how = MFArrayType.from_string(control_line[0])
extpath = None
clpos = 1

if how == MFArrayType.internal:
Expand All @@ -401,8 +473,8 @@ def _load(cls, f, cwd, shape, layered=False, **kwargs):
clpos += 1

elif how == MFArrayType.external:
ext_path = Path(control_line[clpos])
fpath = cwd / ext_path
extpath = Path(control_line[clpos])
fpath = cwd / extpath
with open(fpath) as foo:
array = cls.read_array(foo)
clpos += 1
Expand All @@ -414,7 +486,14 @@ def _load(cls, f, cwd, shape, layered=False, **kwargs):
if len(control_line) > 2:
factor = float(control_line[clpos + 1])

return cls(shape, array=array, how=how, factor=factor, **kwargs)
return cls(
shape,
array=array,
how=how,
factor=factor,
extpath=extpath,
**kwargs,
)

@staticmethod
def read_array(f):
Expand Down
2 changes: 1 addition & 1 deletion spec/make_ipkg.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def __init__(
with open(f"{PROJ_ROOT}/spec/mf6pkg.template") as f:
tout = Template(f.read())

if not (tin or tout):
if not (tin and tout):
raise ValueError("FileSystem NO-OPT")

jinja_blocks = []
Expand Down
1 change: 0 additions & 1 deletion spec/make_toml.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,6 @@ def _set_var_d(self):
self._var_d = vardict

def _substitute(self, blockname, component, subcomponent):
block_d = dict()
block_d = {}
for k in self._var_d:
varname, block = k
Expand Down
31 changes: 26 additions & 5 deletions test/test_array.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ def test_array_load_1d(tmp_path):
how = "INTERNAL"
v = [1.0, 2.0, 3.0]
value = " ".join(str(x) for x in v)

with open(fpth, "w") as f:
f.write(f"{name.upper()}\n{how}\n{value}\n")

with open(fpth, "r") as f:
array = MFArray.load(f, cwd=tmp_path, shape=(3))
assert array.name == name
Expand All @@ -28,9 +28,31 @@ def test_array_load_3d(tmp_path):
for b in a:
value += " ".join(str(x) for x in b)
value += " "

with open(fpth, "w") as f:
f.write(f"{name.upper()}\n{how}\n{value}\n")
with open(fpth, "r") as f:
array = MFArray.load(f, cwd=tmp_path, shape=(3, 1, 3))
assert array.name == name
assert np.allclose(array.value, np.array(v))


def test_array_load_3d_external(tmp_path):
name = "array"
fpth = tmp_path / f"{name}.txt"
extfpth = f"external_{name}.txt"
how = "OPEN/CLOSE"
v = [[[1.0, 2.0, 3.0]], [[4.0, 5.0, 6.0]], [[7.0, 8.0, 9.0]]]
value = ""
for a in v:
for b in a:
value += " ".join(str(x) for x in b)
value += " "

with open(tmp_path / extfpth, "w") as f:
f.write(f"{value}")
with open(fpth, "w") as f:
f.write(f"{name.upper()}\n{how} {extfpth}\n")
with open(fpth, "r") as f:
array = MFArray.load(f, cwd=tmp_path, shape=(3, 1, 3))
assert array.name == name
Expand All @@ -45,13 +67,12 @@ def test_array_load_layered(tmp_path):
value = ""
for a in v:
for b in a:
# TODO: MFArray expects this on separate line
value += f"{how}\n"
value += " ".join(str(x) for x in b)
value += " " + f"{how}\n"
value += " " + " ".join(str(x) for x in b)
value += "\n"

with open(fpth, "w") as f:
f.write(f"{name.upper()} LAYERED\n{value}")

with open(fpth, "r") as f:
array = MFArray.load(f, cwd=tmp_path, shape=(3, 1, 3))
assert array.name == name
Expand Down
4 changes: 3 additions & 1 deletion test/test_block.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,9 @@ def test_load_write(tmp_path):
assert " D 1.0\n" in lines
assert " S value\n" in lines
assert f" F FILEIN {fpth}\n" in lines
# assert " A\n INTERNAL\n 1.0 2.0 3.0\n" in lines
assert " A\n" in lines
assert " INTERNAL\n" in lines
assert " 1.0 2.0 3.0\n" in lines
assert " R RK RI 2 RD 2.0\n" in lines
assert "END OPTIONS\n" in lines

Expand Down
4 changes: 3 additions & 1 deletion test/test_package.py
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,9 @@ def test_load_write(tmp_path):
assert " D 1.0\n" in lines
assert " S value\n" in lines
assert f" F FILEIN {fpth}\n" in lines
# todo check array
assert " A\n" in lines
assert " INTERNAL\n" in lines
assert f" {array}\n" in lines
assert "END OPTIONS\n" in lines


Expand Down
Loading