Skip to content

Commit

Permalink
fix(data check): Minimum number of data columns check fixed (#1062) (#…
Browse files Browse the repository at this point in the history
…1065)

* fix(data check): Minimum number of data column check fixed (#1062)

* fix(data check): Test case for nseg=1 (#1062)

* fix(data check): Minimum number of data columns check fixed (#1062)
  • Loading branch information
spaulins-usgs committed Feb 20, 2021
1 parent 4cee7e7 commit cb04f9d
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 29 deletions.
35 changes: 33 additions & 2 deletions autotest/t505_test.py
Expand Up @@ -37,7 +37,8 @@

try:
import shapefile
if int(shapefile.__version__.split('.')[0]) < 2:

if int(shapefile.__version__.split(".")[0]) < 2:
shapefile = None
except ImportError:
shapefile = None
Expand Down Expand Up @@ -1134,6 +1135,28 @@ def test005_advgw_tidal():
timeseries=ts_dict,
)

# test nseg = 1
evt_period = ModflowGwfevt.stress_period_data.empty(model, 150, nseg=1)
for col in range(0, 10):
for row in range(0, 15):
evt_period[0][col * 15 + row] = (
(0, row, col),
50.0,
0.0004,
10.0,
None,
)
evt_package_test = ModflowGwfevt(
model,
print_input=True,
print_flows=True,
save_flows=True,
maxbound=150,
nseg=1,
stress_period_data=evt_period,
)
evt_package_test.remove()

# test empty
evt_period = ModflowGwfevt.stress_period_data.empty(model, 150, nseg=3)
for col in range(0, 10):
Expand Down Expand Up @@ -1264,7 +1287,15 @@ def test005_advgw_tidal():
("rv2-upper", "RIV", "riv2_upper"),
("rv-2-7-4", "RIV", (0, 6, 3)),
("rv2-8-5", "RIV", (0, 6, 4)),
("rv-2-9-6", "RIV", (0, 5, 5,)),
(
"rv-2-9-6",
"RIV",
(
0,
5,
5,
),
),
],
"riv_flowsA.csv": [
("riv1-3-1", "RIV", (0, 2, 0)),
Expand Down
35 changes: 26 additions & 9 deletions flopy/mf6/coordinates/modeldimensions.py
Expand Up @@ -4,6 +4,7 @@
"""

import sys
from .simulationtime import SimulationTime
from .modelgrid import UnstructuredModelGrid, ModelGrid
from ..mfbase import StructException, FlopyException, VerbosityLevel
Expand Down Expand Up @@ -81,6 +82,7 @@ def get_data_shape(
data=None,
data_item_num=None,
repeating_key=None,
min_size=False,
):
return self.get_model_dim(data_item_num).get_data_shape(
self.structure,
Expand All @@ -89,6 +91,7 @@ def get_data_shape(
data,
self.package_dim.package_path,
repeating_key=repeating_key,
min_size=min_size,
)

def model_subspace_size(self, subspace_string="", data_item_num=None):
Expand Down Expand Up @@ -403,6 +406,7 @@ def get_data_shape(
path=None,
deconstruct_axis=True,
repeating_key=None,
min_size=False,
):
if structure is None:
raise FlopyException(
Expand Down Expand Up @@ -492,6 +496,7 @@ def get_data_shape(
path,
deconstruct_axis,
repeating_key=repeating_key,
min_size=min_size,
)
if self.locked and consistent_shape:
self.stored_shapes[data_item.path] = (
Expand All @@ -509,6 +514,7 @@ def _resolve_data_item_shape(
path=None,
deconstruct_axis=True,
repeating_key=None,
min_size=False,
):
if isinstance(data, tuple):
data = [data]
Expand Down Expand Up @@ -560,7 +566,7 @@ def _resolve_data_item_shape(
result = self.resolve_exp(
item,
self._find_in_dataset(
data_set_struct, item[0], data
data_set_struct, item[0], data, min_size
),
)
if result:
Expand All @@ -584,7 +590,8 @@ def _resolve_data_item_shape(
elif DatumUtil.is_int(item[0]):
shape_dimensions.append(int(item[0]))
else:
# try to resolve dimension within the existing block
# try to resolve dimension within the
# existing block
result = self.simulation_data.mfdata.find_in_path(
parent_path, item[0]
)
Expand Down Expand Up @@ -684,7 +691,7 @@ def resolve_exp(self, expression, value):
return value

@staticmethod
def _find_in_dataset(data_set_struct, item, data):
def _find_in_dataset(data_set_struct, item, data, min_size=False):
if data is not None:
# find the current data item in data_set_struct
for index, data_item in zip(
Expand All @@ -695,12 +702,22 @@ def _find_in_dataset(data_set_struct, item, data):
data_item.name.lower() == item.lower()
and len(data[0]) > index
):
# always use the maximum value
max_val = 0
for data_line in data:
if data_line[index] > max_val:
max_val = data_line[index]
return max_val
if min_size:
# use the minimum value
min_val = sys.maxsize
for data_line in data:
if data_line[index] < min_val:
min_val = data_line[index]
if min_val == sys.maxsize:
return 0
return min_val
else:
# use the maximum value
max_val = 0
for data_line in data:
if data_line[index] > max_val:
max_val = data_line[index]
return max_val
return None

@staticmethod
Expand Down
28 changes: 26 additions & 2 deletions flopy/mf6/data/mfdatalist.py
Expand Up @@ -356,6 +356,31 @@ def _get_data(self, apply_mult=False, **kwargs):
def get_data(self, apply_mult=False, **kwargs):
return self._get_data(apply_mult, **kwargs)

def _get_min_record_entries(self, data=None):
try:
if isinstance(data, dict) and "data" in data:
data = data["data"]
type_list = self._get_storage_obj().build_type_list(
data=data, min_size=True
)
except Exception as ex:
type_, value_, traceback_ = sys.exc_info()
raise MFDataException(
self.structure.get_model(),
self.structure.get_package(),
self._path,
"getting min record entries",
self.structure.name,
inspect.stack()[0][3],
type_,
value_,
traceback_,
None,
self._simulation_data.debug,
ex,
)
return len(type_list)

def _set_data(self, data, autofill=False, check_data=True):
if isinstance(data, dict):
if "data" in data:
Expand All @@ -366,7 +391,7 @@ def _set_data(self, data, autofill=False, check_data=True):
data_check = data
if iterable(data_check) and check_data:
# verify data length
min_line_size = self.structure.get_min_record_entries()
min_line_size = self._get_min_record_entries(data)
if isinstance(data_check[0], np.record) or (
iterable(data_check[0]) and not isinstance(data_check[0], str)
):
Expand Down Expand Up @@ -481,7 +506,6 @@ def _check_valid_cellids(self):

def _check_line_size(self, data_line, min_line_size):
if 0 < len(data_line) < min_line_size:
min_line_size = self.structure.get_min_record_entries()
message = (
"Data line {} only has {} entries, "
"minimum number of entries is "
Expand Down
50 changes: 35 additions & 15 deletions flopy/mf6/data/mfdatastorage.py
Expand Up @@ -2388,6 +2388,7 @@ def build_type_list(
key=None,
nseg=None,
cellid_expanded=False,
min_size=False,
):
if data_set is None:
self.jagged_record = False
Expand Down Expand Up @@ -2438,17 +2439,27 @@ def build_type_list(
ks_data_item.type = DatumType.string
ks_data_item.name = "{}_data".format(ks_data_item.name)
ks_rec_type = ks_data_item.get_rec_type()
self._append_type_lists(
ks_data_item.name, ks_rec_type, ks_data_item.is_cellid
)
if not min_size:
self._append_type_lists(
ks_data_item.name,
ks_rec_type,
ks_data_item.is_cellid,
)
if (
index == len(data_set.data_item_structures) - 1
and data is not None
):
idx = 1
line_max_size = self._get_max_data_line_size(data)
(
line_max_size,
line_min_size,
) = self._get_max_min_data_line_size(data)
if min_size:
line_size = line_min_size
else:
line_size = line_max_size
type_list = self.resolve_typelist(data)
while len(type_list) < line_max_size:
while len(type_list) < line_size:
# keystrings at the end of a line can contain
# items of variable length. assume everything at
# the end of the data line is related to the last
Expand Down Expand Up @@ -2515,6 +2526,7 @@ def build_type_list(
data_set,
data,
repeating_key=key,
min_size=min_size,
)
else:
resolved_shape = [1]
Expand Down Expand Up @@ -2555,14 +2567,17 @@ def build_type_list(
grid = data_dim.get_model_grid()
size = grid.get_num_spatial_coordinates()
data_item.remove_cellid(resolved_shape, size)
for index in range(0, resolved_shape[0]):
if resolved_shape[0] > 1:
name = "{}_{}".format(data_item.name, index)
else:
name = data_item.name
self._append_type_lists(
name, data_type, data_item.is_cellid
)
if not data_item.optional or not min_size:
for index in range(0, resolved_shape[0]):
if resolved_shape[0] > 1:
name = "{}_{}".format(
data_item.name, index
)
else:
name = data_item.name
self._append_type_lists(
name, data_type, data_item.is_cellid
)
if cellid_expanded:
return self._recarray_type_list_ex
else:
Expand Down Expand Up @@ -2625,13 +2640,18 @@ def _calc_data_size(data, count_to=None, current_length=None):
return current_length[0]

@staticmethod
def _get_max_data_line_size(data):
def _get_max_min_data_line_size(data):
max_size = 0
min_size = sys.maxsize
if data is not None:
for value in data:
if len(value) > max_size:
max_size = len(value)
return max_size
if len(value) < min_size:
min_size = len(value)
if min_size == sys.maxsize:
min_size = 0
return max_size, min_size

def get_data_dimensions(self, layer):
data_dimensions = self.data_dimensions.get_data_shape()[0]
Expand Down
4 changes: 3 additions & 1 deletion flopy/utils/datautil.py
Expand Up @@ -173,7 +173,9 @@ def is_empty_list(current_list):
def max_multi_dim_list_size(current_list):
max_length = -1
for item in current_list:
if len(item) > max_length:
if isinstance(item, str):
return len(current_list)
elif len(item) > max_length:
max_length = len(item)
return max_length

Expand Down

0 comments on commit cb04f9d

Please sign in to comment.