pymatgen.analysis.chemenv.utils.chemenv_config — pymatgen 2020.7.3 documentation

# Source code for pymatgen.analysis.chemenv.utils.chemenv_config

    # coding: utf-8
    # Copyright (c) Pymatgen Development Team.
    # Distributed under the terms of the MIT License.

    from pymatgen.analysis.chemenv.utils.scripts_utils import strategies_class_lookup
    from os.path import expanduser, exists
    from os import makedirs
    import json

    from pymatgen import SETTINGS

    """
    This module contains the classes for configuration of the chemenv package.
    """

    __author__ = "David Waroquiers"
    __copyright__ = "Copyright 2012, The Materials Project"
    __credits__ = "Geoffroy Hautier"
    __version__ = "2.0"
    __maintainer__ = "David Waroquiers"
    __email__ = "david.waroquiers@gmail.com"
    __date__ = "Feb 20, 2016"

    class ChemEnvConfig():
        """
        Class used to store the configuration of the chemenv package :
         - Materials project access
         - ICSD database access
         - Default options (strategies, ...)
        """
        DEFAULT_PACKAGE_OPTIONS = {
            'default_strategy': {
                'strategy': 'SimplestChemenvStrategy',
                'strategy_options': {
                    'distance_cutoff': strategies_class_lookup['SimplestChemenvStrategy'].DEFAULT_DISTANCE_CUTOFF,
                    'angle_cutoff': strategies_class_lookup['SimplestChemenvStrategy'].DEFAULT_ANGLE_CUTOFF,
                    'additional_condition': strategies_class_lookup['SimplestChemenvStrategy'].DEFAULT_ADDITIONAL_CONDITION,
                    'continuous_symmetry_measure_cutoff':
                        strategies_class_lookup['SimplestChemenvStrategy'].DEFAULT_CONTINUOUS_SYMMETRY_MEASURE_CUTOFF}},
            'default_max_distance_factor': 1.5
        }

        def __init__(self, package_options=None):
            if SETTINGS.get("PMG_MAPI_KEY", "") != "":
                self.materials_project_configuration = SETTINGS.get("PMG_MAPI_KEY", "")
            else:
                self.materials_project_configuration = None

            if package_options is None:
                self.package_options = self.DEFAULT_PACKAGE_OPTIONS
            else:
                self.package_options = package_options

        def setup(self):
            while True:
                print('\n=> Configuration of the ChemEnv package <=')
                print('Current configuration :')
                if self.has_materials_project_access:
                    print(' - Access to materials project is configured (add test ?)')
                else:
                    print(' - No access to materials project')
                print(' - Package options :')
                for key, val in self.package_options.items():
                    print('     {}   :   {}'.format(str(key), str(val)))
                print('\nChoose in the following :')
                print(' <1> + <ENTER> : configuration of the package options (strategy, ...)')
                print(' <q> + <ENTER> : quit without saving configuration')
                test = input(' <S> + <ENTER> : save configuration and quit\n ... ')
                if test == '1':
                    self.setup_package_options()
                elif test == 'q':
                    break
                elif test == 'S':
                    config_file = self.save()
                    break
                else:
                    print(' ... wrong key, try again ...')
                print('')
            if test == 'S':
                print('Configuration has been saved to file "{}"'.format(config_file))

        @property
        def has_materials_project_access(self):
            return self.materials_project_configuration is not None

        def setup_package_options(self):
            self.package_options = self.DEFAULT_PACKAGE_OPTIONS
            print('Choose between the following strategies : ')
            strategies = list(strategies_class_lookup.keys())
            for istrategy, strategy in enumerate(strategies):
                print(' <{}> : {}'.format(str(istrategy + 1), strategy))
            test = input(' ... ')
            self.package_options['default_strategy'] = {'strategy': strategies[int(test) - 1], 'strategy_options': {}}
            strategy_class = strategies_class_lookup[strategies[int(test) - 1]]
            if len(strategy_class.STRATEGY_OPTIONS) > 0:
                for option, option_dict in strategy_class.STRATEGY_OPTIONS.items():
                    while True:
                        print('  => Enter value for option "{}" '
                              '(<ENTER> for default = {})\n'.format(option,
                                                                    str(option_dict['default'])))
                        print('     Valid options are :\n')
                        print('       {}'.format(option_dict['type'].allowed_values))
                        test = input('     Your choice : ')
                        if test == '':
                            self.package_options['default_strategy']['strategy_options'][option] = option_dict['type'](
                                strategy_class.STRATEGY_OPTIONS[option]['default'])
                            break
                        try:
                            self.package_options['default_strategy']['strategy_options'][option] = option_dict['type'](test)
                            break
                        except ValueError:
                            print('Wrong input for option {}'.format(option))

        def package_options_description(self):
            out = 'Package options :\n'
            out += ' - Maximum distance factor : {:.4f}\n'.format(self.package_options['default_max_distance_factor'])
            out += ' - Default strategy is "{}" :\n'.format(self.package_options['default_strategy']['strategy'])
            strategy_class = strategies_class_lookup[self.package_options['default_strategy']['strategy']]
            out += '{}\n'.format(strategy_class.STRATEGY_DESCRIPTION)
            out += '   with options :\n'
            for option, option_dict in strategy_class.STRATEGY_OPTIONS.items():
                out += '     - {} : {}\n'.format(option,
                                                 self.package_options['default_strategy']['strategy_options'][option])
            return out

        def save(self, root_dir=None):
            if root_dir is None:
                home = expanduser("~")
                root_dir = '{}/.chemenv'.format(home)
            if not exists(root_dir):
                makedirs(root_dir)
            config_dict = {'package_options': self.package_options}
            config_file = '{}/config.json'.format(root_dir)
            if exists(config_file):
                test = input('Overwrite existing configuration ? (<Y> + <ENTER> to confirm)')
                if test != 'Y':
                    print('Configuration not saved')
                    return config_file
            f = open(config_file, 'w')
            json.dump(config_dict, f)
            f.close()
            print('Configuration saved')
            return config_file

        @classmethod
        def auto_load(cls, root_dir=None):
            if root_dir is None:
                home = expanduser("~")
                root_dir = '{}/.chemenv'.format(home)
            config_file = '{}/config.json'.format(root_dir)
            try:
                f = open(config_file, 'r')
                config_dict = json.load(f)
                f.close()
                return ChemEnvConfig(package_options=config_dict['package_options'])

            except IOError:
                print('Unable to load configuration from file "{}" ...'.format(config_file))
                print(' ... loading default configuration')
                return ChemEnvConfig()