Skip to content

Commit 6afdd56

Browse files
authored
Hotfix: Fixing incompatibility with updated SPECFEM2D parameter file (#197)
* updated setpar and getpar velocity model for SPECFEM2D velocity models due to updated structure from SPECFEM and inflexible function on SeisFlows end * bumping version number, updating changelog, bumping copyright year
1 parent 487b738 commit 6afdd56

File tree

5 files changed

+62
-44
lines changed

5 files changed

+62
-44
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,5 @@ A collection of bugfixes and feature improvement (big thanks to @evcano for majo
5757
- output_optim.txt was not writing the correct misfit values for each
5858
iteration, fixed
5959

60+
## v2.3.1
61+
- Hotfix for updated SPECFEM2D parameter file #197

docs/conf.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@
1919
# -- Project information -----------------------------------------------------
2020

2121
project = 'SeisFlows'
22-
copyright = '2023'
22+
copyright = '2024'
2323
author = 'adjTomo Dev Team'
24-
version = '2.3.0'
24+
version = '2.3.1'
2525

2626

2727
# -- General configuration ---------------------------------------------------

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "seisflows"
7-
version = "2.3.0"
7+
version = "2.3.1"
88
description = "An automated workflow tool for full waveform inversion"
99
readme = "README.md"
1010
requires-python = ">=3.7"

seisflows/seisflows.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -841,7 +841,7 @@ def sempar(self, parameter, value=None, skip_print=False,
841841
# formatted the same as the rest of the file
842842
if parameter == "VELOCITY_MODEL":
843843
key = parameter
844-
items = getpar_vel_model(file=par_file)
844+
items = getpar_vel_model(file=par_file, strip=True)
845845
cur_val = ""
846846
else:
847847
try:
@@ -861,7 +861,7 @@ def sempar(self, parameter, value=None, skip_print=False,
861861
setpar_vel_model(file=par_file, model=value.split("+"))
862862
if not skip_print:
863863
items.append("->")
864-
items += getpar_vel_model(file=par_file)
864+
items += getpar_vel_model(file=par_file, strip=True)
865865
print(msg.cli(f"{key}:", items=items))
866866
else:
867867
setpar(key=parameter, val=value, file=par_file, delim="=")

seisflows/tools/specfem.py

Lines changed: 55 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -155,38 +155,69 @@ def setpar(key, val, file, delim="=", match_partial=False):
155155
f.writelines(lines)
156156

157157

158-
def getpar_vel_model(file):
158+
def _getidx_vel_model(lines):
159159
"""
160-
SPECFEM2D doesn't follow standard formatting when defining its internal
161-
velocity models so we need a special function to address this specifically.
162-
Velocity models are ASSUMED to be formatted in the following way in the
163-
SPECFEM2D Par_file (with any number of comment lines in between)
160+
Get the line indices of a velocity model, which can be used to retrieve
161+
or replace the model values in a SPECFEM2D paramter file. Used by
162+
`getpar_vel_model` and `setpar_vel_model`
163+
164+
:type lines: list
165+
:param lines: list of strings read from the par_file
166+
:rtype idxs: list
167+
:param idxs: list of integer indices of the velocity model lines
168+
"""
169+
idxs = []
170+
for l, line in enumerate(lines):
171+
# Skip over all other parameters, comments, newlines etc.
172+
if "=" in line:
173+
continue
174+
elif line.startswith(" "):
175+
continue
176+
elif line.startswith("#"):
177+
continue
178+
elif line.startswith("\n"):
179+
continue
180+
181+
# Matches formatting expected by velocity model and starts with integer
182+
# Should be enough to avoid matching other strings
183+
lines = line.strip().split()
184+
if len(lines) == 15 and lines[0].isdigit():
185+
idxs.append(l)
186+
187+
return idxs
188+
189+
190+
def getpar_vel_model(file, strip=False):
191+
"""
192+
SPECFEM2D doesn't follow standard key = val formatting when defining its
193+
internal velocity models so we need a special function to address this
194+
specifically.
195+
196+
Velocity models are ASSUMED to be formatted in the following way
164197
165-
nbmodels = 4
166198
1 1 2700.d0 3000.d0 1732.051d0 0 0 9999 9999 0 0 0 0 0 0
167-
2 1 2500.d0 2700.d0 0 0 0 9999 9999 0 0 0 0 0 0
168-
3 1 2200.d0 2500.d0 1443.375d0 0 0 9999 9999 0 0 0 0 0 0
169-
4 1 2200.d0 2200.d0 1343.375d0 0 0 9999 9999 0 0 0 0 0 0
170-
TOMOGRAPHY_FILE = ./DATA/tomo_file.xyz
171199
200+
That is, 15 entries separated by spaces. We use that to find all relevant
201+
lines of the model.
202+
172203
:type file: str
173204
:param file: The SPECFEM Par_file to match against
205+
:type strip: bool
206+
:param strip: strip newline '\n' from each of the model lines
174207
:rtype: list of str
175208
:return: list of all the layers of the velocity model as strings
176209
"""
177-
_, _, i_start = getpar("nbmodels", file)
178-
_, _, i_end = getpar("tomography_file", file)
179-
180210
# i_start + 1 to skip over the 'nbmodels' parameter
181-
lines = open(file, "r").readlines()[i_start + 1:i_end]
211+
lines = open(file, "r").readlines()
212+
idxs = _getidx_vel_model(lines)
182213
vel_model = []
183-
for line in lines:
184-
# Skip comments, empty lines, newlines
185-
for not_allowed in [" ", "#", "\n"]:
186-
if line.startswith(not_allowed):
187-
break
214+
for idx in idxs:
215+
if strip:
216+
line = lines[idx].strip()
188217
else:
189-
vel_model.append(line.strip())
218+
line = lines[idx]
219+
vel_model.append(line)
220+
190221
return vel_model
191222

192223

@@ -207,34 +238,19 @@ def setpar_vel_model(file, model):
207238
model = ["1 1 2700.d0 3000.d0 1732.051d0 0 0 9999 9999 0 0 0 0 0 0",
208239
"2 1 2500.d0 2700.d0 0 0 0 9999 9999 0 0 0 0 0 0"]
209240
"""
210-
_, nbmodels, i_start = getpar("nbmodels", file)
211-
i_start += 1 # increase by one to start AFTER nbmodels line
212-
_, _, i_end = getpar("tomography_file", file)
213-
214241
lines = open(file, "r").readlines()
215-
model_lines = []
216-
# i_start + 1 to skip over the 'nbmodels' parameter
217-
for i, line in enumerate(lines[i_start:i_end]):
218-
# Skip comments, empty lines, newlines
219-
for not_allowed in [" ", "#", "\n"]:
220-
if line.startswith(not_allowed):
221-
break
222-
else:
223-
# We will use these indices to delete the original model
224-
model_lines.append(i)
225-
226-
# Make sure that our indices are relative to the list and not enumeration
227-
model_lines = [_ + i_start for _ in model_lines]
242+
model_lines = _getidx_vel_model(open(file, "r").readlines())
228243

229-
# one-liner to get rid of the original model
244+
# one-liner to get rid of the original model from the file
230245
lines = [i for j, i in enumerate(lines) if j not in model_lines]
246+
model_idx_start = model_lines[0]
231247

232248
# Throw a new line onto the last line of the model to get proper formatting
233249
model[-1] = model[-1] + "\n"
234250

235251
# Drop in the new model one line at a time
236252
for i, val in enumerate(model):
237-
lines.insert(i + model_lines[0], f"{val.strip()}\n")
253+
lines.insert(model_idx_start + i, f"{val.strip()}\n")
238254

239255
# Overwrite with new lines containing updated velocity model
240256
with open(file, "w") as f:

0 commit comments

Comments
 (0)