mirror of
https://github.com/triqs/dft_tools
synced 2024-11-07 06:33:48 +01:00
* Completed group parser
* Added a consistency check for groups and shells * Added scenario descriptions to the test suite
This commit is contained in:
parent
0d1ef0ac97
commit
9ab6116b28
@ -241,10 +241,12 @@ class ConfigParameters:
|
|||||||
issue_warning("Shell indices are not uniform or not starting from 1. "
|
issue_warning("Shell indices are not uniform or not starting from 1. "
|
||||||
"This might be an indication of a incorrect setup.")
|
"This might be an indication of a incorrect setup.")
|
||||||
|
|
||||||
# Parse shell parameters
|
# Parse shell parameters and put them into a list sorted according to the original indices
|
||||||
self.shells = {}
|
self.shells = []
|
||||||
for ind in sh_inds:
|
for ind in sh_inds:
|
||||||
self.shells[ind] = {}
|
shell = {}
|
||||||
|
# Store the original user-defined index
|
||||||
|
shell['user_index'] = ind
|
||||||
section = self.sh_sections[ind]
|
section = self.sh_sections[ind]
|
||||||
|
|
||||||
# Shell required parameters
|
# Shell required parameters
|
||||||
@ -252,14 +254,14 @@ class ConfigParameters:
|
|||||||
print
|
print
|
||||||
print " Required shell parameters:"
|
print " Required shell parameters:"
|
||||||
parsed = self.parse_parameter_set(section, self.sh_required, exception=True)
|
parsed = self.parse_parameter_set(section, self.sh_required, exception=True)
|
||||||
self.shells[ind].update(parsed)
|
shell.update(parsed)
|
||||||
|
|
||||||
# Shell optional parameters
|
# Shell optional parameters
|
||||||
if self.verbosity > 0:
|
if self.verbosity > 0:
|
||||||
print
|
print
|
||||||
print " Optional shell parameters:"
|
print " Optional shell parameters:"
|
||||||
parsed = self.parse_parameter_set(section, self.sh_optional, exception=False)
|
parsed = self.parse_parameter_set(section, self.sh_optional, exception=False)
|
||||||
self.shells[ind].update(parsed)
|
shell.update(parsed)
|
||||||
|
|
||||||
# Group required parameters
|
# Group required parameters
|
||||||
# Must be given if no group is explicitly specified
|
# Must be given if no group is explicitly specified
|
||||||
@ -268,14 +270,16 @@ class ConfigParameters:
|
|||||||
print
|
print
|
||||||
print " Required group parameters:"
|
print " Required group parameters:"
|
||||||
parsed = self.parse_parameter_set(section, self.gr_required, exception=False)
|
parsed = self.parse_parameter_set(section, self.gr_required, exception=False)
|
||||||
self.shells[ind].update(parsed)
|
shell.update(parsed)
|
||||||
|
|
||||||
# Group optional parameters
|
# Group optional parameters
|
||||||
if self.verbosity > 0:
|
if self.verbosity > 0:
|
||||||
print
|
print
|
||||||
print " Optional group parameters:"
|
print " Optional group parameters:"
|
||||||
parsed = self.parse_parameter_set(section, self.gr_optional, exception=False)
|
parsed = self.parse_parameter_set(section, self.gr_optional, exception=False)
|
||||||
self.shells[ind].update(parsed)
|
shell.update(parsed)
|
||||||
|
|
||||||
|
self.shells.append(shell)
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
#
|
#
|
||||||
@ -294,20 +298,66 @@ class ConfigParameters:
|
|||||||
|
|
||||||
self.ngroups = len(sec_groups)
|
self.ngroups = len(sec_groups)
|
||||||
|
|
||||||
|
self.groups = []
|
||||||
|
# Parse group parameters
|
||||||
|
for section in sec_groups:
|
||||||
|
group = {}
|
||||||
|
|
||||||
|
# Extract group index (FIXME: do we really need it?)
|
||||||
|
gr_patt2 = re.compile('group +([0-9]*)$', re.IGNORECASE)
|
||||||
|
try:
|
||||||
|
gr_ind = int(gr_patt2.match(section).groups()[0])
|
||||||
|
except (ValueError, AttributeError):
|
||||||
|
raise ValueError("Failed to extract group index from a group name: %s"%(section))
|
||||||
|
group['index'] = gr_ind
|
||||||
|
|
||||||
|
# Group required parameters
|
||||||
|
if self.verbosity > 0:
|
||||||
|
print
|
||||||
|
print " Required group parameters:"
|
||||||
|
parsed = self.parse_parameter_set(section, self.gr_required, exception=True)
|
||||||
|
group.update(parsed)
|
||||||
|
|
||||||
|
# Group optional parameters
|
||||||
|
if self.verbosity > 0:
|
||||||
|
print
|
||||||
|
print " Optional group parameters:"
|
||||||
|
parsed = self.parse_parameter_set(section, self.gr_optional, exception=False)
|
||||||
|
group.update(parsed)
|
||||||
|
|
||||||
|
self.groups.append(group)
|
||||||
|
|
||||||
|
# Sort groups according to indices defined in the config-file
|
||||||
|
if self.ngroups > 0:
|
||||||
|
self.groups.sort(key=lambda g: g['index'])
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
#
|
||||||
|
# groups_shells_consistency()
|
||||||
|
#
|
||||||
|
################################################################################
|
||||||
|
def groups_shells_consistency(self):
|
||||||
|
"""
|
||||||
|
Ensures consistency between groups and shells.
|
||||||
|
In particular:
|
||||||
|
- if no groups are explicitly defined and only shell is defined create
|
||||||
|
a group automatically
|
||||||
|
- check the existance of all shells referenced in the groups
|
||||||
|
- check that all shells are referenced in the groups
|
||||||
|
"""
|
||||||
# Special case: no groups is defined
|
# Special case: no groups is defined
|
||||||
if self.ngroups == 0:
|
if self.ngroups == 0:
|
||||||
# Check that 'nshells = 1'
|
# Check that 'nshells = 1'
|
||||||
assert self.nshells == 1, "At least one group must be defined if there are more than one shells."
|
assert self.nshells == 1, "At least one group must be defined if there are more than one shells."
|
||||||
|
|
||||||
# Otherwise create a single group taking group information from [Shell] section
|
# Otherwise create a single group taking group information from [Shell] section
|
||||||
self.groups = [{}]
|
self.groups.append({})
|
||||||
# Check that the single '[Shell]' section contains enough information
|
# Check that the single '[Shell]' section contains enough information
|
||||||
# and move it to the `groups` dictionary
|
# and move it to the `groups` dictionary
|
||||||
ind = self.sh_sections.keys()[0]
|
|
||||||
try:
|
try:
|
||||||
for par in self.gr_required.keys():
|
for par in self.gr_required.keys():
|
||||||
key = self.gr_required[par][0]
|
key = self.gr_required[par][0]
|
||||||
value = self.shells[ind].pop(key)
|
value = self.shells[0].pop(key)
|
||||||
self.groups[0][key] = value
|
self.groups[0][key] = value
|
||||||
except KeyError:
|
except KeyError:
|
||||||
message = "One [Shell] section is specified but no explicit [Group] section is provided."
|
message = "One [Shell] section is specified but no explicit [Group] section is provided."
|
||||||
@ -316,15 +366,66 @@ class ConfigParameters:
|
|||||||
raise KeyError(message)
|
raise KeyError(message)
|
||||||
|
|
||||||
# Do the same for optional group parameters, but do not raise an exception
|
# Do the same for optional group parameters, but do not raise an exception
|
||||||
for par in self.gr_required.keys():
|
for par in self.gr_optional.keys():
|
||||||
try:
|
try:
|
||||||
key = self.gr_required[par][0]
|
key = self.gr_optional[par][0]
|
||||||
value = self.shells[ind].pop(key)
|
value = self.shells[ind].pop(key)
|
||||||
self.groups[0][key] = value
|
self.groups[0][key] = value
|
||||||
except KeyError:
|
except KeyError:
|
||||||
continue
|
continue
|
||||||
|
# Add the index of the single shell into the group
|
||||||
|
self.groups.update({'shells': 0})
|
||||||
|
|
||||||
|
#
|
||||||
|
# Consistency checks
|
||||||
|
#
|
||||||
|
# Check the existance of shells referenced in the groups
|
||||||
|
def find_shell_by_user_index(uindex):
|
||||||
|
for ind, shell in enumerate(self.shells):
|
||||||
|
if shell['user_index'] == uindex:
|
||||||
|
return shell
|
||||||
|
raise KeyError
|
||||||
|
|
||||||
|
sh_inds = []
|
||||||
|
for group in self.groups:
|
||||||
|
gr_shells = group['shells']
|
||||||
|
for user_ind in gr_shells:
|
||||||
|
try:
|
||||||
|
ind, shell = find_shell_by_user_index(user_ind)
|
||||||
|
except KeyError:
|
||||||
|
raise Exception("Shell %i reference in group '%s' does not exist"%(user_ind, group['index'])
|
||||||
|
sh_inds.append(ind)
|
||||||
|
|
||||||
|
# If [Shell] section contains (potentiall conflicting) group parameters
|
||||||
|
# remove them and issue a warning
|
||||||
|
# First, required group parameters
|
||||||
|
for par in self.gr_required.keys():
|
||||||
|
try:
|
||||||
|
key = self.gr_required[par][0]
|
||||||
|
value = shell.pop(key)
|
||||||
|
mess = (" Redundant group parameter '%s' in [Shell] section"
|
||||||
|
" %i is discarded"%(par, user_ind))
|
||||||
|
issue_warning(mess)
|
||||||
|
except KeyError:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Second, optional group parameters
|
||||||
|
for par in self.gr_optional.keys():
|
||||||
|
try:
|
||||||
|
key = self.gr_optional[par][0]
|
||||||
|
value = shell.pop(key)
|
||||||
|
mess = (" Redundant group parameter '%s' in [Shell] section"
|
||||||
|
" %i is discarded"%(par, user_ind))
|
||||||
|
issue_warning(mess)
|
||||||
|
except KeyError:
|
||||||
|
continue
|
||||||
|
|
||||||
|
sh_refs_used = list(set(sh_inds))
|
||||||
|
sh_refs_used.sort()
|
||||||
|
|
||||||
|
# Check that all shells are referenced in the groups
|
||||||
|
assert sh_refs_used == range(self.nshells), "Some shells are not inside any of the groups"
|
||||||
|
|
||||||
self.groups.update({'shells': [self.shells[ind]]})
|
|
||||||
|
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
@ -340,8 +441,9 @@ class ConfigParameters:
|
|||||||
self.parse_shells()
|
self.parse_shells()
|
||||||
self.parse_groups()
|
self.parse_groups()
|
||||||
|
|
||||||
|
self.groups_shells_consistency()
|
||||||
|
|
||||||
# Output list of dictionaries
|
# Return a
|
||||||
output_pars = [{} for isec in xrange(nsections)]
|
output_pars = [{} for isec in xrange(nsections)]
|
||||||
for isec, section in enumerate(sections):
|
for isec, section in enumerate(sections):
|
||||||
print "Section: %s"%(section)
|
print "Section: %s"%(section)
|
||||||
|
@ -228,6 +228,7 @@ class TestSpecialParsers(unittest.TestCase):
|
|||||||
expected = {1: {'lshell': 2, 'ion_list': np.array([4, 5, 6, 7])},
|
expected = {1: {'lshell': 2, 'ion_list': np.array([4, 5, 6, 7])},
|
||||||
2: {'lshell': 1, 'ion_list': np.array([0, 1, 2, 3]),
|
2: {'lshell': 1, 'ion_list': np.array([0, 1, 2, 3]),
|
||||||
'tmatrix': np.array([[ 0., 1., 0.], [ 1., 0., 0.], [ 0., 0., 1.]])}}
|
'tmatrix': np.array([[ 0., 1., 0.], [ 1., 0., 0.], [ 0., 0., 1.]])}}
|
||||||
|
# ...lousy way to test equality of two dictionaries containing numpy arrays
|
||||||
self.assertSetEqual(set(res.keys()), set(expected.keys()))
|
self.assertSetEqual(set(res.keys()), set(expected.keys()))
|
||||||
|
|
||||||
arr = res[1].pop('ion_list')
|
arr = res[1].pop('ion_list')
|
||||||
@ -257,12 +258,37 @@ class TestSpecialParsers(unittest.TestCase):
|
|||||||
|
|
||||||
Scenarios:
|
Scenarios:
|
||||||
|
|
||||||
- **if** no [Group] section exists and more than one [Shell] section
|
|
||||||
is given **raise** AssertionError
|
|
||||||
- **if** a [Group] section does not contain all required parameters
|
- **if** a [Group] section does not contain all required parameters
|
||||||
**raise** Exception
|
**raise** Exception
|
||||||
- **if** two correct [Shell] sections are defined
|
- **if** a correct group section is defined **return** a list of dictionaries
|
||||||
**return** a dictionary of shell parameters
|
"""
|
||||||
|
# Scenario 1
|
||||||
|
# conf_pars = ConfigParameters('test6.cfg')
|
||||||
|
# err_mess = "At least one group"
|
||||||
|
# with self.assertRaisesRegexp(AssertionError, err_mess):
|
||||||
|
# conf_pars.parse_shells()
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
#
|
||||||
|
# test_groups_shells_consistency()
|
||||||
|
#
|
||||||
|
################################################################################
|
||||||
|
def test_groups_shells_consistency(self):
|
||||||
|
"""
|
||||||
|
Function:
|
||||||
|
|
||||||
|
def groups_shells_consistency(self)
|
||||||
|
|
||||||
|
Scenarios:
|
||||||
|
|
||||||
|
- **if** no [Group] section exists and more than one [Shell] section
|
||||||
|
is given **raise** AssertionError
|
||||||
|
- **if** no [Group] section exists but the single [Shell] section
|
||||||
|
does not contain required group information **raise** KeyError
|
||||||
|
- **if** a shell referenced in a group does not exist
|
||||||
|
**raise** Exception
|
||||||
|
- **if** not all defined shells are referenced in the groups
|
||||||
|
**raise** Exception
|
||||||
"""
|
"""
|
||||||
# Scenario 1
|
# Scenario 1
|
||||||
conf_pars = ConfigParameters('test6.cfg')
|
conf_pars = ConfigParameters('test6.cfg')
|
||||||
@ -271,6 +297,7 @@ class TestSpecialParsers(unittest.TestCase):
|
|||||||
conf_pars.parse_shells()
|
conf_pars.parse_shells()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
suite = unittest.TestLoader().loadTestsFromTestCase(TestSpecialParsers)
|
suite = unittest.TestLoader().loadTestsFromTestCase(TestSpecialParsers)
|
||||||
# unittest.TextTestRunner(verbosity=2, buffer=False).run(suite)
|
# unittest.TextTestRunner(verbosity=2, buffer=False).run(suite)
|
||||||
|
Loading…
Reference in New Issue
Block a user