Exemple #1
0
def test_create_from_folder_duplicate(filepath_pseudos):
    """Test that `SsspFamily.create_from_folder` raises for duplicate label."""
    label = 'SSSP/1.1/PBE/efficiency'
    SsspFamily(label=label).store()

    with pytest.raises(ValueError,
                       match=r'the SsspFamily `.*` already exists'):
        SsspFamily.create_from_folder(filepath_pseudos('upf'), label)
Exemple #2
0
def test_constructor():
    """Test that the `SsspFamily` constructor validates the label."""
    with pytest.raises(
            ValueError,
            match=r'the label `.*` is not a valid SSSP configuration label'):
        SsspFamily()

    with pytest.raises(
            ValueError,
            match=r'the label `.*` is not a valid SSSP configuration label'):
        SsspFamily(label='SSSP_1.1_PBE_efficiency')

    label = SsspFamily.format_configuration_label(
        SsspFamily.default_configuration)
    family = SsspFamily(label=label)
    assert isinstance(family, SsspFamily)
Exemple #3
0
def test_get_valid_labels():
    """Test the `SsspFamily.get_valid_labels` class method."""
    valid_labels = SsspFamily.get_valid_labels()
    assert isinstance(valid_labels, tuple)

    for entry in valid_labels:
        assert isinstance(entry, str)
Exemple #4
0
def cmd_install_sssp(version, functional, protocol, traceback):
    """Install an SSSP configuration.

    The SSSP configuration will be automatically downloaded from the Materials Cloud Archive entry to create a new
    `SsspFamily`.
    """
    # pylint: disable=too-many-locals
    import requests

    from aiida.common.files import md5_file
    from aiida.orm import Group, QueryBuilder

    from aiida_pseudo import __version__
    from aiida_pseudo.groups.family import SsspConfiguration, SsspFamily
    from .utils import attempt, create_family_from_archive

    configuration = SsspConfiguration(version, functional, protocol)
    label = SsspFamily.format_configuration_label(configuration)
    description = f'SSSP v{version} {functional} {protocol} installed with aiida-pseudo v{__version__}'

    if configuration not in SsspFamily.valid_configurations:
        echo.echo_critical(
            f'{version} {functional} {protocol} is not a valid SSSP configuration'
        )

    if QueryBuilder().append(SsspFamily, filters={'label': label}).first():
        echo.echo_critical(
            f'{SsspFamily.__name__}<{label}> is already installed')

    with tempfile.TemporaryDirectory() as dirpath:

        url_archive = f'{URL_SSSP_BASE}/SSSP_{version}_{functional}_{protocol}.tar.gz'
        filepath_archive = os.path.join(dirpath, 'archive.tar.gz')

        url_metadata = f'{URL_SSSP_BASE}/SSSP_{version}_{functional}_{protocol}.json'
        filepath_metadata = os.path.join(dirpath, 'metadata.json')

        with attempt('downloading selected pseudo potentials archive... ',
                     include_traceback=traceback):
            response = requests.get(url_archive)
            response.raise_for_status()
            with open(filepath_archive, 'wb') as handle:
                handle.write(response.content)
                handle.flush()
                description += f'\nArchive pseudos md5: {md5_file(filepath_archive)}'

        with attempt('downloading selected pseudo potentials metadata... ',
                     include_traceback=traceback):
            response = requests.get(url_metadata)
            response.raise_for_status()
            with open(filepath_metadata, 'a+b') as handle:
                handle.write(response.content)
                handle.flush()
                handle.seek(0)
                metadata = json.load(handle)
                description += f'\nPseudo metadata md5: {md5_file(filepath_metadata)}'

        with attempt('unpacking archive and parsing pseudos... ',
                     include_traceback=traceback):
            family = create_family_from_archive(SsspFamily, label,
                                                filepath_archive)

        cutoffs = {}

        for element, values in metadata.items():
            if family.get_pseudo(element).md5 != values['md5']:
                Group.objects.delete(family.pk)
                msg = f"md5 of pseudo for element {element} does not match that of the metadata {values['md5']}"
                echo.echo_critical(msg)

            cutoffs[element] = {
                'cutoff_wfc': values['cutoff_wfc'],
                'cutoff_rho': values['cutoff_rho']
            }

        family.description = description
        family.set_cutoffs(cutoffs)

        echo.echo_success(
            f'installed `{label}` containing {family.count()} pseudo potentials'
        )
Exemple #5
0
def test_format_configuration_label():
    """Test the `SsspFamily.format_configuration_label` class method."""
    configuration = SsspConfiguration(1.1, 'PBE', 'efficiency')
    assert SsspFamily.format_configuration_label(
        configuration) == 'SSSP/1.1/PBE/efficiency'
Exemple #6
0
def test_create_from_folder(filepath_pseudos):
    """Test the `SsspFamily.create_from_folder` class method."""
    family = SsspFamily.create_from_folder(filepath_pseudos('upf'),
                                           'SSSP/1.1/PBE/efficiency',
                                           pseudo_type=UpfData)
    assert isinstance(family, SsspFamily)
Exemple #7
0
def cmd_install_sssp(version, functional, protocol, download_only, traceback):
    """Install an SSSP configuration.

    The SSSP configuration will be automatically downloaded from the Materials Cloud Archive entry to create a new
    `SsspFamily`.
    """
    # pylint: disable=too-many-locals
    from aiida.common.files import md5_file
    from aiida.orm import Group, QueryBuilder

    from aiida_pseudo import __version__
    from aiida_pseudo.groups.family import SsspFamily
    from .utils import attempt, create_family_from_archive

    configuration = SsspConfiguration(version, functional, protocol)
    label = SsspFamily.format_configuration_label(configuration)
    description = f'SSSP v{version} {functional} {protocol} installed with aiida-pseudo v{__version__}'

    if configuration not in SsspFamily.valid_configurations:
        echo.echo_critical(f'{version} {functional} {protocol} is not a valid SSSP configuration')

    if not download_only and QueryBuilder().append(SsspFamily, filters={'label': label}).first():
        echo.echo_critical(f'{SsspFamily.__name__}<{label}> is already installed')

    with tempfile.TemporaryDirectory() as dirpath:

        dirpath = pathlib.Path(dirpath)
        filepath_archive = dirpath / 'archive.tar.gz'
        filepath_metadata = dirpath / 'metadata.json'

        download_sssp(configuration, filepath_archive, filepath_metadata, traceback)

        description += f'\nArchive pseudos md5: {md5_file(filepath_archive)}'
        description += f'\nPseudo metadata md5: {md5_file(filepath_metadata)}'

        if download_only:
            for filepath in [filepath_archive, filepath_metadata]:
                filepath_target = pathlib.Path.cwd() / filepath.name
                if filepath_target.exists():
                    echo.echo_warning(f'the file `{filepath_target}` already exists, skipping.')
                else:
                    # Cannot use ``pathlib.Path.rename`` because this will fail if it moves across file systems.
                    shutil.move(filepath, filepath_target)
                    echo.echo_success(f'`{filepath_target.name}` written to the current directory.')
            return

        with open(filepath_metadata, 'rb') as handle:
            handle.seek(0)
            metadata = json.load(handle)

        with attempt('unpacking archive and parsing pseudos... ', include_traceback=traceback):
            family = create_family_from_archive(SsspFamily, label, filepath_archive)

        cutoffs = {}

        for element, values in metadata.items():
            if family.get_pseudo(element).md5 != values['md5']:
                Group.objects.delete(family.pk)
                msg = f"md5 of pseudo for element {element} does not match that of the metadata {values['md5']}"
                echo.echo_critical(msg)

            cutoffs[element] = {'cutoff_wfc': values['cutoff_wfc'], 'cutoff_rho': values['cutoff_rho']}

        family.description = description
        family.set_cutoffs(cutoffs, 'normal', unit='Ry')

        echo.echo_success(f'installed `{label}` containing {family.count()} pseudo potentials')