def test_get_tagattrib_xpath_case_insensitivity():
    """
    Test that the selection works with case insensitivity
    """
    from masci_tools.util.schema_dict_util import get_tag_xpath, get_attrib_xpath

    schema_dict = schema_dict_34

    assert get_tag_xpath(schema_dict,
                         'bzIntegration') == '/fleurInput/cell/bzIntegration'
    assert get_tag_xpath(schema_dict,
                         'BZINTEGRATION') == '/fleurInput/cell/bzIntegration'
    assert get_tag_xpath(schema_dict,
                         'bzintegration') == '/fleurInput/cell/bzIntegration'
    assert get_tag_xpath(schema_dict,
                         'bZInTegrAtIon') == '/fleurInput/cell/bzIntegration'

    assert get_attrib_xpath(
        schema_dict,
        'jspins') == '/fleurInput/calculationSetup/magnetism/@jspins'
    assert get_attrib_xpath(
        schema_dict,
        'JSPINS') == '/fleurInput/calculationSetup/magnetism/@jspins'
    assert get_attrib_xpath(
        schema_dict,
        'jSpInS') == '/fleurInput/calculationSetup/magnetism/@jspins'
Exemple #2
0
def delete_att(xmltree, schema_dict, attrib_name, complex_xpath=None, occurrences=None, **kwargs):
    """
    This method deletes a attribute with a uniquely identified xpath.

    :param xmltree: an xmltree that represents inp.xml
    :param schema_dict: InputSchemaDict containing all information about the structure of the input
    :param tag: str of the attribute to delete
    :param complex_xpath: an optional xpath to use instead of the simple xpath for the evaluation
    :param occurrences: int or list of int. Which occurence of the parent nodes to delete a attribute.
                        By default all nodes are used.

    Kwargs:
        :param tag_name: str, name of the tag where the attribute should be parsed
        :param contains: str, this string has to be in the final path
        :param not_contains: str, this string has to NOT be in the final path
        :param exclude: list of str, here specific types of attributes can be excluded
                        valid values are: settable, settable_contains, other

    :returns: xmltree with deleted attributes
    """
    from masci_tools.util.xml.xml_setters_basic import xml_delete_att
    from masci_tools.util.xml.common_functions import check_complex_xpath, split_off_attrib

    base_xpath = get_attrib_xpath(schema_dict, attrib_name, **kwargs)

    tag_xpath, attrib_name = split_off_attrib(base_xpath)

    if complex_xpath is None:
        complex_xpath = tag_xpath

    check_complex_xpath(xmltree, tag_xpath, complex_xpath)

    xmltree = xml_delete_att(xmltree, complex_xpath, attrib_name, occurrences=occurrences)

    return xmltree
Exemple #3
0
def set_inpchanges(xmltree, schema_dict, change_dict, path_spec=None):
    """
    This method sets all the attribute and texts provided in the change_dict.

    The first occurrence of the attribute/tag is set

    :param xmltree: xml tree that represents inp.xml
    :param schema_dict: InputSchemaDict containing all information about the structure of the input
    :params change_dict: dictionary {attrib_name : value} with all the wanted changes.
    :param path_spec: dict, with ggf. necessary further specifications for the path of the attribute

    An example of change_dict::

            change_dict = {'itmax' : 1,
                           'l_noco': True,
                           'ctail': False,
                           'l_ss': True}

    :returns: an xmltree of the inp.xml file with changes.
    """
    from masci_tools.util.xml.xml_setters_xpaths import xml_set_first_attrib_value, xml_set_first_text
    from masci_tools.util.xml.common_functions import split_off_attrib
    from masci_tools.util.case_insensitive_dict import CaseInsensitiveDict

    if path_spec is None:
        path_spec = {}
    path_spec = CaseInsensitiveDict(path_spec)

    for key, change_value in change_dict.items():

        #Special alias for xcFunctional since name is not a very telling attribute name
        if key == 'xcFunctional':
            key = 'name'

        if key not in schema_dict['attrib_types'] and key not in schema_dict['simple_elements']:
            raise ValueError(f"You try to set the key:'{key}' to : '{change_value}', but the key is unknown"
                             ' to the fleur plug-in')

        text_attrib = key not in schema_dict['attrib_types']

        key_spec = path_spec.get(key, {})
        #This method only support unique and unique_path attributes
        if 'exclude' not in key_spec:
            key_spec['exclude'] = ['other']
        elif 'other' not in key_spec['exclude']:
            key_spec['exclude'].append('other')

        key_xpath = get_attrib_xpath(schema_dict, key, **key_spec)

        if not text_attrib:
            #Split up path into tag path and attribute name (original name of key could have different cases)
            key_xpath, key = split_off_attrib(key_xpath)

        if text_attrib:
            xml_set_first_text(xmltree, schema_dict, key_xpath, key_xpath, change_value)
        else:
            xml_set_first_attrib_value(xmltree, schema_dict, key_xpath, key_xpath, key, change_value)

    return xmltree
def test_get_attrib_xpath_output():
    """
    Test the path finding for tags for the input schema without additional options
    And verify with different version of the schema
    """
    from masci_tools.util.schema_dict_util import get_attrib_xpath

    #absolute
    assert get_attrib_xpath(
        outschema_dict_31,
        'nat') == '/fleurOutput/numericalParameters/atomsInCell/@nat'
    assert get_attrib_xpath(
        outschema_dict_34,
        'nat') == '/fleurOutput/numericalParameters/atomsInCell/@nat'

    #relative
    assert get_attrib_xpath(outschema_dict_31,
                            'qvectors') == './Forcetheorem_SSDISP/@qvectors'
    assert get_attrib_xpath(outschema_dict_34,
                            'qvectors') == './Forcetheorem_SSDISP/@qvectors'
def test_get_attrib_xpath_exclude_output():
    """
    Test the selection of paths based on a contained keyword
    """
    from masci_tools.util.schema_dict_util import get_attrib_xpath

    schema_dict = outschema_dict_34

    with pytest.raises(
            ValueError,
            match=
            'The attrib units has multiple possible paths with the current specification.'
    ):
        get_attrib_xpath(schema_dict, 'units')

    assert get_attrib_xpath(schema_dict, 'units',
                            contains='DMI') == './Forcetheorem_DMI/@units'
    assert get_attrib_xpath(schema_dict,
                            'units',
                            exclude=['other'],
                            contains='DMI') == './Forcetheorem_DMI/@units'

    with pytest.raises(
            ValueError,
            match=
            'The attrib units has no possible paths with the current specification.'
    ):
        get_attrib_xpath(schema_dict,
                         'units',
                         exclude=['unique_path'],
                         contains='DMI')
def test_get_attrib_xpath_exclude():
    """
    Test the selection of paths based on a contained keyword
    """
    from masci_tools.util.schema_dict_util import get_attrib_xpath

    schema_dict = schema_dict_34

    with pytest.raises(
            ValueError,
            match=
            'The attrib alpha has multiple possible paths with the current specification.'
    ):
        get_attrib_xpath(schema_dict, 'alpha')

    assert get_attrib_xpath(schema_dict,
                            'alpha',
                            exclude=[
                                'unique_path', 'other'
                            ]) == '/fleurInput/calculationSetup/scfLoop/@alpha'
    with pytest.raises(
            ValueError,
            match=
            'The attrib alpha has multiple possible paths with the current specification.'
    ):
        get_attrib_xpath(schema_dict, 'alpha', exclude=['unique'])

    assert get_attrib_xpath(
        schema_dict, 'alpha', not_contains='atom', exclude=['unique']
    ) == '/fleurInput/calculationSetup/greensFunction/contourSemicircle/@alpha'
def test_get_attrib_xpath_contains():
    """
    Test the selection of paths based on a contained keyword
    """
    from masci_tools.util.schema_dict_util import get_attrib_xpath

    schema_dict = schema_dict_34

    with pytest.raises(
            ValueError,
            match=
            'The attrib l_mperp has multiple possible paths with the current specification.'
    ):
        get_attrib_xpath(schema_dict, 'l_mperp')

    assert get_attrib_xpath(
        schema_dict, 'l_mperp', contains='magnetism'
    ) == '/fleurInput/calculationSetup/magnetism/mtNocoParams/@l_mperp'
    assert get_attrib_xpath(
        schema_dict, 'l_mperp', contains='greensFunction'
    ) == '/fleurInput/calculationSetup/greensFunction/@l_mperp'

    with pytest.raises(
            ValueError,
            match=
            'The attrib l_mperp has no possible paths with the current specification.'
    ):
        get_attrib_xpath(schema_dict, 'l_mperp', contains='atom')
Exemple #8
0
def add_number_to_attrib(xmltree,
                         schema_dict,
                         attributename,
                         add_number,
                         complex_xpath=None,
                         mode='abs',
                         occurrences=None,
                         **kwargs):
    """
    Adds a given number to the attribute value in a xmltree specified by the name of the attribute
    and optional further specification
    If there are no nodes under the specified xpath an error is raised

    :param xmltree: an xmltree that represents inp.xml
    :param schema_dict: InputSchemaDict containing all information about the structure of the input
    :param attributename: the attribute name to change
    :param add_number: number to add/multiply with the old attribute value
    :param complex_xpath: an optional xpath to use instead of the simple xpath for the evaluation
    :param mode: str (either `rel` or `abs`).
                 `rel` multiplies the old value with `add_number`
                 `abs` adds the old value and `add_number`
    :param occurrences: int or list of int. Which occurence of the node to set. By default all are set.

    Kwargs:
        :param tag_name: str, name of the tag where the attribute should be parsed
        :param contains: str, this string has to be in the final path
        :param not_contains: str, this string has to NOT be in the final path
        :param exclude: list of str, here specific types of attributes can be excluded
                        valid values are: settable, settable_contains, other

    :returns: xmltree with shifted attribute
    """
    from masci_tools.util.xml.xml_setters_xpaths import xml_add_number_to_attrib
    from masci_tools.util.xml.common_functions import split_off_attrib

    attrib_xpath = get_attrib_xpath(schema_dict, attributename, **kwargs)

    base_xpath, attributename = split_off_attrib(attrib_xpath)

    if complex_xpath is None:
        complex_xpath = base_xpath

    xmltree = xml_add_number_to_attrib(xmltree,
                                       schema_dict,
                                       complex_xpath,
                                       base_xpath,
                                       attributename,
                                       add_number,
                                       mode=mode,
                                       occurrences=occurrences)

    return xmltree
    def get_attrib_xpath(self, name, contains=None, not_contains=None, exclude=None, tag_name=None):
        """
        Tries to find a unique path from the schema_dict based on the given name of the attribute
        and additional further specifications

        :param name: str, name of the attribute
        :param contains: str or list of str, this string has to be in the final path
        :param not_contains: str or list of str, this string has to NOT be in the final path
        :param exclude: list of str, here specific types of attributes can be excluded
                        valid values are: settable, settable_contains, other
        :param tag_name: str, if given this name will be used to find a path to a tag with the
                         same name in :py:func:`get_tag_xpath()`

        :returns: str, xpath to the tag with the given attribute

        :raises ValueError: If no unique path could be found
        """
        return get_attrib_xpath(self,
                                name,
                                contains=contains,
                                not_contains=not_contains,
                                exclude=exclude,
                                tag_name=tag_name)
def test_get_attrib_xpath_input():
    """
    Test the path finding for tags for the input schema without additional options
    And verify with different version of the schema
    """
    from masci_tools.util.schema_dict_util import get_attrib_xpath

    #First example easy (magnetism tag is unique and should not differ between the versions)
    assert get_attrib_xpath(
        schema_dict_27,
        'jspins') == '/fleurInput/calculationSetup/magnetism/@jspins'
    assert get_attrib_xpath(
        schema_dict_34,
        'jspins') == '/fleurInput/calculationSetup/magnetism/@jspins'

    #Differing paths between the version
    assert get_attrib_xpath(
        schema_dict_27,
        'mode') == '/fleurInput/calculationSetup/bzIntegration/@mode'
    assert get_attrib_xpath(schema_dict_34,
                            'mode') == '/fleurInput/cell/bzIntegration/@mode'

    #Non existent tag in old version
    assert get_attrib_xpath(schema_dict_34, 'l_mtNocoPot', exclude=[
        'other'
    ]) == '/fleurInput/calculationSetup/magnetism/mtNocoParams/@l_mtNocoPot'
    with pytest.raises(
            ValueError,
            match=
            'The attrib l_mtNocoPot has no possible paths with the current specification.'
    ):
        get_attrib_xpath(schema_dict_27, 'l_mtNocoPot')

    #Multiple possible paths
    with pytest.raises(
            ValueError,
            match=
            'The attrib l_amf has multiple possible paths with the current specification.'
    ):
        get_attrib_xpath(schema_dict_27, 'l_amf')
    with pytest.raises(
            ValueError,
            match=
            'The attrib l_amf has multiple possible paths with the current specification.'
    ):
        get_attrib_xpath(schema_dict_34, 'l_amf')
Exemple #11
0
def shift_value_species_label(xmltree, schema_dict, atom_label, attributename, value_given, mode='abs', **kwargs):
    """
    Shifts the value of an attribute on a species by label
    if atom_label contains 'all' then applies to all species

    :param xmltree: xml etree of the inp.xml
    :param schema_dict: InputSchemaDict containing all information about the structure of the input
    :param atom_label: string, a label of the atom which specie will be changed. 'all' if set up all species
    :param attributename: name of the attribute to change
    :param value_given: value to add or to multiply by
    :param mode: 'rel' for multiplication or 'abs' for addition

    Kwargs if the attributename does not correspond to a unique path:
        :param contains: str, this string has to be in the final path
        :param not_contains: str, this string has to NOT be in the final path

    :returns: xml etree of the new inp.xml
    """
    from masci_tools.util.schema_dict_util import tag_exists, eval_simple_xpath
    from masci_tools.util.xml.common_functions import get_xml_attribute
    from masci_tools.util.xml.xml_setters_xpaths import xml_add_number_to_first_attrib
    from masci_tools.util.xml.common_functions import split_off_attrib

    if 'contains' in kwargs:
        contains = kwargs.get('contains')
        if not isinstance(contains, list):
            contains = [contains]
        contains.append('species')
        kwargs['contains'] = contains
    else:
        kwargs['contains'] = 'species'

    species_base_path = get_tag_xpath(schema_dict, 'species')
    attr_base_path = get_attrib_xpath(schema_dict, attributename, **kwargs)
    tag_base_xpath, attributename = split_off_attrib(attr_base_path)

    if atom_label != 'all':
        atom_label = f'{atom_label: >20}'
    all_groups = eval_simple_xpath(xmltree, schema_dict, 'atomGroup', list_return=True)

    species_to_set = set()

    for group in all_groups:
        if tag_exists(group, schema_dict, 'filmPos'):
            atoms = eval_simple_xpath(group, schema_dict, 'filmPos', list_return=True)
        else:
            atoms = eval_simple_xpath(group, schema_dict, 'relPos', list_return=True)
        for atom in atoms:
            label = get_xml_attribute(atom, 'label')
            if atom_label in ('all', label):
                species_to_set.add(get_xml_attribute(group, 'species'))

    for species_name in species_to_set:

        xpath_species = f'{species_base_path}[@name="{species_name}"]'
        tag_xpath = tag_base_xpath.replace(species_base_path, xpath_species)

        xmltree = xml_add_number_to_first_attrib(xmltree,
                                                 schema_dict,
                                                 tag_xpath,
                                                 tag_base_xpath,
                                                 attributename,
                                                 value_given,
                                                 mode=mode)

    return xmltree
Exemple #12
0
def set_attrib_value(xmltree,
                     schema_dict,
                     attributename,
                     attribv,
                     complex_xpath=None,
                     occurrences=None,
                     create=False,
                     **kwargs):
    """
    Sets an attribute in a xmltree to a given value, specified by its name and further
    specifications.
    If there are no nodes under the specified xpath a tag can be created with `create=True`.
    The attribute values are converted automatically according to the types of the attribute
    with :py:func:`~masci_tools.util.xml.converters.convert_attribute_to_xml()` if they
    are not `str` already.

    :param xmltree: an xmltree that represents inp.xml
    :param schema_dict: InputSchemaDict containing all information about the structure of the input
    :param attributename: the attribute name to set
    :param attribv: value or list of values to set
    :param complex_xpath: an optional xpath to use instead of the simple xpath for the evaluation
    :param occurrences: int or list of int. Which occurence of the node to set. By default all are set.
    :param create: bool optional (default False), if True the tag is created if is missing

    Kwargs:
        :param tag_name: str, name of the tag where the attribute should be parsed
        :param contains: str, this string has to be in the final path
        :param not_contains: str, this string has to NOT be in the final path
        :param exclude: list of str, here specific types of attributes can be excluded
                        valid values are: settable, settable_contains, other

    :returns: xmltree with set attribute
    """
    from masci_tools.util.xml.xml_setters_xpaths import xml_set_attrib_value
    from masci_tools.util.xml.common_functions import split_off_attrib

    #Special case for xcFunctional
    #(Also implemented here to not confuse users since it would only work in set_inpchanges otherwise)
    if attributename == 'xcFunctional':
        attributename = 'name'
        if 'exclude' not in kwargs:
            kwargs['exclude'] = ['other']
        elif 'other' not in kwargs['exclude']:
            kwargs['exclude'].append('other')

    base_xpath = get_attrib_xpath(schema_dict, attributename, **kwargs)

    base_xpath, attributename = split_off_attrib(base_xpath)

    if complex_xpath is None:
        complex_xpath = base_xpath

    xmltree = xml_set_attrib_value(xmltree,
                                   schema_dict,
                                   complex_xpath,
                                   base_xpath,
                                   attributename,
                                   attribv,
                                   occurrences=occurrences,
                                   create=create)

    return xmltree