"""
defines:
- expand_thru
- expand_thru_by
"""
from typing import Optional
from pyNastran.utils.numpy_utils import integer_types
from pyNastran.bdf.bdf_interface.assign_type import interpret_value
[docs]
def expand_thru(fields: list[str],
set_fields: bool=True,
sort_fields: bool=False) -> list[int]:
"""
Expands a list of values of the form [1,5,THRU,9,13]
to be [1,5,6,7,8,9,13]
Parameters
----------
fields : list[int/str]
the fields to expand
set_fields : bool; default=True
Should the fields be converted to a set and then back to a list?
This is useful for [2, 'THRU' 5, 1]
sort_fields : bool; default=False
Should the fields be sorted at the end?
"""
# ..todo: should this be removed...is the field capitalized when read in?
if isinstance(fields, integer_types):
return [fields]
#elif isinstance(fields[0], integer_types): # don't use this [1, 'THRU', 10]
#return fields
elif len(fields) == 1:
return [int(fields[0])]
fields = _remove_blanks_capitalize(fields)
out = []
nfields = len(fields)
i = 0
while i < nfields:
if isinstance(fields[i], str) and fields[i] == 'THRU':
istart = int(fields[i - 1])
iend = int(fields[i + 1])
# adding 1 to iend for the range offset
for j in range(istart+1, iend + 1):
out.append(j)
i += 2
else:
out.append(int(fields[i]))
i += 1
if set_fields:
out = list(set(out))
if sort_fields:
out.sort()
return out
[docs]
def _remove_blanks_capitalize(fields: list[Optional[str]]) -> list[Optional[str]]:
"""remove any blanks and capitalize any strings"""
#fields2 = [field.upper()
#if isinstance(field, str) else field for field in fields]
fields2 = []
for field in fields:
if field is None:
continue
if isinstance(field, str):
field = field.upper()
if len(field) == 0:
continue
fields2.append(field)
return fields2
[docs]
def expand_thru_by(fields: list[str], set_fields: bool=True, sort_fields: bool=True,
require_int: bool=True, allow_blanks: bool=False) -> list[int]:
"""
Expands a list of values of the form [1,5,THRU,9,BY,2,13]
to be [1,5,7,9,13]
Parameters
----------
fields : list[int/str]
the fields to expand
set_fields : bool; default=True
Should the fields be converted to a set and then back to a list
to remove duplicates?
This is useful for [2, 'THRU' 5, 1]
sort_fields : bool; default=False
Should the fields be sorted at the end?
require_int : bool; default=True
True : all data must be integers
False : floats are allowed (e.g., DDVAL)
allow_blanks : bool; default=Fals
True : blank/Nones are ignored (e.g., NSM1/NSML1)
False : crash
.. todo:: not tested
Notes
-----
used for:
BLSEG, DDVAL, NSM1, ACCEL1
QVECT, QBDY3, RADBC, QVOL
what else ???
"""
if require_int:
func = int
else:
func = interpret_value
# ..todo: should this be removed...is the field capitalized when read in?
fields = _remove_blanks_capitalize(fields)
if len(fields) == 1:
return [func(fields[0])]
out = []
nfields = len(fields)
i = 0
by = 1
while i < nfields:
#print('fields[i]=%r' % fields[i])
is_blank = (
allow_blanks and (
(isinstance(fields[i], str) and fields[i].strip() == '') or
fields[i] is None)
)
if is_blank:
#print('blank=%s' % fields[i])
i += 1
continue
if fields[i] == 'THRU':
by = 1
by_case = False
if i + 2 < nfields and fields[i + 2] == 'BY':
by = func(fields[i + 3])
else:
by = 1
by_case = True
min_value = func(fields[i - 1])
max_value = func(fields[i + 1])
max_range = int((max_value - min_value) // by + 1) # max range value
for j in range(0, max_range): # +1 is to include final point
value = min_value + by * j
out.append(value)
out.append(max_value)
if by_case: # null/standard case
# A thru B
i += 2
else: # BY case
# A thru B by C
i += 4
else:
out.append(func(fields[i]))
i += 1
if set_fields:
out = list(set(out))
if sort_fields:
out.sort()
return out