Source code for molsysmt.basic.get

from molsysmt._private.digestion import digest
from molsysmt._private.variables import is_all
import numpy as np

[docs] @digest() def get(molecular_system, element='system', selection='all', structure_indices='all', mask=None, syntax='MolSysMT', get_missing_bonds=True, output_type='values', skip_digestion=False, **kwargs): """ Retrieving attribute values from a molecular system. This function retrieves values of one or more attributes from a molecular system (or from a selected subset of it), optionally specifying the hierarchical `element` level. Attributes to be returned are indicated via keyword flags in `**kwargs` (e.g., ``n_atoms=True``, ``coordinates=True``). Parameters ---------- molecular_system : molecular system Molecular system to query, in any of the :ref:`supported forms <Introduction_Forms>`. element : {'atom', 'group', 'component', 'molecule', 'chain', 'entity', 'bond', 'system'}, default 'system' Element level at which attributes are retrieved. selection : int, tuple, list, numpy.ndarray or str, default 'all' Subset of elements (interpreted at the level set by `element`) to use when retrieving attributes. Either a 0-based index collection or a selection string parsed according to :ref:`Introduction_Selection`. structure_indices : int, tuple, list, numpy.ndarray or 'all', default 'all' 0-based indices of structures to include in the query. Required for structural attributes (e.g., coordinates, box, time). mask : array-like of bool, optional Boolean mask to apply after selection and structure filtering. Must match the shape of the selected elements. syntax : str, default 'MolSysMT' Selection syntax used when `selection` is a string. See :ref:`Introduction_Selection`. get_missing_bonds : bool, default False Whether to infer and return bond information on the fly when bond-related attributes are requested and the input form lacks explicit connectivity. The inference uses the form backend’s heuristics (distance/chemistry-aware thresholds). output_type : {'values', 'dictionary'}, default 'values' Output format: - ``value` — **convenience mode**: * if exactly **one** attribute is requested, return its value directly; * if **multiple** attributes are requested, return a **tuple** of values following the order in which the attributes were provided in `**kwargs`. - ``'dictionary'`` — return a dictionary mapping attribute names to values. skip_digestion : bool, default False Whether to skip MolSysMT’s internal argument digestion mechanism. MolSysMT includes a built-in digestion system that validates and normalizes function arguments. This process checks types, shapes, and values, and automatically adjusts them when possible to meet expected formats. Setting `skip_digestion=True` disables this process, which may improve performance in workflows where inputs are already validated. Use with caution: only set this to `True` if you are certain all input arguments are correct and consistent **kwargs Attribute flags selecting which values to retrieve (e.g., ``n_atoms=True``, ``coordinates=True``, ``time=True``, ``box=True``, etc.). Only attributes flagged as `True` are returned. Returns ------- Any or tuple or dict or None Depending on `output_type`: - If ``output_type == 'values'`` and a single attribute is requested: the attribute value. This value can be `None` if the attribute is not found in the system. - If ``output_type == 'values'`` and multiple attributes are requested: a tuple with values in the order given by `**kwargs`. - If ``output_type == 'dictionary'``: a dictionary ``{attribute_name: value}``. Raises ------ NotSupportedFormError If the molecular system has an unsupported form. ArgumentError If any input argument is invalid or inconsistent. Notes ----- - Supported molecular-system forms are summarized in :ref:`Introduction_Forms`. - Selection strings must follow one of the syntaxes described in :ref:`Introduction_Selection`. See Also -------- :func:`molsysmt.basic.select` Select elements from a molecular system. :func:`molsysmt.basic.get_attributes` Get the list of available attributes for a molecular system. Examples -------- >>> import molsysmt as msm >>> from molsysmt import systems >>> molsys = systems['T4 lysozyme L99A']['181l.h5msm'] >>> msm.get(molsys, element='group', selection=[10,11,12], n_atoms=True) [9, 4, 8] >>> msm.get(molsys, element='molecule', selection='molecule_type=="water"', n_molecules=True) 136 >>> msm.get(molsys, element='bond', selection=[0,1,2,3,4], bonded_atoms=True) [0, 1, 2, 3, 4, 8] .. admonition:: Tutorial with more examples See the following tutorial for a practical demonstration of how to use this function, along with additional examples: :ref:`Tutorial_Get`. .. versionadded:: 1.0.0 """ from .. import select, where_is_attribute, get_form, convert from molsysmt.form import _dict_modules from molsysmt.attribute import attributes, bonds_are_required_to_get_attribute from molsysmt.attribute import is_topological_attribute, is_structural_attribute form = get_form(molecular_system) if isinstance(form, (list, tuple)): attributes_filter = _dict_modules[form[0]].attributes.copy() for aux_form in form[1:]: for aux_attribute, aux_bool in _dict_modules[aux_form].attributes.items(): if aux_bool: attributes_filter[aux_attribute]=True else: attributes_filter = _dict_modules[form].attributes in_attributes = [] for key in kwargs.keys(): if kwargs[key]: in_attributes.append(key) if not isinstance(molecular_system, (list, tuple)): molecular_system = [molecular_system] form = [form] # Correction from element='system' to element='atom' if: # selection is not 'all' or indices is not None # all attributes are attributable to atoms if (element=='system') and (not is_all(selection)): from molsysmt.attribute import attributes as _attributes attributes_from_atom = [] attributes_from_system = [] for ii in in_attributes: if 'atom' in _attributes[ii]['get_from']: attributes_from_atom.append(ii) elif 'system' in _attributes[ii]['get_from']: attributes_from_system.append(ii) aux_result_atoms = {} aux_result_system = {} if len(attributes_from_atom) > 0: aux_result_atoms = get(molecular_system, element='atom', selection=selection, structure_indices=structure_indices, mask=mask, syntax=syntax, get_missing_bonds=get_missing_bonds, output_type='dictionary', skip_digestion=True, **{ii:True for ii in attributes_from_atom}) if len(attributes_from_system) > 0: aux_result_system = get(molecular_system, element='system', selection='all', structure_indices=structure_indices, get_missing_bonds=get_missing_bonds, output_type='dictionary', skip_digestion=True, **{ii:True for ii in attributes_from_system}) aux_result = aux_result_atoms | aux_result_system output = [] for ii in in_attributes: output.append(aux_result[ii]) if output_type=='values': if len(output) == 1: return output[0] else: return output elif output_type=='dictionary': return dict(zip(in_attributes, output)) if not is_all(selection): indices = select(molecular_system, element=element, selection=selection, mask=mask, syntax=syntax, skip_digestion=True) else: if (mask is None) or (is_all(mask)): indices = 'all' else: indices = select(molecular_system, element=element, selection=mask, syntax=syntax, skip_digestion=True) piped_molecular_systems, piped_attributes = _piped_molecular_system(molecular_system, element, in_attributes) if piped_molecular_systems is None: output = [] for in_attribute in in_attributes: if attributes_filter[in_attribute]: dict_indices = {} if element != 'system': if attributes[in_attribute]['runs_on_elements']: dict_indices['indices'] = indices if attributes[in_attribute]['runs_on_structures']: dict_indices['structure_indices'] = structure_indices aux_item, aux_form = where_is_attribute(molecular_system, in_attribute, skip_digestion=True) if aux_item is None: result = None else: aux_get = getattr(_dict_modules[aux_form], f'get_{in_attribute}_from_{element}') result = aux_get(aux_item, **dict_indices) else: result = None output.append(result) else: output_dictionary = {} for aux_molecular_system, aux_attributes in zip(piped_molecular_systems, piped_attributes): if aux_molecular_system is None: aux_molecular_system = molecular_system aux_dict = get(aux_molecular_system, element=element, selection=indices, structure_indices=structure_indices, mask=mask, syntax=syntax, get_missing_bonds=get_missing_bonds, output_type='dictionary', skip_digestion=False, **{ii:True for ii in aux_attributes}) output_dictionary.update(aux_dict) output = [] for in_attribute in in_attributes: output.append(output_dictionary[in_attribute]) if output_type=='values': if len(output) == 1: return output[0] else: return output elif output_type=='dictionary': return dict(zip(in_attributes, output))
def _piped_molecular_system(molecular_system, element, in_attributes): from .. import select, where_is_attribute, get_form, convert from molsysmt.form import _dict_modules from molsysmt.attribute import attributes, bonds_are_required_to_get_attribute from molsysmt.attribute import is_topological_attribute, is_structural_attribute topological_pipes = {} structural_pipes = {} any_pipes = {} form = get_form(molecular_system) if not isinstance(molecular_system, (list, tuple)): molecular_system = [molecular_system] form = [form] for aux_form in form: topological_pipes[aux_form] = getattr(_dict_modules[aux_form], f'piped_topological_attribute') structural_pipes[aux_form] = getattr(_dict_modules[aux_form], f'piped_structural_attribute') any_pipes[aux_form] = getattr(_dict_modules[aux_form], f'piped_any_attribute') not_piped = all([ii is None for ii in topological_pipes.values()]) & \ all([ii is None for ii in structural_pipes.values()]) & \ all([ii is None for ii in any_pipes.values()]) if not_piped or len(in_attributes)==1: return None, None else: aux_topological_attributes = [] aux_topological_pipes = [] aux_structural_attributes = [] aux_structural_pipes = [] aux_any_pipes = [] bonds_required_by_attributes = False for in_attribute in in_attributes: bonds_required_by_attributes += bonds_are_required_to_get_attribute(in_attribute, element, skip_digestion=True) if is_topological_attribute(in_attribute, skip_digestion=True): aux_topological_attributes.append(in_attribute) _, aux_form = where_is_attribute(molecular_system, in_attribute, skip_digestion=True) if aux_form is not None: if topological_pipes[aux_form] is not None: if topological_pipes[aux_form] not in aux_topological_pipes: aux_topological_pipes.append(topological_pipes[aux_form]) if any_pipes[aux_form] is not None: if any_pipes[aux_form] not in aux_any_pipes: aux_any_pipes.append(any_pipes[aux_form]) elif is_structural_attribute(in_attribute, skip_digestion=True): _, aux_form = where_is_attribute(molecular_system, in_attribute) aux_structural_attributes.append(in_attribute) if aux_form is not None: if structural_pipes[aux_form] is not None: if structural_pipes[aux_form] not in aux_structural_pipes: aux_structural_pipes.append(structural_pipes[aux_form]) if any_pipes[aux_form] is not None: if any_pipes[aux_form] not in aux_any_pipes: aux_any_pipes.append(any_pipes[aux_form]) n_top_pipes = len(aux_topological_pipes) n_str_pipes = len(aux_structural_pipes) n_any_pipes = len(aux_any_pipes) n_top_atts = len(aux_topological_attributes) n_str_atts = len(aux_structural_attributes) output_systems = [] output_attributes = [] if n_top_pipes==0 and n_str_pipes==0 and n_any_pipes==0: output_systems = None output_attributes = None elif n_top_atts>0 and n_str_atts==0: if n_top_pipes==1: aux_molecular_system = convert(molecular_system, to_form=aux_topological_pipes[0], get_missing_bonds=bonds_required_by_attributes, skip_digestion=True) else: aux_molecular_system = convert(molecular_system, to_form='molsysmt.Topology', get_missing_bonds=bonds_required_by_attributes, skip_digestion=True) output_systems.append(aux_molecular_system) output_attributes.append(aux_topological_attributes) elif n_top_atts==0 and n_str_atts>0: if n_str_pipes == 1: aux_molecular_system = convert(molecular_system, to_form=aux_structural_pipes[0], skip_digestion=True) else: aux_molecular_system = convert(molecular_system, to_form='molsysmt.Structures', skip_digestion=True) output_systems.append(aux_molecular_system) output_attributes.append(aux_structural_attributes) else: if n_any_pipes == 1: aux_molecular_system = convert(molecular_system, to_form=aux_any_pipes[0], get_missing_bonds=bonds_required_by_attributes, skip_digestion=True) output_systems.append(aux_molecular_system) output_attributes.append(aux_topological_attributes+aux_structural_attributes) elif n_any_pipes > 1: aux_molecular_system = convert(molecular_system, to_form='molsysmt.MolSys', get_missing_bonds=bonds_required_by_attributes, skip_digestion=True) output_systems.append(aux_molecular_system) output_attributes.append(aux_topological_attributes+aux_structural_attributes) elif n_any_pipes == 0: if n_top_pipes == 1: aux_molecular_system = convert(molecular_system, to_form=aux_topological_pipes[0], get_missing_bonds=bonds_required_by_attributes, skip_digestion=True) elif n_top_pipes > 1: aux_molecular_system = convert(molecular_system, to_form='molsysmt.Topology', get_missing_bonds=bonds_required_by_attributes, skip_digestion=True) else: aux_molecular_system = None output_systems.append(aux_molecular_system) output_attributes.append(aux_topological_attributes) if n_str_pipes == 1: aux_molecular_system = convert(molecular_system, to_form=aux_structural_pipes[0], skip_digestion=True) elif n_str_pipes > 1: aux_molecular_system = convert(molecular_system, to_form='molsysmt.Structures', skip_digestion=True) else: aux_molecular_system = None output_systems.append(aux_molecular_system) output_attributes.append(aux_structural_attributes) return output_systems, output_attributes