Commit ccb98160 authored by eric pellegrini's avatar eric pellegrini
Browse files

Modified the configure method by removing the configuration argument.

This one is now set at __init__
parent 2d9a92a9
...@@ -33,8 +33,8 @@ Created on Mar 30, 2015 ...@@ -33,8 +33,8 @@ Created on Mar 30, 2015
import collections import collections
import operator import operator
import numpy
from MDANSE import ELEMENTS
from MDANSE.Framework.UserDefinitionStore import UD_STORE from MDANSE.Framework.UserDefinitionStore import UD_STORE
from MDANSE.Framework.Configurators.IConfigurator import IConfigurator, ConfiguratorError from MDANSE.Framework.Configurators.IConfigurator import IConfigurator, ConfiguratorError
from MDANSE.Framework.AtomSelectionParser import AtomSelectionParser from MDANSE.Framework.AtomSelectionParser import AtomSelectionParser
...@@ -53,27 +53,37 @@ class AtomSelectionConfigurator(IConfigurator): ...@@ -53,27 +53,37 @@ class AtomSelectionConfigurator(IConfigurator):
Without any selection, all the atoms stored into the trajectory file will be selected. Without any selection, all the atoms stored into the trajectory file will be selected.
:note: this configurator depends on 'trajectory' and 'grouping_level' configurators to be configured After the call to :py:meth:`~MDANSE.Framework.Configurators.AtomSelectionConfigurator.AtomSelectionConfigurator.configure` method
the following keys will be available for this configurator
#. value: the input value used to configure this configurator
#. indexes: the sorted (in increasing order) MMTK indexes of the selected atoms
#. n_selected_atoms: the number of selected atoms
#. elements: a nested-list of the chemical symbols of the selected atoms. The size of the nested list depends on the
grouping_level selected via :py:class:`~MDANSE.Framework.Configurators.GroupingLevelConfigurator.GroupingLevelConfigurator`
configurator.
:note: this configurator depends on :py:class:`~MDANSE.Framework.Configurators.MMTKTrajectoryConfigurator.MMTKTrajectoryConfigurator`
and :py:class:`~MDANSE.Framework.Configurators.GroupingLevelConfigurator.GroupingLevelConfigurator` configurators to be configured
''' '''
type = 'atom_selection' type = 'atom_selection'
_default = "all" _default = "all"
def configure(self, configuration, value): def configure(self, value):
''' '''
Configure an input value. Configure an input value.
The value must be a string that can be either an atom selection string or a valid user The value must be a string that can be either an atom selection string or a valid user
definition. definition.
:param configuration: the current configuration
:type configuration: a MDANSE.Framework.Configurable.Configurable object
:param value: the input value :param value: the input value
:type value: str :type value: str
''' '''
trajConfig = configuration[self._dependencies['trajectory']] trajConfig = self._configurable[self._dependencies['trajectory']]
if value is None: if value is None:
value = ['all'] value = ['all']
...@@ -86,96 +96,50 @@ class AtomSelectionConfigurator(IConfigurator): ...@@ -86,96 +96,50 @@ class AtomSelectionConfigurator(IConfigurator):
self["value"] = value self["value"] = value
self["indexes"] = [] indexes = set()
for v in value: for v in value:
if UD_STORE.has_definition(trajConfig["basename"],"atom_selection",v): if UD_STORE.has_definition(trajConfig["basename"],"atom_selection",v):
ud = UD_STORE.get_definition(trajConfig["basename"],"atom_selection",v) ud = UD_STORE.get_definition(trajConfig["basename"],"atom_selection",v)
self["indexes"].extend(ud["indexes"]) indexes.update(ud["indexes"])
else: else:
parser = AtomSelectionParser(trajConfig["instance"].universe) parser = AtomSelectionParser(trajConfig["instance"].universe)
self["indexes"].extend(parser.parse(v)) indexes.update(parser.parse(v))
self["indexes"].sort() indexes = sorted(list(indexes))
self["n_selected_atoms"] = len(self["indexes"])
atoms = sorted(trajConfig["universe"].atomList(), key = operator.attrgetter('index')) atoms = sorted(trajConfig["universe"].atomList(), key = operator.attrgetter('index'))
selectedAtoms = [atoms[idx] for idx in self["indexes"]] selectedAtoms = [atoms[idx] for idx in indexes]
self["elements"] = [[at.symbol] for at in selectedAtoms]
if self._dependencies.has_key("grouping_level"): self["selection_length"] = len(indexes)
self.group(selectedAtoms, configuration[self._dependencies['grouping_level']]['value']) self['elements'] = [[at.symbol] for at in selectedAtoms]
else: self['indexes'] = [[idx] for idx in indexes]
self.group(selectedAtoms) self['names'] = [at.symbol for at in selectedAtoms]
self['unique_names'] = sorted(set(self['names']))
self.set_contents() self['masses'] = [[ELEMENTS[n,'atomic_weight']] for n in self['names']]
@staticmethod
def find_parent(atom, level):
'''
Retrieve recursively the parent of a given MMTK atom at a given level.
For example, a level of 1 will return the direct parent of the atom.
:note: this is a static method def get_natoms(self):
:param atom: the atom for which the parent is searched for
:type atom: MMTK.Atom object
:param level: the level of the parent
:type level: int
'''
for _ in range(level):
atom = atom.parent
return atom
def group(self, atoms, level="atom"):
'''
Group the selected atoms according to a given granularity and update
the configurator with the grouping results.
:param atoms: the atoms for nAtomsPerElement = {}
:type atoms: list of MMTK.Atom for v in self["names"]:
:param level: the level of granularity at which the atoms should be grouped if nAtomsPerElement.has_key(v):
:type level: str nAtomsPerElement[v] += 1
''' else:
nAtomsPerElement[v] = 1
groups = collections.OrderedDict()
for at in atoms:
lvl = LEVELS[level][at.topLevelChemicalObject().__class__.__name__.lower()]
parent = self.find_parent(at,lvl)
groups.setdefault(parent,[]).append(at.index)
self["groups"] = groups.values()
self["n_groups"] = len(self["groups"])
if level != "atom":
self["elements"] = [["dummy"]]*self["n_groups"]
self["level"] = level
self.set_contents()
def set_contents(self): return nAtomsPerElement
'''
Sets the contents of the atom selection.
'''
self["contents"] = collections.OrderedDict() def get_indexes(self):
self['index_to_symbol'] = collections.OrderedDict()
for i, group in enumerate(self["elements"]):
for j, el in enumerate(group):
self["contents"].setdefault(el,[]).append(self["groups"][i][j])
self['index_to_symbol'][self["groups"][i][j]] = el
for k,v in self["contents"].items(): indexesPerElement = {}
self["contents"][k] = numpy.array(v,dtype=numpy.int32) for i,v in enumerate(self["names"]):
if indexesPerElement.has_key(v):
indexesPerElement[v].extend(self['indexes'][i])
else:
indexesPerElement[v] = self['indexes'][i]
self["n_atoms_per_element"] = dict([(k,len(v)) for k,v in self["contents"].items()]) return indexesPerElement
self['n_selected_elements'] = len(self["contents"])
def get_information(self): def get_information(self):
''' '''
...@@ -190,8 +154,6 @@ class AtomSelectionConfigurator(IConfigurator): ...@@ -190,8 +154,6 @@ class AtomSelectionConfigurator(IConfigurator):
info = [] info = []
info.append("Number of selected atoms:%d" % self["n_selected_atoms"]) info.append("Number of selected atoms:%d" % self["n_selected_atoms"])
info.append("Level of selection:%s" % self["level"])
info.append("Number of selected groups:%d" % self["n_groups"])
info.append("Selected elements:%s" % self["contents"].keys()) info.append("Selected elements:%s" % self["contents"].keys())
return "\n".join(info) return "\n".join(info)
\ No newline at end of file
...@@ -53,7 +53,7 @@ class AtomTransmutationConfigurator(IConfigurator): ...@@ -53,7 +53,7 @@ class AtomTransmutationConfigurator(IConfigurator):
_default = None _default = None
def configure(self, configuration, value): def configure(self, value):
''' '''
Configure an input value. Configure an input value.
...@@ -65,8 +65,6 @@ class AtomTransmutationConfigurator(IConfigurator): ...@@ -65,8 +65,6 @@ class AtomTransmutationConfigurator(IConfigurator):
selection to the target chemical element stored in the 2nd element selection to the target chemical element stored in the 2nd element
#. str: the transmutation will be performed by reading the corresponding user definition #. str: the transmutation will be performed by reading the corresponding user definition
:param configuration: the current configuration
:type configuration: MDANSE.Framework.Configurable.Configurable
:param value: the input value :param value: the input value
:type value: None or (str,str)-dict or str :type value: None or (str,str)-dict or str
''' '''
...@@ -80,14 +78,12 @@ class AtomTransmutationConfigurator(IConfigurator): ...@@ -80,14 +78,12 @@ class AtomTransmutationConfigurator(IConfigurator):
if not isinstance(value,(list,tuple)): if not isinstance(value,(list,tuple)):
raise ConfiguratorError("Invalid input value.") raise ConfiguratorError("Invalid input value.")
self["atom_selection"] = configuration[self._dependencies['atom_selection']] trajConfig = self._configurable[self._dependencies['trajectory']]
if self["atom_selection"]["level"] != "atom":
raise ConfiguratorError("the atom transmutation can only be set with a grouping level set to %r" % 'atom', self)
trajConfig = configuration[self._dependencies['trajectory']]
parser = AtomSelectionParser(trajConfig["instance"].universe) parser = AtomSelectionParser(trajConfig["instance"].universe)
self._nTransmutatedAtoms = 0
for expression,element in value: for expression,element in value:
# Otherwise, it must be a string that will be found as a user-definition keys # Otherwise, it must be a string that will be found as a user-definition keys
...@@ -96,17 +92,18 @@ class AtomTransmutationConfigurator(IConfigurator): ...@@ -96,17 +92,18 @@ class AtomTransmutationConfigurator(IConfigurator):
if UD_STORE.has_definition(trajConfig["basename"],"atom_selection",expression): if UD_STORE.has_definition(trajConfig["basename"],"atom_selection",expression):
ud = UD_STORE.get_definition(trajConfig["basename"],"atom_selection",expression) ud = UD_STORE.get_definition(trajConfig["basename"],"atom_selection",expression)
self.transmutate(configuration, ud["indexes"], element) indexes = ud["indexes"]
else: else:
indexes = parser.parse(expression) indexes = parser.parse(expression)
self.transmutate(configuration, indexes, element)
def transmutate(self, configuration, selection, element): self.transmutate(indexes, element)
self._nTransmutatedAtoms += len(indexes)
def transmutate(self, selection, element):
''' '''
Transmutates a set of atoms to a given element Transmutates a set of atoms to a given element
:param configuration: the current configuration
:type configuration: MDANSE.Framework.Configurable.Configurable
:param selection: the indexes of the atoms to be transmutated :param selection: the indexes of the atoms to be transmutated
:type selection: list of int :type selection: list of int
:param element: the symbol of the element to which the selected atoms should be transmutated :param element: the symbol of the element to which the selected atoms should be transmutated
...@@ -116,13 +113,13 @@ class AtomTransmutationConfigurator(IConfigurator): ...@@ -116,13 +113,13 @@ class AtomTransmutationConfigurator(IConfigurator):
if element not in ELEMENTS: if element not in ELEMENTS:
raise ConfiguratorError("the element %r is not registered in the database" % element, self) raise ConfiguratorError("the element %r is not registered in the database" % element, self)
atomSelConfigurator = self._configurable[self._dependencies['atom_selection']]
for idx in selection: for idx in selection:
pos = self["atom_selection"]["groups"].index([idx]) atomSelConfigurator["names"][idx] = element
self["atom_selection"]["elements"][pos] = [element] atomSelConfigurator["elements"][idx] = [element]
# Update the current configuration according to the changes triggered by atomSelConfigurator['unique_names'] = sorted(set(atomSelConfigurator['names']))
# atom transumutation
configuration[self._dependencies['atom_selection']].set_contents()
def get_information(self): def get_information(self):
''' '''
...@@ -136,6 +133,6 @@ class AtomTransmutationConfigurator(IConfigurator): ...@@ -136,6 +133,6 @@ class AtomTransmutationConfigurator(IConfigurator):
return "Not configured yet" return "Not configured yet"
if self["value"] is None: if self["value"] is None:
return "No atoms selected for deuteration" return "No atoms selected for transmutation"
return "Number of selected atoms for deuteration:%d\n" % self["atom_selection"]["n_selected_atoms"] return "Number of transmutated atoms:%d\n" % self._nTransmutatedAtoms
\ No newline at end of file \ No newline at end of file
...@@ -47,7 +47,7 @@ class AtomsListConfigurator(IConfigurator): ...@@ -47,7 +47,7 @@ class AtomsListConfigurator(IConfigurator):
_default = None _default = None
def __init__(self, name, nAtoms=2, **kwargs): def __init__(self, configurable, name, nAtoms=2, **kwargs):
''' '''
Initializes the configurator. Initializes the configurator.
...@@ -57,7 +57,7 @@ class AtomsListConfigurator(IConfigurator): ...@@ -57,7 +57,7 @@ class AtomsListConfigurator(IConfigurator):
:type nAtoms: int :type nAtoms: int
''' '''
IConfigurator.__init__(self, name, **kwargs) IConfigurator.__init__(self, configurable, name, **kwargs)
self._nAtoms = nAtoms self._nAtoms = nAtoms
...@@ -66,20 +66,18 @@ class AtomsListConfigurator(IConfigurator): ...@@ -66,20 +66,18 @@ class AtomsListConfigurator(IConfigurator):
return self._nAtoms return self._nAtoms
def configure(self, configuration, value): def configure(self, value):
''' '''
Configure an input value. Configure an input value.
The value must be a string that can be either an atom selection string or a valid user The value must be a string that can be either an atom selection string or a valid user
definition. definition.
:param configuration: the current configuration
:type configuration: a MDANSE.Framework.Configurable.Configurable object
:param value: the input value :param value: the input value
:type value: str :type value: str
''' '''
trajConfig = configuration[self._dependencies['trajectory']] trajConfig = self._configurable[self._dependencies['trajectory']]
if UD_STORE.has_definition(trajConfig["basename"],"%d_atoms_list" % self._nAtoms,value): if UD_STORE.has_definition(trajConfig["basename"],"%d_atoms_list" % self._nAtoms,value):
molecule,atoms = UD_STORE.get_definition(trajConfig["basename"],"%d_atoms_list" % self._nAtoms,value) molecule,atoms = UD_STORE.get_definition(trajConfig["basename"],"%d_atoms_list" % self._nAtoms,value)
......
...@@ -47,7 +47,7 @@ class AxisSelection(IConfigurator): ...@@ -47,7 +47,7 @@ class AxisSelection(IConfigurator):
_default = None _default = None
def configure(self, configuration, value): def configure(self, value):
''' '''
Configure an input value. Configure an input value.
...@@ -64,7 +64,7 @@ class AxisSelection(IConfigurator): ...@@ -64,7 +64,7 @@ class AxisSelection(IConfigurator):
:type value: tuple or str :type value: tuple or str
''' '''
trajConfig = configuration[self._dependencies['trajectory']] trajConfig = self._configurable[self._dependencies['trajectory']]
if UD_STORE.has_definition(trajConfig["basename"],"axis_selection",value): if UD_STORE.has_definition(trajConfig["basename"],"axis_selection",value):
ud = UD_STORE.get_definition(trajConfig["basename"],"axis_selection",value) ud = UD_STORE.get_definition(trajConfig["basename"],"axis_selection",value)
......
...@@ -47,7 +47,7 @@ class BasisSelection(IConfigurator): ...@@ -47,7 +47,7 @@ class BasisSelection(IConfigurator):
_default = None _default = None
def configure(self, configuration, value): def configure(self, value):
''' '''
Configure an input value. Configure an input value.
...@@ -58,15 +58,13 @@ class BasisSelection(IConfigurator): ...@@ -58,15 +58,13 @@ class BasisSelection(IConfigurator):
keys are the names of three atoms of the molecule that will be used to define respectively the origin, the X and Y axis of the basis keys are the names of three atoms of the molecule that will be used to define respectively the origin, the X and Y axis of the basis
#. str: the axis selection will be performed by reading the corresponding user definition. #. str: the axis selection will be performed by reading the corresponding user definition.
:param configuration: the current configuration
:type configuration: MDANSE.Framework.Configurable.Configurable
:param value: the input value :param value: the input value
:type value: tuple or str :type value: tuple or str
:note: this configurator depends on 'trajectory' configurator to be configured :note: this configurator depends on 'trajectory' configurator to be configured
''' '''
trajConfig = configuration[self._dependencies['trajectory']] trajConfig = self._configurable[self._dependencies['trajectory']]
if UD_STORE.has_definition(trajConfig["basename"],"basis_selection",value): if UD_STORE.has_definition(trajConfig["basename"],"basis_selection",value):
ud = UD_STORE.get_definition(trajConfig["basename"],"basis_selection",value) ud = UD_STORE.get_definition(trajConfig["basename"],"basis_selection",value)
......
...@@ -47,7 +47,7 @@ class BooleanConfigurator(IConfigurator): ...@@ -47,7 +47,7 @@ class BooleanConfigurator(IConfigurator):
_shortCuts = {True : True, "true" : True , "yes" : True, "y" : True, "1" : True, 1 : True, _shortCuts = {True : True, "true" : True , "yes" : True, "y" : True, "1" : True, 1 : True,
False : False, "false" : False, "no" : False, "n" : False, "0" : False, 0 : False} False : False, "false" : False, "no" : False, "n" : False, "0" : False, 0 : False}
def configure(self, configuration, value): def configure(self, value):
''' '''
Configure an input value. Configure an input value.
......
...@@ -42,7 +42,7 @@ class ComplexNumberConfigurator(IConfigurator): ...@@ -42,7 +42,7 @@ class ComplexNumberConfigurator(IConfigurator):
_default = 0 _default = 0
def __init__(self, name, mini=None, maxi=None, choices=None, **kwargs): def __init__(self, configurable, name, mini=None, maxi=None, choices=None, **kwargs):
''' '''
Initializes the configurator. Initializes the configurator.
...@@ -57,7 +57,7 @@ class ComplexNumberConfigurator(IConfigurator): ...@@ -57,7 +57,7 @@ class ComplexNumberConfigurator(IConfigurator):
''' '''
# The base class constructor. # The base class constructor.
IConfigurator.__init__(self, name, **kwargs) IConfigurator.__init__(self, configurable, name, **kwargs)
self._mini = float(mini) if mini is not None else None self._mini = float(mini) if mini is not None else None
...@@ -65,12 +65,10 @@ class ComplexNumberConfigurator(IConfigurator): ...@@ -65,12 +65,10 @@ class ComplexNumberConfigurator(IConfigurator):
self._choices = choices if choices is not None else [] self._choices = choices if choices is not None else []
def configure(self, configuration, value): def configure(self, value):
''' '''
Configure an input value. Configure an input value.
:param configuration: the current configuration.
:type configuration: a MDANSE.Framework.Configurable.Configurable object
:param value: the input complex number. :param value: the input complex number.
:type value: complex :type value: complex
''' '''
......
...@@ -41,7 +41,7 @@ class FloatConfigurator(IConfigurator): ...@@ -41,7 +41,7 @@ class FloatConfigurator(IConfigurator):
_default = 0 _default = 0
def __init__(self, name, mini=None, maxi=None, choices=None, **kwargs): def __init__(self, configurable, name, mini=None, maxi=None, choices=None, **kwargs):
''' '''
Initializes the configurator. Initializes the configurator.
...@@ -56,7 +56,7 @@ class FloatConfigurator(IConfigurator): ...@@ -56,7 +56,7 @@ class FloatConfigurator(IConfigurator):
''' '''
# The base class constructor. # The base class constructor.
IConfigurator.__init__(self, name, **kwargs) IConfigurator.__init__(self, configurable, name, **kwargs)
self._mini = float(mini) if mini is not None else None self._mini = float(mini) if mini is not None else None
...@@ -64,12 +64,10 @@ class FloatConfigurator(IConfigurator): ...@@ -64,12 +64,10 @@ class FloatConfigurator(IConfigurator):
self._choices = choices if choices is not None else [] self._choices = choices if choices is not None else []
def configure(self, configuration, value): def configure(self, value):
''' '''
Configure an input value. Configure an input value.
:param configuration: the current configuration
:type configuration: a MDANSE.Framework.Configurable.Configurable object