class CoordinationGeometryFinderTest(unittest2.TestCase):

    def setUp(self):
        self.lgf = LocalGeometryFinder()
        self.lgf.setup_parameters(centering_type='standard')
        self.strategies = [SimplestChemenvStrategy(), SimpleAbundanceChemenvStrategy()]

    # def _strategy_test(self, strategy):
    #     files = []
    #     for (dirpath, dirnames, filenames) in os.walk(json_files_dir):
    #         files.extend(filenames)
    #         break
    #
    #     for ifile, json_file in enumerate(files):
    #         with self.subTest(json_file=json_file):
    #             f = open("{}/{}".format(json_files_dir, json_file), 'r')
    #             dd = json.load(f)
    #             f.close()
    #
    #             atom_indices = dd['atom_indices']
    #             expected_geoms = dd['expected_geoms']
    #
    #             struct = Structure.from_dict(dd['structure'])
    #
    #             struct = self.lgf.setup_structure(struct)
    #             se = self.lgf.compute_structure_environments_detailed_voronoi(only_indices=atom_indices,
    #                                                                           maximum_distance_factor=1.5)
    #
    #             #All strategies should get the correct environment with their default parameters
    #             strategy.set_structure_environments(se)
    #             for ienv, isite in enumerate(atom_indices):
    #                 ce = strategy.get_site_coordination_environment(struct[isite])
    #                 try:
    #                     coord_env = ce[0]
    #                 except TypeError:
    #                     coord_env = ce
    #                 #Check that the environment found is the expected one
    #                 self.assertEqual(coord_env, expected_geoms[ienv])
    #
    # def test_simplest_chemenv_strategy(self):
    #     strategy = SimplestChemenvStrategy()
    #     self._strategy_test(strategy)
    #
    # def test_simple_abundance_chemenv_strategy(self):
    #     strategy = SimpleAbundanceChemenvStrategy()
    #     self._strategy_test(strategy)

    def test_perfect_environments(self):
        for coordination in range(1, 13):
            for mp_symbol in AllCoordinationGeometries().get_implemented_geometries(coordination=coordination,
                                                                                    returned='mp_symbol'):
                with self.subTest(msg=mp_symbol, mp_symbol=mp_symbol):
                    self.lgf.setup_test_perfect_environment(mp_symbol, randomness=False,
                                                            indices='RANDOM',
                                                            random_translation=True, random_rotation=True,
                                                            random_scale=True)
                    se = self.lgf.compute_structure_environments_detailed_voronoi(only_indices=[0],
                                                                                  maximum_distance_factor=1.5)
                    self.assertAlmostEqual(se.get_csm(0, mp_symbol)['symmetry_measure'], 0.0,
                                           msg='mp_symbol {} not recognized ...'.format(mp_symbol))
class LightStructureEnvironmentsTest(unittest.TestCase):

    @classmethod
    def setUpClass(cls):
        os.makedirs('tmp_dir')

    def setUp(self):
        self.lgf = LocalGeometryFinder()
        self.lgf.setup_parameters(centering_type='standard')
        self.strategies = [SimplestChemenvStrategy(), SimpleAbundanceChemenvStrategy()]

    def test_read_structure_environments(self):
        f = open("{}/{}".format(json_files_dir, 'test_T--4_FePO4_icsd_4266.json'), 'r')
        dd = json.load(f)
        f.close()

        atom_indices = dd['atom_indices']

        struct = Structure.from_dict(dd['structure'])
        self.lgf.setup_structure(struct)
        se = self.lgf.compute_structure_environments_detailed_voronoi(only_indices=atom_indices,
                                                                      maximum_distance_factor=2.25)

        f = open('tmp_dir/se.json', 'w')
        json.dump(se.as_dict(), f)
        f.close()

        f = open('tmp_dir/se.json', 'r')
        dd = json.load(f)
        f.close()

        se2 = StructureEnvironments.from_dict(dd)

        self.assertEqual(se, se2)

        _strategy = SimplestChemenvStrategy()
        light_se = LightStructureEnvironments(_strategy, se)

        f = open('tmp_dir/light_se.json', 'w')
        json.dump(light_se.as_dict(), f)
        f.close()

        f = open('tmp_dir/light_se.json', 'r')
        dd = json.load(f)
        f.close()

        light_se2 = LightStructureEnvironments.from_dict(dd)

        self.assertEqual(light_se, light_se2)

    @classmethod
    def tearDownClass(cls):
        #Remove the directory in which the temporary files have been created
        shutil.rmtree('tmp_dir')
    def figure_fractions(self, weights_options, morphing_factors=None):
        if morphing_factors is None:
            morphing_factors = np.linspace(1.0, 2.0, 21)
        # Set up the local geometry finder
        lgf = LocalGeometryFinder()
        lgf.setup_parameters(structure_refinement=lgf.STRUCTURE_REFINEMENT_NONE)
        # Set up the weights for the MultiWeights strategy
        weights = self.get_weights(weights_options)
        # Set up the strategy
        strat = MultiWeightsChemenvStrategy(dist_ang_area_weight=weights['DistAngArea'],
                                            self_csm_weight=weights['SelfCSM'],
                                            delta_csm_weight=weights['DeltaCSM'],
                                            cn_bias_weight=weights['CNBias'],
                                            angle_weight=weights['Angle'],
                                            normalized_angle_distance_weight=weights['NormalizedAngDist'])
        fake_valences = [-1] * (self.coordination_geometry.coordination_number + 1)
        fake_valences[0] = 1
        fractions_initial_environment = np.zeros_like(morphing_factors)
        fractions_final_environment = np.zeros_like(morphing_factors)
        for ii, morphing_factor in enumerate(morphing_factors):
            print(ii)
            struct = self.get_structure(morphing_factor=morphing_factor)
            print(struct)
            # Get the StructureEnvironments
            lgf.setup_structure(structure=struct)
            se = lgf.compute_structure_environments(only_indices=[0], valences=fake_valences)
            strat.set_structure_environments(structure_environments=se)
            result = strat.get_site_coordination_environments_fractions(site=se.structure[0], isite=0,
                                                                        return_strategy_dict_info=True,
                                                                        return_all=True)
            for res in result:
                if res['ce_symbol'] == self.initial_environment_symbol:
                    fractions_initial_environment[ii] = res['ce_fraction']
                elif res['ce_symbol'] == self.expected_final_environment_symbol:
                    fractions_final_environment[ii] = res['ce_fraction']

        fig_width_cm = 8.25
        fig_height_cm = 7.0
        fig_width = fig_width_cm / 2.54
        fig_height = fig_height_cm / 2.54

        fig = plt.figure(num=1, figsize=(fig_width, fig_height))
        subplot = fig.add_subplot(111)

        subplot.plot(morphing_factors, fractions_initial_environment, 'b-',
                     label='{}'.format(self.initial_environment_symbol),
                     linewidth=1.5)
        subplot.plot(morphing_factors, fractions_final_environment, 'g--',
                     label='{}'.format(self.expected_final_environment_symbol), linewidth=1.5)

        plt.legend(fontsize=8.0, loc=7)
        plt.show()
    def estimate_parameters(self, dist_factor_min, dist_factor_max, symmetry_measure_type='csm_wcs_ctwcc'):
        only_symbols = [self.initial_environment_symbol, self.expected_final_environment_symbol]
        # Set up the local geometry finder
        lgf = LocalGeometryFinder()
        lgf.setup_parameters(structure_refinement=lgf.STRUCTURE_REFINEMENT_NONE)
        # Get the StructureEnvironments
        fake_valences = [-1] * (self.coordination_geometry.coordination_number + 1)
        fake_valences[0] = 1
        # Get the StructureEnvironments for the structure with dist_factor_min
        struct = self.get_structure(morphing_factor=dist_factor_min)
        lgf.setup_structure(structure=struct)
        se = lgf.compute_structure_environments(only_indices=[0], valences=fake_valences,
                                                only_symbols=only_symbols)
        csm_info = se.get_csms(isite=0,
                               mp_symbol=self.initial_environment_symbol)
        if len(csm_info) == 0:
            raise ValueError('No csm found for {}'.format(self.initial_environment_symbol))
        csm_info.sort(key=lambda x: x['other_symmetry_measures'][symmetry_measure_type])
        csm_initial_min_dist = csm_info[0]['other_symmetry_measures'][symmetry_measure_type]

        csm_info = se.get_csms(isite=0,
                               mp_symbol=self.expected_final_environment_symbol)
        if len(csm_info) == 0:
            raise ValueError('No csm found for {}'.format(self.initial_environment_symbol))
        csm_info.sort(key=lambda x: x['other_symmetry_measures'][symmetry_measure_type])

        csm_final = csm_info[0]['other_symmetry_measures'][symmetry_measure_type]
        if not np.isclose(csm_final, 0.0, rtol=0.0, atol=1e-10):
            raise ValueError('Final coordination is not perfect !')
        # Get the StructureEnvironments for the structure with dist_factor_max
        struct = self.get_structure(morphing_factor=dist_factor_max)
        lgf.setup_structure(structure=struct)
        se = lgf.compute_structure_environments(only_indices=[0], valences=fake_valences,
                                                only_symbols=only_symbols)
        csm_info = se.get_csms(isite=0,
                               mp_symbol=self.initial_environment_symbol)
        if len(csm_info) == 0:
            raise ValueError('No csm found for {}'.format(self.initial_environment_symbol))
        csm_info.sort(key=lambda x: x['other_symmetry_measures'][symmetry_measure_type])
        csm_initial_max_dist = csm_info[0]['other_symmetry_measures'][symmetry_measure_type]

        csm_info = se.get_csms(isite=0,
                               mp_symbol=self.expected_final_environment_symbol)
        if len(csm_info) == 0:
            raise ValueError('No csm found for {}'.format(self.initial_environment_symbol))
        csm_info.sort(key=lambda x: x['other_symmetry_measures'][symmetry_measure_type])

        csm_final = csm_info[0]['other_symmetry_measures'][symmetry_measure_type]
        if not np.isclose(csm_final, 0.0, rtol=0.0, atol=1e-10):
            raise ValueError('Final coordination is not perfect !')

        return {'delta_csm_min': csm_initial_min_dist, 'self_weight_max_csm': csm_initial_max_dist}
    def estimate_parameters(self, dist_factor_min, dist_factor_max, symmetry_measure_type="csm_wcs_ctwcc"):
        only_symbols = [self.initial_environment_symbol, self.expected_final_environment_symbol]
        # Set up the local geometry finder
        lgf = LocalGeometryFinder()
        lgf.setup_parameters(structure_refinement=lgf.STRUCTURE_REFINEMENT_NONE)
        # Get the StructureEnvironments
        fake_valences = [-1] * (self.coordination_geometry.coordination_number + 1)
        fake_valences[0] = 1
        # Get the StructureEnvironments for the structure with dist_factor_min
        struct = self.get_structure(morphing_factor=dist_factor_min)
        lgf.setup_structure(structure=struct)
        se = lgf.compute_structure_environments(only_indices=[0], valences=fake_valences, only_symbols=only_symbols)
        csm_info = se.get_csms(isite=0, mp_symbol=self.initial_environment_symbol)
        if len(csm_info) == 0:
            raise ValueError(f"No csm found for {self.initial_environment_symbol}")
        csm_info.sort(key=lambda x: x["other_symmetry_measures"][symmetry_measure_type])
        csm_initial_min_dist = csm_info[0]["other_symmetry_measures"][symmetry_measure_type]

        csm_info = se.get_csms(isite=0, mp_symbol=self.expected_final_environment_symbol)
        if len(csm_info) == 0:
            raise ValueError(f"No csm found for {self.initial_environment_symbol}")
        csm_info.sort(key=lambda x: x["other_symmetry_measures"][symmetry_measure_type])

        csm_final = csm_info[0]["other_symmetry_measures"][symmetry_measure_type]
        if not np.isclose(csm_final, 0.0, rtol=0.0, atol=1e-10):
            raise ValueError("Final coordination is not perfect !")
        # Get the StructureEnvironments for the structure with dist_factor_max
        struct = self.get_structure(morphing_factor=dist_factor_max)
        lgf.setup_structure(structure=struct)
        se = lgf.compute_structure_environments(only_indices=[0], valences=fake_valences, only_symbols=only_symbols)
        csm_info = se.get_csms(isite=0, mp_symbol=self.initial_environment_symbol)
        if len(csm_info) == 0:
            raise ValueError(f"No csm found for {self.initial_environment_symbol}")
        csm_info.sort(key=lambda x: x["other_symmetry_measures"][symmetry_measure_type])
        csm_initial_max_dist = csm_info[0]["other_symmetry_measures"][symmetry_measure_type]

        csm_info = se.get_csms(isite=0, mp_symbol=self.expected_final_environment_symbol)
        if len(csm_info) == 0:
            raise ValueError(f"No csm found for {self.initial_environment_symbol}")
        csm_info.sort(key=lambda x: x["other_symmetry_measures"][symmetry_measure_type])

        csm_final = csm_info[0]["other_symmetry_measures"][symmetry_measure_type]
        if not np.isclose(csm_final, 0.0, rtol=0.0, atol=1e-10):
            raise ValueError("Final coordination is not perfect !")

        return {"delta_csm_min": csm_initial_min_dist, "self_weight_max_csm": csm_initial_max_dist}
class CoordinationGeometryFinderTest(unittest.TestCase):

    def setUp(self):
        self.lgf = LocalGeometryFinder()
        self.lgf.setup_parameters(centering_type='standard',
                                  structure_refinement=self.lgf.STRUCTURE_REFINEMENT_NONE)
    #     self.strategies = [SimplestChemenvStrategy(), SimpleAbundanceChemenvStrategy()]
    #
    # def _strategy_test(self, strategy):
    #     files = []
    #     for (dirpath, dirnames, filenames) in os.walk(json_files_dir):
    #         files.extend(filenames)
    #         break
    #
    #     for ifile, json_file in enumerate(files):
    #         with self.subTest(json_file=json_file):
    #             f = open("{}/{}".format(json_files_dir, json_file), 'r')
    #             dd = json.load(f)
    #             f.close()
    #
    #             atom_indices = dd['atom_indices']
    #             expected_geoms = dd['expected_geoms']
    #
    #             struct = Structure.from_dict(dd['structure'])
    #
    #             struct = self.lgf.setup_structure(struct)
    #             se = self.lgf.compute_structure_environments_detailed_voronoi(only_indices=atom_indices,
    #                                                                           maximum_distance_factor=1.5)
    #
    #             #All strategies should get the correct environment with their default parameters
    #             strategy.set_structure_environments(se)
    #             for ienv, isite in enumerate(atom_indices):
    #                 ce = strategy.get_site_coordination_environment(struct[isite])
    #                 try:
    #                     coord_env = ce[0]
    #                 except TypeError:
    #                     coord_env = ce
    #                 #Check that the environment found is the expected one
    #                 self.assertEqual(coord_env, expected_geoms[ienv])
    #
    # def test_simplest_chemenv_strategy(self):
    #     strategy = SimplestChemenvStrategy()
    #     self._strategy_test(strategy)
    #
    # def test_simple_abundance_chemenv_strategy(self):
    #     strategy = SimpleAbundanceChemenvStrategy()
    #     self._strategy_test(strategy)

    def test_perfect_environments(self):
        allcg = AllCoordinationGeometries()
        indices_CN = {1: [0],
                      2: [1, 0],
                      3: [1, 0, 2],
                      4: [2, 0, 3, 1],
                      5: [2, 3, 1, 0, 4],
                      6: [0, 2, 3, 1, 5, 4],
                      7: [2, 6, 0, 3, 4, 5, 1],
                      8: [1, 2, 6, 3, 7, 0, 4, 5],
                      9: [5, 2, 6, 0, 4, 7, 3, 8, 1],
                      10: [8, 5, 6, 3, 0, 7, 2, 4, 9, 1],
                      11: [7, 6, 4, 1, 2, 5, 0, 8, 9, 10, 3],
                      12: [5, 8, 9, 0, 3, 1, 4, 2, 6, 11, 10, 7],
                      13: [4, 11, 5, 12, 1, 2, 8, 3, 0, 6, 9, 7, 10],
                      }

        for coordination in range(1, 14):
            for mp_symbol in allcg.get_implemented_geometries(coordination=coordination,
                                                              returned='mp_symbol'):
                cg = allcg.get_geometry_from_mp_symbol(mp_symbol=mp_symbol)
                self.lgf.allcg = AllCoordinationGeometries(only_symbols=[mp_symbol])
                self.lgf.setup_test_perfect_environment(mp_symbol, randomness=False,
                                                        indices=indices_CN[coordination],
                                                        random_translation='NONE', random_rotation='NONE',
                                                        random_scale='NONE')
                se = self.lgf.compute_structure_environments(only_indices=[0],
                                                             maximum_distance_factor=1.01*cg.distfactor_max,
                                                             min_cn=cg.coordination_number,
                                                             max_cn=cg.coordination_number,
                                                             only_symbols=[mp_symbol]
                                                             )
                self.assertAlmostEqual(se.get_csm(0, mp_symbol)['symmetry_measure'], 0.0, delta=1e-8,
                                       msg='Failed to get perfect environment with mp_symbol {}'.format(mp_symbol))
        # Define the coordination geometry
        cg_symbol = raw_input('Enter symbol of the geometry for which you want to get the optimized permutations '
                              'or "q" to quit : ')
        if cg_symbol == 'q':
            break
        if cg_symbol not in sepplane_cgs:
            print('Wrong geometry, try again ...')
            continue

        cg = allcg[cg_symbol]

        print('Getting explicit permutations for geometry "{}" (symbol : "{}")\n'.format(cg.name, cg_symbol))

        # Setup of the local geometry finder
        lgf = LocalGeometryFinder()
        lgf.setup_parameters(structure_refinement=lgf.STRUCTURE_REFINEMENT_NONE)

        # Setup the random environment
        lgf.setup_test_perfect_environment(cg_symbol, randomness=True, indices=range(cg.coordination_number),
                                           max_random_dist=0.05)
        lgf.perfect_geometry = AbstractGeometry.from_cg(cg=cg)
        points_perfect = lgf.perfect_geometry.points_wocs_ctwocc()

        # 1. Check the algorithms defined for this coordination geometry and get the explicit permutations
        original_nexplicit_perms = []
        original_nexplicit_optimized_perms = []
        for ialgo, algo in enumerate(cg.algorithms):
            algo._permutations = algo.explicit_permutations
            if algo.algorithm_type == 'EXPLICIT_PERMUTATIONS':
                raise ValueError('Do something for the explicit ones ... (these should anyway be by far ok!)')
            if algo.explicit_optimized_permutations is None:
class CoordinationGeometryFinderTest(unittest2.TestCase):

    def setUp(self):
        self.lgf = LocalGeometryFinder()
        self.lgf.setup_parameters(centering_type='standard')
        self.strategies = [SimplestChemenvStrategy(), SimpleAbundanceChemenvStrategy()]
Ejemplo n.º 9
0
    def run_task(self, fw_spec):
        logging.basicConfig(filename='chemenv_structure_environments.log',
                            format='%(levelname)s:%(module)s:%(funcName)s:%(message)s',
                            level=logging.DEBUG)
        lgf = LocalGeometryFinder()
        lgf.setup_parameters(centering_type='centroid', include_central_site_in_centroid=True,
                             structure_refinement=lgf.STRUCTURE_REFINEMENT_NONE)
        if 'chemenv_parameters' in fw_spec:
            for param, value in fw_spec['chemenv_parameters'].items():
                lgf.setup_parameter(param, value)
        identifier = fw_spec['identifier']
        if 'structure' in fw_spec:
            structure = fw_spec['structure']
        else:
            if identifier['source'] == 'MaterialsProject' and 'material_id' in identifier:
                if not 'mapi_key' in fw_spec:
                    raise ValueError('The mapi_key should be provided to get the structure from the Materials Project')
                # FIXME: Use MPRester from pymatgen
                from pymatgen.matproj.rest import MPRester
                a = MPRester(fw_spec['mapi_key'])
                structure = a.get_structure_by_material_id(identifier['material_id'])
            else:
                raise ValueError('Either structure or identifier with source = MaterialsProject and material_id '
                                 'should be provided')

        info = {}
        # Compute the structure environments
        lgf.setup_structure(structure)
        if 'valences' in fw_spec:
            valences = fw_spec['valences']
        else:
            try:
                bva = BVAnalyzer()
                valences = bva.get_valences(structure=structure)
                info['valences'] = {'origin': 'BVAnalyzer'}
            except:
                valences = 'undefined'
                info['valences'] = {'origin': 'None'}
        excluded_atoms = None
        if 'excluded_atoms' in fw_spec:
            excluded_atoms = fw_spec['excluded_atoms']

        se = lgf.compute_structure_environments(only_cations=False, valences=valences, excluded_atoms=excluded_atoms)

        # Write to json file
        if 'json_file' in fw_spec:
            json_file = fw_spec['json_file']
        else:
            json_file = 'structure_environments.json'
        f = open(json_file, 'w')
        json.dump(se.as_dict(), f)
        f.close()

        # Save to database
        if 'mongo_database' in fw_spec:
            database = fw_spec['mongo_database']
            entry = {'identifier': identifier,
                     'elements': [elmt.symbol for elmt in structure.composition.elements],
                     'nelements': len(structure.composition.elements),
                     'pretty_formula': structure.composition.reduced_formula,
                     'nsites': len(structure)
                     }

            saving_option = fw_spec['saving_option']
            if saving_option == 'gridfs':
                gridfs_msonables = {'structure': structure,
                                    'structure_environments': se}
            elif saving_option == 'storefile':
                gridfs_msonables = None
                if 'se_prefix' in fw_spec:
                    se_prefix = fw_spec['se_prefix']
                    if not se_prefix.isalpha():
                        raise ValueError('Prefix for structure_environments file is "{}" '
                                         'while it should be alphabetic'.format(se_prefix))
                else:
                    se_prefix = ''
                if se_prefix:
                    se_rfilename = '{}_{}.json'.format(se_prefix, fw_spec['storefile_basename'])
                else:
                    se_rfilename = '{}.json'.format(fw_spec['storefile_basename'])
                se_rfilepath = '{}/{}'.format(fw_spec['storefile_dirpath'], se_rfilename)
                storage_server = fw_spec['storage_server']
                storage_server.put(localpath=json_file, remotepath=se_rfilepath, overwrite=True, makedirs=False)
                entry['structure_environments_file'] = se_rfilepath
            else:
                raise ValueError('Saving option is "{}" while it should be '
                                 '"gridfs" or "storefile"'.format(saving_option))
            criteria = {'identifier': identifier}
            if database.collection.find(criteria).count() == 1:
                database.update_entry(query=criteria, entry_update=entry,
                                      gridfs_msonables=gridfs_msonables)
            else:
                database.insert_entry(entry=entry, gridfs_msonables=gridfs_msonables)
Ejemplo n.º 10
0
def compute_environments(chemenv_configuration):
    string_sources = {'cif': {'string': 'a Cif file', 'regexp': r'.*\.cif$'},
                      'mp': {'string': 'the Materials Project database',
                             'regexp': r'mp-[0-9]+$'}}
    questions = {'c': 'cif'}
    questions['m'] = 'mp'
    lgf = LocalGeometryFinder()
    lgf.setup_parameters()
    allcg = AllCoordinationGeometries()
    strategy_class = strategies_class_lookup[chemenv_configuration.package_options['default_strategy']['strategy']]
    #TODO: Add the possibility to change the parameters and save them in the chemenv_configuration
    default_strategy = strategy_class()
    default_strategy.setup_options(chemenv_configuration.package_options['default_strategy']['strategy_options'])
    max_dist_factor = chemenv_configuration.package_options['default_max_distance_factor']
    firsttime = True
    while True:
        if len(questions) > 1:
            found = False
            print('Enter the source from which the structure is coming or <q> to quit :')
            for key_character, qq in questions.items():
                print(' - <{}> for a structure from {}'.format(key_character, string_sources[qq]['string']))
            test = input(' ... ')
            if test == 'q':
                break
            if test not in list(questions.keys()):
                for key_character, qq in questions.items():
                    if re.match(string_sources[qq]['regexp'], str(test)) is not None:
                        found = True
                        source_type = qq
                if not found:
                    print('Wrong key, try again ...')
                    continue
            else:
                source_type = questions[test]
        else:
            found = False
            source_type = list(questions.values())[0]
        if found and len(questions) > 1:
            input_source = test
        if source_type == 'cif':
            if not found:
                input_source = input('Enter path to cif file : ')
            cp = CifParser(input_source)
            structure = cp.get_structures()[0]
        elif source_type == 'mp':
            if not found:
                input_source = input('Enter materials project id (e.g. "mp-1902") : ')
            a = MPRester()
            structure = a.get_structure_by_material_id(input_source)
        lgf.setup_structure(structure)
        print('Computing environments for {} ... '.format(structure.composition.reduced_formula))
        se = lgf.compute_structure_environments(maximum_distance_factor=max_dist_factor)
        print('Computing environments finished')
        while True:
            test = input('See list of environments determined for each (unequivalent) site ? '
                         '("y" or "n", "d" with details, "g" to see the grid) : ')
            strategy = default_strategy
            if test in ['y', 'd', 'g']:
                strategy.set_structure_environments(se)
                for eqslist in se.equivalent_sites:
                    site = eqslist[0]
                    isite = se.structure.index(site)
                    try:
                        if strategy.uniquely_determines_coordination_environments:
                            ces = strategy.get_site_coordination_environments(site)
                        else:
                            ces = strategy.get_site_coordination_environments_fractions(site)
                    except NeighborsNotComputedChemenvError:
                        continue
                    if ces is None:
                        continue
                    if len(ces) == 0:
                        continue
                    comp = site.species_and_occu
                    #ce = strategy.get_site_coordination_environment(site)
                    if strategy.uniquely_determines_coordination_environments:
                        ce = ces[0]
                        if ce is None:
                            continue
                        thecg = allcg.get_geometry_from_mp_symbol(ce[0])
                        mystring = 'Environment for site #{} {} ({}) : {} ({})\n'.format(str(isite),
                                                                                         comp.get_reduced_formula_and_factor()[0],
                                                                                         str(comp),
                                                                                         thecg.name,
                                                                                         ce[0])
                    else:
                        mystring = 'Environments for site #{} {} ({}) : \n'.format(str(isite),
                                                                                   comp.get_reduced_formula_and_factor()[0],
                                                                                   str(comp))
                        for ce in ces:
                            cg = allcg.get_geometry_from_mp_symbol(ce[0])
                            csm = ce[1]['other_symmetry_measures']['csm_wcs_ctwcc']
                            mystring += ' - {} ({}): {:.2f} % (csm : {:2f})\n'.format(cg.name, cg.mp_symbol,
                                                                                      100.0*ce[2],
                                                                                      csm)
                    if test in ['d', 'g'] and strategy.uniquely_determines_coordination_environments:
                        if thecg.mp_symbol != UNCLEAR_ENVIRONMENT_SYMBOL:
                            mystring += '  <Continuous symmetry measures>  '
                            mingeoms = se.ce_list[isite][thecg.coordination_number][0].minimum_geometries()
                            for mingeom in mingeoms:
                                csm = mingeom[1]['other_symmetry_measures']['csm_wcs_ctwcc']
                                mystring += '{} : {:.2f}       '.format(mingeom[0], csm)
                    print(mystring)
            if test == 'g':
                while True:
                    test = input('Enter index of site(s) (e.g. 0 1 2, separated by spaces) for which you want to see the grid of parameters : ')
                    try:
                         indices=[int(x) for x in test.split()]
                         print(str(indices))
                         for isite in indices:
                             if isite <0:
                                 raise IndexError
                             se.plot_environments(isite, additional_condition=se.AC.ONLY_ACB)
                         break
                    except ValueError:
                         print('This is not a valid site')
                    except IndexError:
                         print('This site is out of the site range')


            if no_vis:
                test = input('Go to next structure ? ("y" to do so)')
                if test == 'y':
                    break
                continue
            test = input('View structure with environments ? ("y" for the unit cell or "m" for a supercell or "n") : ')
            if test in ['y', 'm']:
                if test == 'm':
                    mydeltas = []
                    while True:
                        try:
                            test = input('Enter multiplicity (e.g. 3 2 2) : ')
                            nns = test.split()
                            for i0 in range(int(nns[0])):
                                for i1 in range(int(nns[1])):
                                    for i2 in range(int(nns[2])):
                                        mydeltas.append(np.array([1.0*i0, 1.0*i1, 1.0*i2], np.float))
                            break

                        except (ValueError,IndexError):
                            print('Not a valid multiplicity')
                else:
                    mydeltas = [np.zeros(3, np.float)]
                if firsttime:
                    vis = StructureVis(show_polyhedron=False, show_unit_cell=True)
                    vis.show_help = False
                    firsttime = False
                vis.set_structure(se.structure)
                strategy.set_structure_environments(se)
                for isite, site in enumerate(se.structure):
                    try:
                        ces = strategy.get_site_coordination_environments(site)
                    except NeighborsNotComputedChemenvError:
                        continue
                    if len(ces) == 0:
                        continue
                    ce = strategy.get_site_coordination_environment(site)
                    if ce is not None and ce[0] != UNCLEAR_ENVIRONMENT_SYMBOL:
                        for mydelta in mydeltas:
                            psite = PeriodicSite(site._species, site._fcoords + mydelta, site._lattice,
                                                 properties=site._properties)
                            vis.add_site(psite)
                            neighbors = strategy.get_site_neighbors(psite)
                            draw_cg(vis, psite, neighbors, cg=lgf.allcg.get_geometry_from_mp_symbol(ce[0]),
                                    perm=ce[1]['permutation'])
                vis.show()
            test = input('Go to next structure ? ("y" to do so) : ')
            if test == 'y':
                break
        print('')
class CoordinationGeometryFinderTest(PymatgenTest):

    def setUp(self):
        self.lgf = LocalGeometryFinder()
        self.lgf.setup_parameters(centering_type='standard',
                                  structure_refinement=self.lgf.STRUCTURE_REFINEMENT_NONE)
    #     self.strategies = [SimplestChemenvStrategy(), SimpleAbundanceChemenvStrategy()]

    def test_abstract_geometry(self):
        cg_ts3 = self.lgf.allcg['TS:3']
        cg_tet = self.lgf.allcg['T:4']
        abstract_geom = AbstractGeometry.from_cg(cg=cg_ts3, centering_type='central_site')
        self.assertArrayAlmostEqual(abstract_geom.centre, [0.0, 0.0, 0.0])
        abstract_geom = AbstractGeometry.from_cg(cg=cg_ts3, centering_type='centroid')
        self.assertArrayAlmostEqual(abstract_geom.centre, [0.0, 0.0, 0.33333333333])
        with self.assertRaises(ValueError) as cm:
            AbstractGeometry.from_cg(cg=cg_ts3, centering_type='central_site',
                                     include_central_site_in_centroid=True)
        self.assertEqual(str(cm.exception), 'The center is the central site, no calculation of the centroid, '
                                            'variable include_central_site_in_centroid should be set to False')
        abstract_geom = AbstractGeometry.from_cg(cg=cg_ts3, centering_type='centroid',
                                                 include_central_site_in_centroid=True)
        self.assertArrayAlmostEqual(abstract_geom.centre, [0.0, 0.0, 0.25])

        self.assertEqual(abstract_geom.__str__(),
                         '\nAbstract Geometry with 3 points :\n'
                         '  [-1.    0.   -0.25]\n'
                         '  [ 1.    0.   -0.25]\n'
                         '  [0.   0.   0.75]\n'
                         'Points are referenced to the centroid (calculated with the central site) :\n'
                         '  [0.   0.   0.25]\n')

        symm_dict = symmetry_measure([[0.0, 0.0, 0.0]], [1.1, 2.2, 3.3])
        self.assertAlmostEqual(symm_dict['symmetry_measure'], 0.0)
        self.assertEqual(symm_dict['scaling_factor'], None)
        self.assertEqual(symm_dict['rotation_matrix'], None)

        tio2_struct = self.get_structure('TiO2')

        envs = self.lgf.compute_coordination_environments(structure=tio2_struct, indices=[0])
        self.assertAlmostEqual(envs[0][0]['csm'], 1.5309987846957258)
        self.assertAlmostEqual(envs[0][0]['ce_fraction'], 1.0)
        self.assertEqual(envs[0][0]['ce_symbol'], 'O:6')
        self.assertEqual(sorted(envs[0][0]['permutation']), sorted([0, 4, 1, 5, 2, 3]))

        self.lgf.setup_random_structure(coordination=5)
        self.assertEqual(len(self.lgf.structure), 6)

        self.lgf.setup_random_indices_local_geometry(coordination=5)
        self.assertEqual(self.lgf.icentral_site, 0)
        self.assertEqual(len(self.lgf.indices), 5)

        self.lgf.setup_ordered_indices_local_geometry(coordination=5)
        self.assertEqual(self.lgf.icentral_site, 0)
        self.assertEqual(self.lgf.indices, list(range(1, 6)))

        self.lgf.setup_explicit_indices_local_geometry(explicit_indices=[3, 5, 2, 0, 1, 4])
        self.assertEqual(self.lgf.icentral_site, 0)
        self.assertEqual(self.lgf.indices, [4, 6, 3, 1, 2, 5])

        LiFePO4_struct = self.get_structure('LiFePO4')
        isite = 10
        envs_LiFePO4 = self.lgf.compute_coordination_environments(structure=LiFePO4_struct, indices=[isite])
        self.assertAlmostEqual(envs_LiFePO4[isite][0]['csm'], 0.140355832317)
        nbs_coords = [np.array([6.16700437, -4.55194317, -5.89031356]),
                      np.array([4.71588167, -4.54248093, -3.75553856]),
                      np.array([6.88012571, -5.79877503, -3.73177541]),
                      np.array([6.90041188, -3.32797839, -3.71812416])]
        self.lgf.setup_structure(LiFePO4_struct)
        self.lgf.setup_local_geometry(isite, coords=nbs_coords)

        perfect_tet = AbstractGeometry.from_cg(cg=cg_tet,
                                               centering_type='centroid',
                                               include_central_site_in_centroid=False)
        points_perfect_tet = perfect_tet.points_wcs_ctwcc()
        res = self.lgf.coordination_geometry_symmetry_measures_fallback_random(coordination_geometry=cg_tet,
                                                                               NRANDOM=5,
                                                                               points_perfect=points_perfect_tet)
        permutations_symmetry_measures, permutations, algos, local2perfect_maps, perfect2local_maps = res
        for perm_csm_dict in permutations_symmetry_measures:
            self.assertAlmostEqual(perm_csm_dict['symmetry_measure'], 0.140355832317)

    #
    # def _strategy_test(self, strategy):
    #     files = []
    #     for (dirpath, dirnames, filenames) in os.walk(json_files_dir):
    #         files.extend(filenames)
    #         break
    #
    #     for ifile, json_file in enumerate(files):
    #         with self.subTest(json_file=json_file):
    #             f = open("{}/{}".format(json_files_dir, json_file), 'r')
    #             dd = json.load(f)
    #             f.close()
    #
    #             atom_indices = dd['atom_indices']
    #             expected_geoms = dd['expected_geoms']
    #
    #             struct = Structure.from_dict(dd['structure'])
    #
    #             struct = self.lgf.setup_structure(struct)
    #             se = self.lgf.compute_structure_environments_detailed_voronoi(only_indices=atom_indices,
    #                                                                           maximum_distance_factor=1.5)
    #
    #             #All strategies should get the correct environment with their default parameters
    #             strategy.set_structure_environments(se)
    #             for ienv, isite in enumerate(atom_indices):
    #                 ce = strategy.get_site_coordination_environment(struct[isite])
    #                 try:
    #                     coord_env = ce[0]
    #                 except TypeError:
    #                     coord_env = ce
    #                 #Check that the environment found is the expected one
    #                 self.assertEqual(coord_env, expected_geoms[ienv])
    #
    # def test_simplest_chemenv_strategy(self):
    #     strategy = SimplestChemenvStrategy()
    #     self._strategy_test(strategy)
    #
    # def test_simple_abundance_chemenv_strategy(self):
    #     strategy = SimpleAbundanceChemenvStrategy()
    #     self._strategy_test(strategy)

    def test_perfect_environments(self):
        allcg = AllCoordinationGeometries()
        indices_CN = {1: [0],
                      2: [1, 0],
                      3: [1, 0, 2],
                      4: [2, 0, 3, 1],
                      5: [2, 3, 1, 0, 4],
                      6: [0, 2, 3, 1, 5, 4],
                      7: [2, 6, 0, 3, 4, 5, 1],
                      8: [1, 2, 6, 3, 7, 0, 4, 5],
                      9: [5, 2, 6, 0, 4, 7, 3, 8, 1],
                      10: [8, 5, 6, 3, 0, 7, 2, 4, 9, 1],
                      11: [7, 6, 4, 1, 2, 5, 0, 8, 9, 10, 3],
                      12: [5, 8, 9, 0, 3, 1, 4, 2, 6, 11, 10, 7],
                      13: [4, 11, 5, 12, 1, 2, 8, 3, 0, 6, 9, 7, 10],
                      }

        for coordination in range(1, 14):
            for mp_symbol in allcg.get_implemented_geometries(coordination=coordination,
                                                              returned='mp_symbol'):
                cg = allcg.get_geometry_from_mp_symbol(mp_symbol=mp_symbol)
                self.lgf.allcg = AllCoordinationGeometries(only_symbols=[mp_symbol])
                self.lgf.setup_test_perfect_environment(mp_symbol, randomness=False,
                                                        indices=indices_CN[coordination],
                                                        random_translation='NONE', random_rotation='NONE',
                                                        random_scale='NONE')
                se = self.lgf.compute_structure_environments(only_indices=[0],
                                                             maximum_distance_factor=1.01*cg.distfactor_max,
                                                             min_cn=cg.coordination_number,
                                                             max_cn=cg.coordination_number,
                                                             only_symbols=[mp_symbol]
                                                             )
                self.assertAlmostEqual(se.get_csm(0, mp_symbol)['symmetry_measure'], 0.0, delta=1e-8,
                                       msg='Failed to get perfect environment with mp_symbol {}'.format(mp_symbol))

    def test_disable_hints(self):
        allcg = AllCoordinationGeometries()
        mp_symbol = 'SH:13'
        mp_symbols = ['SH:13', 'HP:12']
        cg = allcg.get_geometry_from_mp_symbol(mp_symbol=mp_symbol)
        mypoints = cg.points
        mypoints[-1] = [0.9*cc for cc in mypoints[-1]]
        self.lgf.allcg = AllCoordinationGeometries(only_symbols=[mp_symbol])
        self.lgf.setup_test_perfect_environment(mp_symbol, randomness=False,
                                                indices=[4, 11, 5, 12, 1, 2, 8, 3, 0, 6, 9, 7, 10],
                                                random_translation='NONE', random_rotation='NONE',
                                                random_scale='NONE', points=mypoints)
        se_nohints = self.lgf.compute_structure_environments(only_indices=[0],
                                                             maximum_distance_factor=1.02 * cg.distfactor_max,
                                                             min_cn=12,
                                                             max_cn=13,
                                                             only_symbols=mp_symbols,
                                                             get_from_hints=False
                                                             )
        se_hints = self.lgf.compute_structure_environments(only_indices=[0],
                                                           maximum_distance_factor=1.02 * cg.distfactor_max,
                                                           min_cn=12,
                                                           max_cn=13,
                                                           only_symbols=mp_symbols,
                                                           get_from_hints=True
                                                           )
        with self.assertRaises(KeyError):
            abc = se_nohints.ce_list[0][12]
            abc.minimum_geometries()
        self.assertAlmostEqual(se_hints.ce_list[0][13][0], se_nohints.ce_list[0][13][0])
        self.assertTrue(set(se_nohints.ce_list[0].keys()).issubset(set(se_hints.ce_list[0].keys())))
Ejemplo n.º 12
0
class CoordinationGeometryFinderTest(unittest2.TestCase):
    def setUp(self):
        self.lgf = LocalGeometryFinder()
        self.lgf.setup_parameters(centering_type='standard')
        self.strategies = [
            SimplestChemenvStrategy(),
            SimpleAbundanceChemenvStrategy()
        ]

    # def _strategy_test(self, strategy):
    #     files = []
    #     for (dirpath, dirnames, filenames) in os.walk(json_files_dir):
    #         files.extend(filenames)
    #         break
    #
    #     for ifile, json_file in enumerate(files):
    #         with self.subTest(json_file=json_file):
    #             f = open("{}/{}".format(json_files_dir, json_file), 'r')
    #             dd = json.load(f)
    #             f.close()
    #
    #             atom_indices = dd['atom_indices']
    #             expected_geoms = dd['expected_geoms']
    #
    #             struct = Structure.from_dict(dd['structure'])
    #
    #             struct = self.lgf.setup_structure(struct)
    #             se = self.lgf.compute_structure_environments_detailed_voronoi(only_indices=atom_indices,
    #                                                                           maximum_distance_factor=1.5)
    #
    #             #All strategies should get the correct environment with their default parameters
    #             strategy.set_structure_environments(se)
    #             for ienv, isite in enumerate(atom_indices):
    #                 ce = strategy.get_site_coordination_environment(struct[isite])
    #                 try:
    #                     coord_env = ce[0]
    #                 except TypeError:
    #                     coord_env = ce
    #                 #Check that the environment found is the expected one
    #                 self.assertEqual(coord_env, expected_geoms[ienv])
    #
    # def test_simplest_chemenv_strategy(self):
    #     strategy = SimplestChemenvStrategy()
    #     self._strategy_test(strategy)
    #
    # def test_simple_abundance_chemenv_strategy(self):
    #     strategy = SimpleAbundanceChemenvStrategy()
    #     self._strategy_test(strategy)

    def test_perfect_environments(self):
        for coordination in range(1, 13):
            for mp_symbol in AllCoordinationGeometries(
            ).get_implemented_geometries(coordination=coordination,
                                         returned='mp_symbol'):
                with self.subTest(msg=mp_symbol, mp_symbol=mp_symbol):
                    self.lgf.setup_test_perfect_environment(
                        mp_symbol,
                        randomness=False,
                        indices='RANDOM',
                        random_translation=True,
                        random_rotation=True,
                        random_scale=True)
                    se = self.lgf.compute_structure_environments_detailed_voronoi(
                        only_indices=[0], maximum_distance_factor=1.5)
                    self.assertAlmostEqual(
                        se.get_csm(0, mp_symbol)['symmetry_measure'], 0.0, 4)