Esempio n. 1
0
def analyse_local_coord_env(atoms=None, ):
    """
    """
    #| - analyse_local_coord_env
    out_dict = dict()

    Ir_indices = []
    for i, s in enumerate(atoms.get_chemical_symbols()):
        if s == "Ir":
            Ir_indices.append(i)

    struct = AseAtomsAdaptor.get_structure(atoms)

    lgf = LocalGeometryFinder()
    lgf.setup_structure(structure=struct)

    se = lgf.compute_structure_environments(maximum_distance_factor=1.41,
                                            only_cations=False)

    strategy = MultiWeightsChemenvStrategy.stats_article_weights_parameters()

    lse = LightStructureEnvironments.from_structure_environments(
        strategy=strategy, structure_environments=se)

    isite = 0
    cor_env = []
    coor_env_dict = dict()
    for isite in Ir_indices:
        c_env = lse.coordination_environments[isite]
        coor_env_dict[isite] = c_env
        cor_env += [c_env[0]['ce_symbol']]

    out_dict["coor_env_dict"] = coor_env_dict

    return (out_dict)
Esempio n. 2
0
    def from_dict(cls, d):
        """

        Args:
            d ():

        Returns:

        """
        # Reconstructs the graph with integer as nodes (json's as_dict replaces integer keys with str keys)
        cgraph = nx.from_dict_of_dicts(d["connectivity_graph"],
                                       create_using=nx.MultiGraph,
                                       multigraph_input=True)
        cgraph = nx.relabel_nodes(
            cgraph, int
        )  # Just relabel the nodes using integer casting (maps str->int)
        # Relabel multiedges (removes multiedges with str keys and adds them back with int keys)
        edges = set(cgraph.edges())
        for n1, n2 in edges:
            new_edges = {
                int(iedge): edata
                for iedge, edata in cgraph[n1][n2].items()
            }
            cgraph.remove_edges_from([
                (n1, n2, iedge) for iedge, edata in cgraph[n1][n2].items()
            ])
            cgraph.add_edges_from([(n1, n2, iedge, edata)
                                   for iedge, edata in new_edges.items()])
        return cls(
            LightStructureEnvironments.from_dict(
                d["light_structure_environments"]),
            connectivity_graph=cgraph,
            environment_subgraphs=None,
        )
Esempio n. 3
0
    def test_serialization(self):
        BaTiO3_se_fpath = os.path.join(
            self.TEST_FILES_DIR,
            "chemenv",
            "structure_environments_files",
            "se_mp-5020.json",
        )
        with open(BaTiO3_se_fpath) as f:
            dd = json.load(f)
        se = StructureEnvironments.from_dict(dd)
        lse = LightStructureEnvironments.from_structure_environments(
            strategy=SimplestChemenvStrategy(), structure_environments=se
        )
        cf = ConnectivityFinder()
        sc = cf.get_structure_connectivity(light_structure_environments=lse)
        sc_from_dict = StructureConnectivity.from_dict(sc.as_dict())
        assert sc.light_structure_environments == sc_from_dict.light_structure_environments
        assert set(sc._graph.nodes()) == set(sc_from_dict._graph.nodes())
        assert set(sc._graph.edges()) == set(sc_from_dict._graph.edges())

        sc_from_json = StructureConnectivity.from_dict(json.loads(json.dumps(sc.as_dict())))
        assert sc.light_structure_environments == sc_from_json.light_structure_environments
        assert set(sc._graph.nodes()) == set(sc_from_json._graph.nodes())
        assert set(sc._graph.edges()) == set(sc_from_json._graph.edges())

        if bson is not None:
            bson_data = bson.BSON.encode(sc.as_dict())
            sc_from_bson = StructureConnectivity.from_dict(bson_data.decode())
            assert sc.light_structure_environments == sc_from_bson.light_structure_environments
            assert set(sc._graph.nodes()) == set(sc_from_bson._graph.nodes())
            assert set(sc._graph.edges()) == set(sc_from_bson._graph.edges())
    def setUp(self):
        with open("mp-7000.json", "r") as f:
            dict_lse = json.load(f)
        lse = LightStructureEnvironments.from_dict(dict_lse)
        struct = lse.structure
        bva = BVAnalyzer()
        valences = bva.get_valences(structure=struct)
        lgf = LocalGeometryFinder()
        lgf.setup_structure(structure=struct)
        se = lgf.compute_structure_environments(maximum_distance_factor=1.41, only_cations=False, valences=valences)
        strategy = MultiWeightsChemenvStrategy.stats_article_weights_parameters()
        self.lse = LightStructureEnvironments.from_structure_environments(strategy=strategy, structure_environments=se)

        with open("mp-5634.json", "r") as f:
            dict_lse2 = json.load(f)
        self.lse2 = LightStructureEnvironments.from_dict(dict_lse2)
 def setUp(self):
     self.paulingconnetion = PaulingConnection(DISTANCE=8.0)
     self.matlist = ["mp-7000.json"]
     self.lse_dict = {}
     for mat in self.matlist:
         with open(mat, "r") as f:
             dict_lse = json.load(f)
         lse = LightStructureEnvironments.from_dict(dict_lse)
         self.lse_dict[mat] = lse
 def setUp(self):
     self.matlist = ["mp-1788.json", "mp-7000.json", "mp-19359.json", "mp-306.json", "mp-886.json", "mp-2605.json"]
     self.lse_dict = {}
     self.Pauling_dict = {}
     for mat in self.matlist:
         with open(mat, "r") as f:
             dict_lse = json.load(f)
         lse = LightStructureEnvironments.from_dict(dict_lse)
         self.lse_dict[mat] = lse
         self.Pauling_dict[mat] = Pauling0(self.lse_dict[mat])
Esempio n. 7
0
    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._strategy, light_se2._strategy)
        self.assertEqual(light_se._structure, light_se2._structure)
        self.assertEqual(light_se._bva_valences, light_se2._bva_valences)
        self.assertEqual(light_se._coordination_environments, light_se2._coordination_environments)
        self.assertEqual(light_se._neighbors, light_se2._neighbors)
        self.assertEqual(light_se, light_se2)
Esempio n. 8
0
    def test_read_write_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(
            only_indices=atom_indices,
            maximum_distance_factor=2.25,
            get_from_hints=True)

        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()
        lse = LightStructureEnvironments.from_structure_environments(
            structure_environments=se, strategy=strategy, valences="undefined")

        f = open("tmp_dir/lse.json", "w")
        json.dump(lse.as_dict(), f)
        f.close()

        f = open("tmp_dir/lse.json", "r")
        dd = json.load(f)
        f.close()

        lse2 = LightStructureEnvironments.from_dict(dd)

        self.assertEqual(lse, lse2)
 def setUp(self):
     self.matlist = ["mp-7000.json", "mp-19359.json", "mp-1788.json", "mp-12236.json", "mp-5986.json"]
     self.lse_dict = {}
     self.Pauling_List = {}
     for mat in self.matlist:
         with open(mat, "r") as f:
             dict_lse = json.load(f)
         lse = LightStructureEnvironments.from_dict(dict_lse)
         self.lse_dict[mat] = lse
         self.Pauling_List[mat] = Pauling5()
         self.Pauling_List[mat].newsetup(lse=lse, save_to_file=False)
Esempio n. 10
0
    def test_read_write_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(
            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()
        lse = LightStructureEnvironments.from_structure_environments(
            structure_environments=se, strategy=strategy, valences='undefined')

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

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

        lse2 = LightStructureEnvironments.from_dict(dd)

        self.assertEqual(lse, lse2)
 def setUp(self):
     # test it for further candidates -> differing in CN, differing in val
     self.matlist = ["mp-7000.json", "mp-19359.json", "mp-1788.json", "mp-5986.json", "mp-19418.json"]
     self.lse_dict = {}
     self.Pauling_List = {}
     for mat in self.matlist:
         with open(mat, "r") as f:
             dict_lse = json.load(f)
         lse = LightStructureEnvironments.from_dict(dict_lse)
         self.lse_dict[mat] = lse
         self.Pauling_List[mat] = Pauling4()
         self.Pauling_List[mat].newsetup(lse=lse, save_to_file=False)
Esempio n. 12
0
    def test_read_write_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(only_indices=atom_indices,
                                                     maximum_distance_factor=2.25,
                                                     get_from_hints=True)

        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()
        lse = LightStructureEnvironments.from_structure_environments(structure_environments=se, strategy=strategy,
                                                                     valences='undefined')

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

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

        lse2 = LightStructureEnvironments.from_dict(dd)

        self.assertEqual(lse, lse2)
 def setUp(self):
     self.matlist = ["mp-7000.json", "mp-19418.json"]
     self.lse_dict = {}
     for mat in self.matlist:
         with open(mat, "r") as f:
             dict_lse = json.load(f)
         lse = LightStructureEnvironments.from_dict(dict_lse)
         self.lse_dict[mat] = lse
     self.pauling3and4_dist1 = Pauling3and4()
     self.pauling3and4_dist1.newsetup(self.lse_dict["mp-7000.json"], save_to_file=False, filename=False,
                                      distance=4.5)
     self.pauling3and4_dist2 = Pauling3and4()
     self.pauling3and4_dist2.newsetup(self.lse_dict["mp-7000.json"], save_to_file=False, filename=False)
     self.pauling3and4_dict3 = Pauling3and4()
     self.pauling3and4_dict3.newsetup(self.lse_dict["mp-19418.json"], save_to_file=False, filename=False, distance=4)
    def setUp(self):
        # TODO: initilaize normal pauling as well
        self.matlist = ["mp-7000.json", "mp-566090.json", "mp-2605.json", "mp-4056.json"]
        self.lse_dict = {}
        self.Pauling_dict = {}
        self.Pauling_dict_perc1 = {}
        self.Pauling_dict_perc02 = {}
        self.Pauling_dict_realtwo = {}

        for mat in self.matlist:
            with open(mat, "r") as f:
                dict_lse = json.load(f)
            lse = LightStructureEnvironments.from_dict(dict_lse)
            self.lse_dict[mat] = lse
            self.Pauling_dict[mat] = Pauling2_optimized_environments(self.lse_dict[mat], perc=0.3)
            self.Pauling_dict_perc02[mat] = Pauling2_optimized_environments(self.lse_dict[mat], perc=0.2)
            self.Pauling_dict_perc1[mat] = Pauling2_optimized_environments(self.lse_dict[mat], perc=1.0)
            self.Pauling_dict_realtwo[mat] = Pauling2(self.lse_dict[mat])
Esempio n. 15
0
def getSimplestChemenvStrategy(struct):
    # Setup the local geometry finder
    lgf = LocalGeometryFinder()
    lgf.setup_parameters(centering_type='centroid',
                         include_central_site_in_centroid=True)

    #you can also save the logging to a file, just remove the comment

    #     logging.basicConfig(#filename='chemenv_structure_environments.log',
    #                         format='%(levelname)s:%(module)s:%(funcName)s:%(message)s',
    #                         level=logging.DEBUG)
    lgf.setup_structure(structure=struct)
    se = lgf.compute_structure_environments(maximum_distance_factor=1.41,
                                            only_cations=False)
    strategy = SimplestChemenvStrategy(distance_cutoff=1.4, angle_cutoff=0.3)
    lse = LightStructureEnvironments.from_structure_environments(
        strategy=strategy, structure_environments=se)
    return lse.coordination_environments
Esempio n. 16
0
    def run_task(self, fw_spec):
        logging.basicConfig(filename='chemenv_light_structure_environments.log',
                            format='%(levelname)s:%(module)s:%(funcName)s:%(message)s',
                            level=logging.DEBUG)

        identifier = fw_spec['identifier']
        criteria = {'identifier': identifier}
        # Where to get the full structure environments object
        se_database = fw_spec['structure_environments_database']
        entry = se_database.collection.find_one(criteria)
        if fw_spec['structure_environments_setup'] == 'from_gridfs':
            gfs_fileobject = se_database.gridfs.get(entry['structure_environments'])
            dd = json.load(gfs_fileobject)
            se = StructureEnvironments.from_dict(dd)
        elif fw_spec['structure_environments_setup'] == 'from_storedfile':
            se_storage_server = fw_spec['se_storage_server']
            se_filepath = entry['structure_environments_file']
            se_storage_server.get(se_filepath, 'se.json')
            f = open('se.json', 'r')
            dd = json.load(f)
            f.close()
            se = StructureEnvironments.from_dict(dd)
        else:
            raise RuntimeError('Wrong structure_environments_setup : '
                               '"{}" is not allowed'.format(fw_spec['structure_environments_setup']))

        # Compute the light structure environments
        chemenv_strategy = fw_spec['chemenv_strategy']
        if 'valences' in fw_spec:
            valences = fw_spec['valences']
            valences_origin = fw_spec['valences_origin']
        else:
            valences = 'undefined'
            valences_origin = 'None'
        lse = LightStructureEnvironments.from_structure_environments(strategy=chemenv_strategy,
                                                                     structure_environments=se,
                                                                     valences=valences,
                                                                     valences_origin=valences_origin)

        # Write to json file
        if 'json_file' in fw_spec:
            json_file = fw_spec['json_file']
        else:
            json_file = 'light_structure_environments.json'
        f = open(json_file, 'w')
        json.dump(lse.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 lse.structure.composition.elements],
                     'nelements': len(lse.structure.composition.elements),
                     'pretty_formula': lse.structure.composition.reduced_formula,
                     'nsites': len(lse.structure),
                     'chemenv_statistics': lse.get_statistics(statistics_fields='ALL', bson_compatible=True)
                     }
            saving_option = fw_spec['saving_option']
            if saving_option == 'gridfs':
                gridfs_msonables = {'structure': lse.structure,
                                    'light_structure_environments': lse}
            elif saving_option == 'storefile':
                gridfs_msonables = None
                if 'lse_prefix' in fw_spec:
                    lse_prefix = fw_spec['lse_prefix']
                    if not lse_prefix.isalpha():
                        raise ValueError('Prefix for light_structure_environments file is "{}" '
                                         'while it should be alphabetic'.format(lse_prefix))
                else:
                    lse_prefix = ''
                if lse_prefix:
                    lse_rfilename = '{}_{}.json'.format(lse_prefix, fw_spec['storefile_basename'])
                else:
                    lse_rfilename = '{}.json'.format(fw_spec['storefile_basename'])
                lse_rfilepath = '{}/{}'.format(fw_spec['storefile_dirpath'], lse_rfilename)
                storage_server = fw_spec['storage_server']
                storage_server.put(localpath=json_file, remotepath=lse_rfilepath, overwrite=True, makedirs=False)
                entry['light_structure_environments_file'] = lse_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)
 def from_dict(cls, d):
     return cls(LightStructureEnvironments.from_dict(d['light_structure_environments']),
                connectivity_graph=nx.from_dict_of_dicts(d['connectivity_graph'], multigraph_input=True),
                environment_subgraphs={env_key: nx.from_dict_of_dicts(subgraph, multigraph_input=True)
                                       for env_key, subgraph in d['environment_subgraphs'].items()})
    def test_light_structure_environments(self):
        with ScratchDir("."):
            with open(f"{se_files_dir}/se_mp-7000.json") as f:
                dd = json.load(f)

            se = StructureEnvironments.from_dict(dd)

            strategy = SimplestChemenvStrategy()
            lse = LightStructureEnvironments.from_structure_environments(
                structure_environments=se,
                strategy=strategy,
                valences="undefined")
            isite = 6
            nb_set = lse.neighbors_sets[isite][0]
            neighb_coords = [
                np.array([0.2443798, 1.80409653, -1.13218359]),
                np.array([1.44020353, 1.11368738, 1.13218359]),
                np.array([2.75513098, 2.54465207, -0.70467298]),
                np.array([0.82616785, 3.65833945, 0.70467298]),
            ]
            neighb_indices = [0, 3, 5, 1]
            neighb_images = [[0, 0, -1], [0, 0, 0], [0, 0, -1], [0, 0, 0]]

            np.testing.assert_array_almost_equal(neighb_coords,
                                                 nb_set.neighb_coords)
            np.testing.assert_array_almost_equal(
                neighb_coords, [s.coords for s in nb_set.neighb_sites])
            nb_sai = nb_set.neighb_sites_and_indices
            np.testing.assert_array_almost_equal(
                neighb_coords, [sai["site"].coords for sai in nb_sai])
            np.testing.assert_array_almost_equal(
                neighb_indices, [sai["index"] for sai in nb_sai])
            nb_iai = nb_set.neighb_indices_and_images
            np.testing.assert_array_almost_equal(
                neighb_indices, [iai["index"] for iai in nb_iai])
            np.testing.assert_array_equal(
                neighb_images, [iai["image_cell"] for iai in nb_iai])

            self.assertEqual(nb_set.__len__(), 4)
            self.assertEqual(nb_set.__hash__(), 4)

            self.assertFalse(nb_set.__ne__(nb_set))

            self.assertEqual(
                nb_set.__str__(),
                "Neighbors Set for site #6 :\n"
                " - Coordination number : 4\n"
                " - Neighbors sites indices : 0, 1, 2, 3\n",
            )

            stats = lse.get_statistics()

            neighbors = lse.strategy.get_site_neighbors(
                site=lse.structure[isite])
            self.assertArrayAlmostEqual(
                neighbors[0].coords,
                np.array([0.2443798, 1.80409653, -1.13218359]))
            self.assertArrayAlmostEqual(
                neighbors[1].coords,
                np.array([1.44020353, 1.11368738, 1.13218359]))
            self.assertArrayAlmostEqual(
                neighbors[2].coords,
                np.array([2.75513098, 2.54465207, -0.70467298]))
            self.assertArrayAlmostEqual(
                neighbors[3].coords,
                np.array([0.82616785, 3.65833945, 0.70467298]))

            equiv_site_index_and_transform = lse.strategy.equivalent_site_index_and_transform(
                neighbors[0])
            self.assertEqual(equiv_site_index_and_transform[0], 0)
            self.assertArrayAlmostEqual(equiv_site_index_and_transform[1],
                                        [0.0, 0.0, 0.0])
            self.assertArrayAlmostEqual(equiv_site_index_and_transform[2],
                                        [0.0, 0.0, -1.0])

            equiv_site_index_and_transform = lse.strategy.equivalent_site_index_and_transform(
                neighbors[1])
            self.assertEqual(equiv_site_index_and_transform[0], 3)
            self.assertArrayAlmostEqual(equiv_site_index_and_transform[1],
                                        [0.0, 0.0, 0.0])
            self.assertArrayAlmostEqual(equiv_site_index_and_transform[2],
                                        [0.0, 0.0, 0.0])

            self.assertEqual(stats["atom_coordination_environments_present"],
                             {"Si": {
                                 "T:4": 3.0
                             }})
            self.assertEqual(stats["coordination_environments_atom_present"],
                             {"T:4": {
                                 "Si": 3.0
                             }})
            self.assertEqual(
                stats["fraction_atom_coordination_environments_present"],
                {"Si": {
                    "T:4": 1.0
                }},
            )

            site_info_ce = lse.get_site_info_for_specie_ce(specie=Species(
                "Si", 4),
                                                           ce_symbol="T:4")
            np.testing.assert_array_almost_equal(site_info_ce["fractions"],
                                                 [1.0, 1.0, 1.0])
            np.testing.assert_array_almost_equal(
                site_info_ce["csms"],
                [
                    0.009887784240541068, 0.009887786546730826,
                    0.009887787384385317
                ],
            )
            self.assertEqual(site_info_ce["isites"], [6, 7, 8])

            site_info_allces = lse.get_site_info_for_specie_allces(
                specie=Species("Si", 4))

            self.assertEqual(site_info_allces["T:4"], site_info_ce)

            self.assertFalse(lse.contains_only_one_anion("I-"))
            self.assertFalse(lse.contains_only_one_anion_atom("I"))
            self.assertTrue(
                lse.site_contains_environment(isite=isite, ce_symbol="T:4"))
            self.assertFalse(
                lse.site_contains_environment(isite=isite, ce_symbol="S:4"))
            self.assertFalse(
                lse.structure_contains_atom_environment(atom_symbol="Si",
                                                        ce_symbol="S:4"))
            self.assertTrue(
                lse.structure_contains_atom_environment(atom_symbol="Si",
                                                        ce_symbol="T:4"))
            self.assertFalse(
                lse.structure_contains_atom_environment(atom_symbol="O",
                                                        ce_symbol="T:4"))
            self.assertTrue(lse.uniquely_determines_coordination_environments)
            self.assertFalse(lse.__ne__(lse))

            envs = lse.strategy.get_site_coordination_environments(
                lse.structure[6])
            self.assertEqual(len(envs), 1)
            self.assertEqual(envs[0][0], "T:4")

            multi_strategy = MultiWeightsChemenvStrategy.stats_article_weights_parameters(
            )

            lse_multi = LightStructureEnvironments.from_structure_environments(
                strategy=multi_strategy,
                structure_environments=se,
                valences="undefined")
            self.assertAlmostEqual(
                lse_multi.coordination_environments[isite][0]["csm"],
                0.009887784240541068,
            )
            self.assertAlmostEqual(
                lse_multi.coordination_environments[isite][0]["ce_fraction"],
                1.0)
            self.assertEqual(
                lse_multi.coordination_environments[isite][0]["ce_symbol"],
                "T:4")
Esempio n. 19
0
        def get_chemenv_analysis(struct, distance_cutoff, angle_cutoff):

            if not struct:
                raise PreventUpdate

            struct = self.from_data(struct)
            distance_cutoff = float(distance_cutoff)
            angle_cutoff = float(angle_cutoff)

            # decide which indices to present to user
            sga = SpacegroupAnalyzer(struct)
            symm_struct = sga.get_symmetrized_structure()
            inequivalent_indices = [
                indices[0] for indices in symm_struct.equivalent_indices
            ]
            wyckoffs = symm_struct.wyckoff_symbols

            lgf = LocalGeometryFinder()
            lgf.setup_structure(structure=struct)

            se = lgf.compute_structure_environments(
                maximum_distance_factor=distance_cutoff + 0.01,
                only_indices=inequivalent_indices,
            )
            strategy = SimplestChemenvStrategy(distance_cutoff=distance_cutoff,
                                               angle_cutoff=angle_cutoff)
            lse = LightStructureEnvironments.from_structure_environments(
                strategy=strategy, structure_environments=se)
            all_ce = AllCoordinationGeometries()

            envs = []
            unknown_sites = []

            for index, wyckoff in zip(inequivalent_indices, wyckoffs):

                datalist = {
                    "Site": struct[index].species_string,
                    "Wyckoff Label": wyckoff,
                }

                if not lse.neighbors_sets[index]:
                    unknown_sites.append(
                        f"{struct[index].species_string} ({wyckoff})")
                    continue

                # represent the local environment as a molecule
                mol = Molecule.from_sites(
                    [struct[index]] +
                    lse.neighbors_sets[index][0].neighb_sites)
                mol = mol.get_centered_molecule()
                mg = MoleculeGraph.with_empty_graph(molecule=mol)
                for i in range(1, len(mol)):
                    mg.add_edge(0, i)

                view = html.Div(
                    [
                        StructureMoleculeComponent(
                            struct_or_mol=mg,
                            static=True,
                            id=
                            f"{struct.composition.reduced_formula}_site_{index}",
                            scene_settings={
                                "enableZoom": False,
                                "defaultZoom": 0.6
                            },
                        ).all_layouts["struct"]
                    ],
                    style={
                        "width": "300px",
                        "height": "300px"
                    },
                )

                env = lse.coordination_environments[index]
                co = all_ce.get_geometry_from_mp_symbol(env[0]["ce_symbol"])
                name = co.name
                if co.alternative_names:
                    name += f" (also known as {', '.join(co.alternative_names)})"

                datalist.update({
                    "Environment":
                    name,
                    "IUPAC Symbol":
                    co.IUPAC_symbol_str,
                    get_tooltip(
                        "CSM",
                        '"Continuous Symmetry Measure," a measure of how symmetrical a '
                        "local environment is from most symmetrical at 0% to least "
                        "symmetrical at 100%",
                    ):
                    f"{env[0]['csm']:.2f}%",
                    "Interactive View":
                    view,
                })

                envs.append(get_data_list(datalist))

            # TODO: switch to tiles?
            envs_grouped = [envs[i:i + 2] for i in range(0, len(envs), 2)]
            analysis_contents = []
            for env_group in envs_grouped:
                analysis_contents.append(
                    Columns([Column(e, size=6) for e in env_group]))

            if unknown_sites:
                unknown_sites = html.Strong(
                    f"The following sites were not identified: {', '.join(unknown_sites)}. "
                    f"Please try changing the distance or angle cut-offs to identify these sites."
                )
            else:
                unknown_sites = html.Span()

            return html.Div(
                [html.Div(analysis_contents),
                 html.Br(), unknown_sites])
    def test_light_structure_environments(self):
        f = open("{}/{}".format(se_files_dir, 'se_mp-7000.json'), 'r')
        dd = json.load(f)
        f.close()

        se = StructureEnvironments.from_dict(dd)

        strategy = SimplestChemenvStrategy()
        lse = LightStructureEnvironments.from_structure_environments(structure_environments=se, strategy=strategy,
                                                                     valences='undefined')
        isite = 6
        nb_set = lse.neighbors_sets[isite][0]
        neighb_coords = [np.array([0.2443798, 1.80409653, -1.13218359]),
                         np.array([1.44020353, 1.11368738, 1.13218359]),
                         np.array([2.75513098, 2.54465207, -0.70467298]),
                         np.array([0.82616785, 3.65833945, 0.70467298])]
        neighb_indices = [0, 3, 5, 1]
        neighb_images = [[0, 0, -1], [0, 0, 0], [0, 0, -1], [0, 0, 0]]

        np.testing.assert_array_almost_equal(neighb_coords, nb_set.neighb_coords)
        np.testing.assert_array_almost_equal(neighb_coords, [s.coords for s in nb_set.neighb_sites])
        nb_sai = nb_set.neighb_sites_and_indices
        np.testing.assert_array_almost_equal(neighb_coords, [sai['site'].coords for sai in nb_sai])
        np.testing.assert_array_almost_equal(neighb_indices, [sai['index'] for sai in nb_sai])
        nb_iai = nb_set.neighb_indices_and_images
        np.testing.assert_array_almost_equal(neighb_indices, [iai['index'] for iai in nb_iai])
        np.testing.assert_array_equal(neighb_images, [iai['image_cell'] for iai in nb_iai])

        self.assertEqual(nb_set.__len__(), 4)
        self.assertEqual(nb_set.__hash__(), 4)

        self.assertFalse(nb_set.__ne__(nb_set))

        self.assertEqual(nb_set.__str__(), 'Neighbors Set for site #6 :\n'
                                           ' - Coordination number : 4\n'
                                           ' - Neighbors sites indices : 0, 1, 2, 3\n')

        stats = lse.get_statistics()

        neighbors = lse.strategy.get_site_neighbors(site=lse.structure[isite])
        self.assertArrayAlmostEqual(neighbors[0].coords, np.array([ 0.2443798, 1.80409653, -1.13218359]))
        self.assertArrayAlmostEqual(neighbors[1].coords, np.array([ 1.44020353, 1.11368738, 1.13218359]))
        self.assertArrayAlmostEqual(neighbors[2].coords, np.array([ 2.75513098, 2.54465207, -0.70467298]))
        self.assertArrayAlmostEqual(neighbors[3].coords, np.array([ 0.82616785, 3.65833945, 0.70467298]))

        equiv_site_index_and_transform = lse.strategy.equivalent_site_index_and_transform(neighbors[0])
        self.assertEqual(equiv_site_index_and_transform[0], 0)
        self.assertArrayAlmostEqual(equiv_site_index_and_transform[1], [0.0, 0.0, 0.0])
        self.assertArrayAlmostEqual(equiv_site_index_and_transform[2], [0.0, 0.0, -1.0])

        equiv_site_index_and_transform = lse.strategy.equivalent_site_index_and_transform(neighbors[1])
        self.assertEqual(equiv_site_index_and_transform[0], 3)
        self.assertArrayAlmostEqual(equiv_site_index_and_transform[1], [0.0, 0.0, 0.0])
        self.assertArrayAlmostEqual(equiv_site_index_and_transform[2], [0.0, 0.0, 0.0])

        self.assertEqual(stats['atom_coordination_environments_present'], {'Si': {'T:4': 3.0}})
        self.assertEqual(stats['coordination_environments_atom_present'], {'T:4': {'Si': 3.0}})
        self.assertEqual(stats['fraction_atom_coordination_environments_present'], {'Si': {'T:4': 1.0}})

        site_info_ce = lse.get_site_info_for_specie_ce(specie=Specie('Si', 4), ce_symbol='T:4')
        np.testing.assert_array_almost_equal(site_info_ce['fractions'], [1.0, 1.0, 1.0])
        np.testing.assert_array_almost_equal(site_info_ce['csms'],
                                             [0.009887784240541068, 0.009887786546730826, 0.009887787384385317])
        self.assertEqual(site_info_ce['isites'], [6, 7, 8])

        site_info_allces = lse.get_site_info_for_specie_allces(specie=Specie('Si', 4))

        self.assertEqual(site_info_allces['T:4'], site_info_ce)

        self.assertFalse(lse.contains_only_one_anion('I-'))
        self.assertFalse(lse.contains_only_one_anion_atom('I'))
        self.assertTrue(lse.site_contains_environment(isite=isite, ce_symbol='T:4'))
        self.assertFalse(lse.site_contains_environment(isite=isite, ce_symbol='S:4'))
        self.assertFalse(lse.structure_contains_atom_environment(atom_symbol='Si', ce_symbol='S:4'))
        self.assertTrue(lse.structure_contains_atom_environment(atom_symbol='Si', ce_symbol='T:4'))
        self.assertFalse(lse.structure_contains_atom_environment(atom_symbol='O', ce_symbol='T:4'))
        self.assertTrue(lse.uniquely_determines_coordination_environments)
        self.assertFalse(lse.__ne__(lse))

        envs = lse.strategy.get_site_coordination_environments(lse.structure[6])
        self.assertEqual(len(envs), 1)
        self.assertEqual(envs[0][0], 'T:4')

        multi_strategy = MultiWeightsChemenvStrategy.stats_article_weights_parameters()

        lse_multi = LightStructureEnvironments.from_structure_environments(strategy=multi_strategy,
                                                                           structure_environments=se,
                                                                           valences='undefined')
        self.assertAlmostEqual(lse_multi.coordination_environments[isite][0]['csm'], 0.009887784240541068)
        self.assertAlmostEqual(lse_multi.coordination_environments[isite][0]['ce_fraction'], 1.0)
        self.assertEqual(lse_multi.coordination_environments[isite][0]['ce_symbol'], 'T:4')
        Ir_indices = [
            i for i, s in enumerate(atoms.get_chemical_symbols()) if s == 'Ir'
        ]

        struct = AseAtomsAdaptor.get_structure(atoms)

        lgf = LocalGeometryFinder()
        lgf.setup_structure(structure=struct)

        se = lgf.compute_structure_environments(maximum_distance_factor=1.41,
                                                only_cations=False)

        strategy = MultiWeightsChemenvStrategy.stats_article_weights_parameters(
        )

        lse = LightStructureEnvironments.from_structure_environments(
            strategy=strategy, structure_environments=se)

        isite = 0

        cor_env = []
        for isite in Ir_indices:
            c_env = lse.coordination_environments[isite]
            if len(c_env) == 0:
                continue
            cor_env += [c_env[0]['ce_symbol']]

        if len(cor_env) == 0:
            continue
        uniques, counts = np.unique(cor_env, return_counts=True)

        if len(uniques) > 1:
Esempio n. 22
0
    def run_task(self, fw_spec):
        logging.basicConfig(
            filename='chemenv_light_structure_environments.log',
            format='%(levelname)s:%(module)s:%(funcName)s:%(message)s',
            level=logging.DEBUG)

        identifier = fw_spec['identifier']
        criteria = {'identifier': identifier}
        # Where to get the full structure environments object
        se_database = fw_spec['structure_environments_database']
        entry = se_database.collection.find_one(criteria)
        if fw_spec['structure_environments_setup'] == 'from_gridfs':
            gfs_fileobject = se_database.gridfs.get(
                entry['structure_environments'])
            dd = json.load(gfs_fileobject)
            se = StructureEnvironments.from_dict(dd)
        elif fw_spec['structure_environments_setup'] == 'from_storedfile':
            se_storage_server = fw_spec['se_storage_server']
            se_filepath = entry['structure_environments_file']
            se_storage_server.get(se_filepath, 'se.json')
            f = open('se.json', 'r')
            dd = json.load(f)
            f.close()
            se = StructureEnvironments.from_dict(dd)
        else:
            raise RuntimeError('Wrong structure_environments_setup : '
                               '"{}" is not allowed'.format(
                                   fw_spec['structure_environments_setup']))

        # Compute the light structure environments
        chemenv_strategy = fw_spec['chemenv_strategy']
        if 'valences' in fw_spec:
            valences = fw_spec['valences']
            valences_origin = fw_spec['valences_origin']
        else:
            valences = 'undefined'
            valences_origin = 'None'
        lse = LightStructureEnvironments.from_structure_environments(
            strategy=chemenv_strategy,
            structure_environments=se,
            valences=valences,
            valences_origin=valences_origin)

        # Write to json file
        if 'json_file' in fw_spec:
            json_file = fw_spec['json_file']
        else:
            json_file = 'light_structure_environments.json'
        f = open(json_file, 'w')
        json.dump(lse.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 lse.structure.composition.elements],
                'nelements':
                len(lse.structure.composition.elements),
                'pretty_formula':
                lse.structure.composition.reduced_formula,
                'nsites':
                len(lse.structure),
                'chemenv_statistics':
                lse.get_statistics(statistics_fields='ALL',
                                   bson_compatible=True)
            }
            saving_option = fw_spec['saving_option']
            if saving_option == 'gridfs':
                gridfs_msonables = {
                    'structure': lse.structure,
                    'light_structure_environments': lse
                }
            elif saving_option == 'storefile':
                gridfs_msonables = None
                if 'lse_prefix' in fw_spec:
                    lse_prefix = fw_spec['lse_prefix']
                    if not lse_prefix.isalpha():
                        raise ValueError(
                            'Prefix for light_structure_environments file is "{}" '
                            'while it should be alphabetic'.format(lse_prefix))
                else:
                    lse_prefix = ''
                if lse_prefix:
                    lse_rfilename = '{}_{}.json'.format(
                        lse_prefix, fw_spec['storefile_basename'])
                else:
                    lse_rfilename = '{}.json'.format(
                        fw_spec['storefile_basename'])
                lse_rfilepath = '{}/{}'.format(fw_spec['storefile_dirpath'],
                                               lse_rfilename)
                storage_server = fw_spec['storage_server']
                storage_server.put(localpath=json_file,
                                   remotepath=lse_rfilepath,
                                   overwrite=True,
                                   makedirs=False)
                entry['light_structure_environments_file'] = lse_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)
    def test_real_systems(self):
        # Initialize geometry and connectivity finders
        strat = SimplestChemenvStrategy()
        lgf = LocalGeometryFinder()
        cf = ConnectivityFinder()

        # Connectivity of LiFePO4
        struct = self.get_structure("LiFePO4")
        lgf.setup_structure(structure=struct)
        se = lgf.compute_structure_environments(only_atoms=["Li", "Fe", "P"],
                                                maximum_distance_factor=1.2)
        lse = LightStructureEnvironments.from_structure_environments(
            strategy=strat, structure_environments=se)
        # Make sure the initial structure and environments are correct
        for isite in range(0, 4):
            assert lse.structure[isite].specie.symbol == "Li"
            assert lse.coordination_environments[isite][0][
                "ce_symbol"] == "O:6"
        for isite in range(4, 8):
            assert lse.structure[isite].specie.symbol == "Fe"
            assert lse.coordination_environments[isite][0][
                "ce_symbol"] == "O:6"
        for isite in range(8, 12):
            assert lse.structure[isite].specie.symbol == "P"
            assert lse.coordination_environments[isite][0][
                "ce_symbol"] == "T:4"
        # Get the connectivity including all environments and check results
        sc = cf.get_structure_connectivity(lse)
        assert len(sc.environment_subgraphs
                   ) == 0  # Connected component not computed by default
        ccs = sc.get_connected_components(
        )  # by default, will use all the environments (O:6 and T:4 here)
        assert list(sc.environment_subgraphs.keys()) == [
            "O:6-T:4"
        ]  # Now the default components are there
        assert len(sc.environment_subgraphs) == 1
        assert len(ccs) == 1
        cc = ccs[0]
        assert len(cc) == 12
        assert cc.periodicity == "3D"
        assert (
            cc.description() == """Connected component with environment nodes :
Node #0 Li (O:6)
Node #1 Li (O:6)
Node #2 Li (O:6)
Node #3 Li (O:6)
Node #4 Fe (O:6)
Node #5 Fe (O:6)
Node #6 Fe (O:6)
Node #7 Fe (O:6)
Node #8 P (T:4)
Node #9 P (T:4)
Node #10 P (T:4)
Node #11 P (T:4)""")
        assert (cc.description(
            full=True) == """Connected component with environment nodes :
Node #0 Li (O:6), connected to :
  - Node #1 Li (O:6) with delta image cells
     (-1 0 1)
     (-1 1 1)
  - Node #4 Fe (O:6) with delta image cells
     (-1 1 1)
     (0 1 1)
  - Node #5 Fe (O:6) with delta image cells
     (0 0 1)
  - Node #6 Fe (O:6) with delta image cells
     (-1 1 0)
  - Node #7 Fe (O:6) with delta image cells
     (-1 0 0)
     (0 0 0)
  - Node #8 P (T:4) with delta image cells
     (-1 0 1)
     (0 0 1)
  - Node #11 P (T:4) with delta image cells
     (-1 1 0)
     (0 1 0)
Node #1 Li (O:6), connected to :
  - Node #0 Li (O:6) with delta image cells
     (1 -1 -1)
     (1 0 -1)
  - Node #4 Fe (O:6) with delta image cells
     (0 0 0)
     (1 0 0)
  - Node #5 Fe (O:6) with delta image cells
     (1 0 0)
  - Node #6 Fe (O:6) with delta image cells
     (0 0 -1)
  - Node #7 Fe (O:6) with delta image cells
     (0 0 -1)
     (1 0 -1)
  - Node #8 P (T:4) with delta image cells
     (0 0 0)
     (1 0 0)
  - Node #11 P (T:4) with delta image cells
     (0 0 -1)
     (1 0 -1)
Node #2 Li (O:6), connected to :
  - Node #3 Li (O:6) with delta image cells
     (0 0 0)
     (0 1 0)
  - Node #4 Fe (O:6) with delta image cells
     (0 1 0)
  - Node #5 Fe (O:6) with delta image cells
     (0 0 0)
     (1 0 0)
  - Node #6 Fe (O:6) with delta image cells
     (-1 1 0)
     (0 1 0)
  - Node #7 Fe (O:6) with delta image cells
     (0 0 0)
  - Node #9 P (T:4) with delta image cells
     (0 1 0)
     (1 1 0)
  - Node #10 P (T:4) with delta image cells
     (-1 0 0)
     (0 0 0)
Node #3 Li (O:6), connected to :
  - Node #2 Li (O:6) with delta image cells
     (0 -1 0)
     (0 0 0)
  - Node #4 Fe (O:6) with delta image cells
     (0 0 0)
  - Node #5 Fe (O:6) with delta image cells
     (0 0 0)
     (1 0 0)
  - Node #6 Fe (O:6) with delta image cells
     (-1 0 0)
     (0 0 0)
  - Node #7 Fe (O:6) with delta image cells
     (0 0 0)
  - Node #9 P (T:4) with delta image cells
     (0 0 0)
     (1 0 0)
  - Node #10 P (T:4) with delta image cells
     (-1 0 0)
     (0 0 0)
Node #4 Fe (O:6), connected to :
  - Node #0 Li (O:6) with delta image cells
     (0 -1 -1)
     (1 -1 -1)
  - Node #1 Li (O:6) with delta image cells
     (-1 0 0)
     (0 0 0)
  - Node #2 Li (O:6) with delta image cells
     (0 -1 0)
  - Node #3 Li (O:6) with delta image cells
     (0 0 0)
  - Node #5 Fe (O:6) with delta image cells
     (0 -1 0)
     (0 0 0)
     (1 -1 0)
     (1 0 0)
  - Node #8 P (T:4) with delta image cells
     (0 -1 0)
     (0 0 0)
  - Node #9 P (T:4) with delta image cells
     (0 0 0)
     (1 0 0)
  - Node #11 P (T:4) with delta image cells
     (0 0 -1)
Node #5 Fe (O:6), connected to :
  - Node #0 Li (O:6) with delta image cells
     (0 0 -1)
  - Node #1 Li (O:6) with delta image cells
     (-1 0 0)
  - Node #2 Li (O:6) with delta image cells
     (-1 0 0)
     (0 0 0)
  - Node #3 Li (O:6) with delta image cells
     (-1 0 0)
     (0 0 0)
  - Node #4 Fe (O:6) with delta image cells
     (-1 0 0)
     (-1 1 0)
     (0 0 0)
     (0 1 0)
  - Node #8 P (T:4) with delta image cells
     (-1 0 0)
     (0 0 0)
  - Node #9 P (T:4) with delta image cells
     (0 0 0)
     (0 1 0)
  - Node #10 P (T:4) with delta image cells
     (-1 0 0)
Node #6 Fe (O:6), connected to :
  - Node #0 Li (O:6) with delta image cells
     (1 -1 0)
  - Node #1 Li (O:6) with delta image cells
     (0 0 1)
  - Node #2 Li (O:6) with delta image cells
     (0 -1 0)
     (1 -1 0)
  - Node #3 Li (O:6) with delta image cells
     (0 0 0)
     (1 0 0)
  - Node #7 Fe (O:6) with delta image cells
     (0 -1 0)
     (0 0 0)
     (1 -1 0)
     (1 0 0)
  - Node #9 P (T:4) with delta image cells
     (1 0 0)
  - Node #10 P (T:4) with delta image cells
     (0 -1 0)
     (0 0 0)
  - Node #11 P (T:4) with delta image cells
     (0 0 0)
     (1 0 0)
Node #7 Fe (O:6), connected to :
  - Node #0 Li (O:6) with delta image cells
     (0 0 0)
     (1 0 0)
  - Node #1 Li (O:6) with delta image cells
     (-1 0 1)
     (0 0 1)
  - Node #2 Li (O:6) with delta image cells
     (0 0 0)
  - Node #3 Li (O:6) with delta image cells
     (0 0 0)
  - Node #6 Fe (O:6) with delta image cells
     (-1 0 0)
     (-1 1 0)
     (0 0 0)
     (0 1 0)
  - Node #8 P (T:4) with delta image cells
     (0 0 1)
  - Node #10 P (T:4) with delta image cells
     (-1 0 0)
     (0 0 0)
  - Node #11 P (T:4) with delta image cells
     (0 0 0)
     (0 1 0)
Node #8 P (T:4), connected to :
  - Node #0 Li (O:6) with delta image cells
     (0 0 -1)
     (1 0 -1)
  - Node #1 Li (O:6) with delta image cells
     (-1 0 0)
     (0 0 0)
  - Node #4 Fe (O:6) with delta image cells
     (0 0 0)
     (0 1 0)
  - Node #5 Fe (O:6) with delta image cells
     (0 0 0)
     (1 0 0)
  - Node #7 Fe (O:6) with delta image cells
     (0 0 -1)
Node #9 P (T:4), connected to :
  - Node #2 Li (O:6) with delta image cells
     (-1 -1 0)
     (0 -1 0)
  - Node #3 Li (O:6) with delta image cells
     (-1 0 0)
     (0 0 0)
  - Node #4 Fe (O:6) with delta image cells
     (-1 0 0)
     (0 0 0)
  - Node #5 Fe (O:6) with delta image cells
     (0 -1 0)
     (0 0 0)
  - Node #6 Fe (O:6) with delta image cells
     (-1 0 0)
Node #10 P (T:4), connected to :
  - Node #2 Li (O:6) with delta image cells
     (0 0 0)
     (1 0 0)
  - Node #3 Li (O:6) with delta image cells
     (0 0 0)
     (1 0 0)
  - Node #5 Fe (O:6) with delta image cells
     (1 0 0)
  - Node #6 Fe (O:6) with delta image cells
     (0 0 0)
     (0 1 0)
  - Node #7 Fe (O:6) with delta image cells
     (0 0 0)
     (1 0 0)
Node #11 P (T:4), connected to :
  - Node #0 Li (O:6) with delta image cells
     (0 -1 0)
     (1 -1 0)
  - Node #1 Li (O:6) with delta image cells
     (-1 0 1)
     (0 0 1)
  - Node #4 Fe (O:6) with delta image cells
     (0 0 1)
  - Node #6 Fe (O:6) with delta image cells
     (-1 0 0)
     (0 0 0)
  - Node #7 Fe (O:6) with delta image cells
     (0 -1 0)
     (0 0 0)""")
        # Get the connectivity for T:4 and O:6 separately and check results
        # Only tetrahedral
        sc.setup_environment_subgraph(environments_symbols=["T:4"])
        assert list(sc.environment_subgraphs.keys()) == ["O:6-T:4", "T:4"]
        ccs = sc.get_connected_components()
        assert len(ccs) == 4
        for cc in ccs:
            assert cc.periodicity == "0D"
        # Only octahedral
        sc.setup_environment_subgraph(environments_symbols=["O:6"])
        assert list(
            sc.environment_subgraphs.keys()) == ["O:6-T:4", "T:4", "O:6"]
        ccs = sc.get_connected_components()
        assert len(ccs) == 1
        cc = ccs[0]
        assert cc.periodicity == "3D"
        # Only Manganese octahedral
        sc.setup_environment_subgraph(environments_symbols=["O:6"],
                                      only_atoms=["Fe"])
        assert list(sc.environment_subgraphs.keys()) == [
            "O:6-T:4",
            "T:4",
            "O:6",
            "O:6#Fe",
        ]
        ccs = sc.get_connected_components()
        assert len(ccs) == 2
        for cc in ccs:
            assert cc.periodicity == "2D"

        # Connectivity of Li4Fe3Mn1(PO4)4
        struct = Structure.from_file(
            os.path.join(self.TEST_FILES_DIR, "Li4Fe3Mn1(PO4)4.cif"))
        lgf.setup_structure(structure=struct)
        se = lgf.compute_structure_environments(
            only_atoms=["Li", "Fe", "Mn", "P"], maximum_distance_factor=1.2)
        lse = LightStructureEnvironments.from_structure_environments(
            strategy=strat, structure_environments=se)
        # Make sure the initial structure and environments are correct
        for isite in range(0, 4):
            assert lse.structure[isite].specie.symbol == "Li"
            assert lse.coordination_environments[isite][0][
                "ce_symbol"] == "O:6"
        for isite in range(4, 5):
            assert lse.structure[isite].specie.symbol == "Mn"
            assert lse.coordination_environments[isite][0][
                "ce_symbol"] == "O:6"
        for isite in range(5, 8):
            assert lse.structure[isite].specie.symbol == "Fe"
            assert lse.coordination_environments[isite][0][
                "ce_symbol"] == "O:6"
        for isite in range(8, 12):
            assert lse.structure[isite].specie.symbol == "P"
            assert lse.coordination_environments[isite][0][
                "ce_symbol"] == "T:4"
        # Get the connectivity including all environments and check results
        sc = cf.get_structure_connectivity(lse)
        assert len(sc.environment_subgraphs
                   ) == 0  # Connected component not computed by default
        ccs = sc.get_connected_components(
        )  # by default, will use all the environments (O:6 and T:4 here)
        # Now connected components for the defaults are there :
        assert list(sc.environment_subgraphs.keys()) == ["O:6-T:4"]
        assert len(sc.environment_subgraphs) == 1
        assert len(ccs) == 1
        cc = ccs[0]
        assert cc.periodicity == "3D"
        # Get the connectivity for Li octahedral only
        ccs = sc.get_connected_components(environments_symbols=["O:6"],
                                          only_atoms=["Li"])
        assert list(sc.environment_subgraphs.keys()) == ["O:6-T:4", "O:6#Li"]
        assert len(ccs) == 2
        for cc in ccs:
            assert cc.periodicity == "1D"
            assert len(cc) == 2
        # Sort connected components as they might
        # come in a different order depending on
        # the algorithm used to get them.
        sorted_ccs = sorted(ccs, key=lambda x: sorted(x.graph.nodes())[0])
        assert (sorted_ccs[0].description(
            full=True) == """Connected component with environment nodes :
Node #0 Li (O:6), connected to :
  - Node #1 Li (O:6) with delta image cells
     (1 -1 1)
     (1 0 1)
Node #1 Li (O:6), connected to :
  - Node #0 Li (O:6) with delta image cells
     (-1 0 -1)
     (-1 1 -1)""")
        assert (sorted_ccs[1].description(
            full=True) == """Connected component with environment nodes :
Node #2 Li (O:6), connected to :
  - Node #3 Li (O:6) with delta image cells
     (0 -1 0)
     (0 0 0)
Node #3 Li (O:6), connected to :
  - Node #2 Li (O:6) with delta image cells
     (0 0 0)
     (0 1 0)""")
        # Get the connectivity for Mn octahedral only
        ccs = sc.get_connected_components(environments_symbols=["O:6"],
                                          only_atoms=["Mn"])
        assert list(sc.environment_subgraphs.keys()) == [
            "O:6-T:4", "O:6#Li", "O:6#Mn"
        ]
        assert len(ccs) == 1
        assert ccs[0].periodicity == "0D"
        # Get the connectivity for Fe octahedral only
        ccs = sc.get_connected_components(environments_symbols=["O:6"],
                                          only_atoms=["Fe"])
        assert list(sc.environment_subgraphs.keys()) == [
            "O:6-T:4",
            "O:6#Li",
            "O:6#Mn",
            "O:6#Fe",
        ]
        assert len(ccs) == 2
        ccs_periodicities = set(cc.periodicity for cc in ccs)
        assert ccs_periodicities == {"0D", "2D"}
Esempio n. 24
0
    def test_light_structure_environments(self):
        with ScratchDir("."):
            f = open("{}/{}".format(se_files_dir, 'se_mp-7000.json'), 'r')
            dd = json.load(f)
            f.close()

            se = StructureEnvironments.from_dict(dd)

            strategy = SimplestChemenvStrategy()
            lse = LightStructureEnvironments.from_structure_environments(
                structure_environments=se,
                strategy=strategy,
                valences='undefined')
            isite = 6
            nb_set = lse.neighbors_sets[isite][0]
            neighb_coords = [
                np.array([0.2443798, 1.80409653, -1.13218359]),
                np.array([1.44020353, 1.11368738, 1.13218359]),
                np.array([2.75513098, 2.54465207, -0.70467298]),
                np.array([0.82616785, 3.65833945, 0.70467298])
            ]
            neighb_indices = [0, 3, 5, 1]
            neighb_images = [[0, 0, -1], [0, 0, 0], [0, 0, -1], [0, 0, 0]]

            np.testing.assert_array_almost_equal(neighb_coords,
                                                 nb_set.neighb_coords)
            np.testing.assert_array_almost_equal(
                neighb_coords, [s.coords for s in nb_set.neighb_sites])
            nb_sai = nb_set.neighb_sites_and_indices
            np.testing.assert_array_almost_equal(
                neighb_coords, [sai['site'].coords for sai in nb_sai])
            np.testing.assert_array_almost_equal(
                neighb_indices, [sai['index'] for sai in nb_sai])
            nb_iai = nb_set.neighb_indices_and_images
            np.testing.assert_array_almost_equal(
                neighb_indices, [iai['index'] for iai in nb_iai])
            np.testing.assert_array_equal(
                neighb_images, [iai['image_cell'] for iai in nb_iai])

            self.assertEqual(nb_set.__len__(), 4)
            self.assertEqual(nb_set.__hash__(), 4)

            self.assertFalse(nb_set.__ne__(nb_set))

            self.assertEqual(
                nb_set.__str__(), 'Neighbors Set for site #6 :\n'
                ' - Coordination number : 4\n'
                ' - Neighbors sites indices : 0, 1, 2, 3\n')

            stats = lse.get_statistics()

            neighbors = lse.strategy.get_site_neighbors(
                site=lse.structure[isite])
            self.assertArrayAlmostEqual(
                neighbors[0].coords,
                np.array([0.2443798, 1.80409653, -1.13218359]))
            self.assertArrayAlmostEqual(
                neighbors[1].coords,
                np.array([1.44020353, 1.11368738, 1.13218359]))
            self.assertArrayAlmostEqual(
                neighbors[2].coords,
                np.array([2.75513098, 2.54465207, -0.70467298]))
            self.assertArrayAlmostEqual(
                neighbors[3].coords,
                np.array([0.82616785, 3.65833945, 0.70467298]))

            equiv_site_index_and_transform = lse.strategy.equivalent_site_index_and_transform(
                neighbors[0])
            self.assertEqual(equiv_site_index_and_transform[0], 0)
            self.assertArrayAlmostEqual(equiv_site_index_and_transform[1],
                                        [0.0, 0.0, 0.0])
            self.assertArrayAlmostEqual(equiv_site_index_and_transform[2],
                                        [0.0, 0.0, -1.0])

            equiv_site_index_and_transform = lse.strategy.equivalent_site_index_and_transform(
                neighbors[1])
            self.assertEqual(equiv_site_index_and_transform[0], 3)
            self.assertArrayAlmostEqual(equiv_site_index_and_transform[1],
                                        [0.0, 0.0, 0.0])
            self.assertArrayAlmostEqual(equiv_site_index_and_transform[2],
                                        [0.0, 0.0, 0.0])

            self.assertEqual(stats['atom_coordination_environments_present'],
                             {'Si': {
                                 'T:4': 3.0
                             }})
            self.assertEqual(stats['coordination_environments_atom_present'],
                             {'T:4': {
                                 'Si': 3.0
                             }})
            self.assertEqual(
                stats['fraction_atom_coordination_environments_present'],
                {'Si': {
                    'T:4': 1.0
                }})

            site_info_ce = lse.get_site_info_for_specie_ce(specie=Species(
                'Si', 4),
                                                           ce_symbol='T:4')
            np.testing.assert_array_almost_equal(site_info_ce['fractions'],
                                                 [1.0, 1.0, 1.0])
            np.testing.assert_array_almost_equal(site_info_ce['csms'], [
                0.009887784240541068, 0.009887786546730826,
                0.009887787384385317
            ])
            self.assertEqual(site_info_ce['isites'], [6, 7, 8])

            site_info_allces = lse.get_site_info_for_specie_allces(
                specie=Species('Si', 4))

            self.assertEqual(site_info_allces['T:4'], site_info_ce)

            self.assertFalse(lse.contains_only_one_anion('I-'))
            self.assertFalse(lse.contains_only_one_anion_atom('I'))
            self.assertTrue(
                lse.site_contains_environment(isite=isite, ce_symbol='T:4'))
            self.assertFalse(
                lse.site_contains_environment(isite=isite, ce_symbol='S:4'))
            self.assertFalse(
                lse.structure_contains_atom_environment(atom_symbol='Si',
                                                        ce_symbol='S:4'))
            self.assertTrue(
                lse.structure_contains_atom_environment(atom_symbol='Si',
                                                        ce_symbol='T:4'))
            self.assertFalse(
                lse.structure_contains_atom_environment(atom_symbol='O',
                                                        ce_symbol='T:4'))
            self.assertTrue(lse.uniquely_determines_coordination_environments)
            self.assertFalse(lse.__ne__(lse))

            envs = lse.strategy.get_site_coordination_environments(
                lse.structure[6])
            self.assertEqual(len(envs), 1)
            self.assertEqual(envs[0][0], 'T:4')

            multi_strategy = MultiWeightsChemenvStrategy.stats_article_weights_parameters(
            )

            lse_multi = LightStructureEnvironments.from_structure_environments(
                strategy=multi_strategy,
                structure_environments=se,
                valences='undefined')
            self.assertAlmostEqual(
                lse_multi.coordination_environments[isite][0]['csm'],
                0.009887784240541068)
            self.assertAlmostEqual(
                lse_multi.coordination_environments[isite][0]['ce_fraction'],
                1.0)
            self.assertEqual(
                lse_multi.coordination_environments[isite][0]['ce_symbol'],
                'T:4')
 def test_coordination_sequences(self):
     BaTiO3_se_fpath = os.path.join(
         self.TEST_FILES_DIR,
         "chemenv",
         "structure_environments_files",
         "se_mp-5020.json",
     )
     with open(BaTiO3_se_fpath, "r") as f:
         dd = json.load(f)
     se = StructureEnvironments.from_dict(dd)
     lse = LightStructureEnvironments.from_structure_environments(
         strategy=SimplestChemenvStrategy(), structure_environments=se)
     cf = ConnectivityFinder()
     sc = cf.get_structure_connectivity(light_structure_environments=lse)
     ccs_oct = sc.get_connected_components(environments_symbols=["O:6"])
     ccs_all = sc.get_connected_components(
         environments_symbols=["O:6", "C:12"])
     assert len(ccs_oct) == 1
     assert len(ccs_all) == 1
     cc_oct = ccs_oct[0]
     cc_all = ccs_all[0]
     cc_oct_node = list(cc_oct.graph.nodes())[0]
     cseq = cc_oct.coordination_sequence(source_node=cc_oct_node,
                                         path_size=6)
     assert cseq == {1: 6, 2: 18, 3: 38, 4: 66, 5: 102, 6: 146}
     cc_all_oct_node = next(n for n in cc_all.graph.nodes()
                            if n.coordination_environment == "O:6")
     cc_all_cuboct_node = next(n for n in cc_all.graph.nodes()
                               if n.coordination_environment == "C:12")
     cseq = cc_all.coordination_sequence(source_node=cc_all_oct_node,
                                         path_size=6)
     assert cseq == {1: 14, 2: 74, 3: 218, 4: 442, 5: 746, 6: 1130}
     cseq = cc_all.coordination_sequence(source_node=cc_all_cuboct_node,
                                         path_size=6)
     assert cseq == {1: 26, 2: 122, 3: 298, 4: 554, 5: 890, 6: 1306}
     cseq = cc_all.coordination_sequence(source_node=cc_all_cuboct_node,
                                         path_size=6,
                                         include_source=True)
     assert cseq == {0: 1, 1: 26, 2: 122, 3: 298, 4: 554, 5: 890, 6: 1306}
     cseq = cc_all.coordination_sequence(source_node=cc_all_oct_node,
                                         path_size=4,
                                         coordination="env:number")
     assert cseq == {
         1: {
             "O:6": 6,
             "C:12": 8
         },
         2: {
             "O:6": 26,
             "C:12": 48
         },
         3: {
             "O:6": 90,
             "C:12": 128
         },
         4: {
             "O:6": 194,
             "C:12": 248
         },
     }
     cseq = cc_all.coordination_sequence(source_node=cc_all_cuboct_node,
                                         path_size=4,
                                         coordination="env:number")
     assert cseq == {
         1: {
             "O:6": 8,
             "C:12": 18
         },
         2: {
             "O:6": 48,
             "C:12": 74
         },
         3: {
             "O:6": 128,
             "C:12": 170
         },
         4: {
             "O:6": 248,
             "C:12": 306
         },
     }
     cseq = cc_all.coordination_sequence(
         source_node=cc_all_cuboct_node,
         path_size=4,
         coordination="env:number",
         include_source=True,
     )
     assert cseq == {
         0: {
             "C:12": 1
         },
         1: {
             "O:6": 8,
             "C:12": 18
         },
         2: {
             "O:6": 48,
             "C:12": 74
         },
         3: {
             "O:6": 128,
             "C:12": 170
         },
         4: {
             "O:6": 248,
             "C:12": 306
         },
     }
Esempio n. 26
0
        def get_chemenv_analysis(struct, distance_cutoff, angle_cutoff):

            if not struct:
                raise PreventUpdate

            struct = self.from_data(struct)
            kwargs = self.reconstruct_kwargs_from_state(
                callback_context.inputs)
            distance_cutoff = kwargs["distance_cutoff"]
            angle_cutoff = kwargs["angle_cutoff"]

            # TODO: remove these brittle guard statements, figure out more robust way to handle multiple input types
            if isinstance(struct, StructureGraph):
                struct = struct.structure

            def get_valences(struct):
                valences = [
                    getattr(site.specie, "oxi_state", None) for site in struct
                ]
                valences = [v for v in valences if v is not None]
                if len(valences) == len(struct):
                    return valences
                else:
                    return "undefined"

            # decide which indices to present to user
            sga = SpacegroupAnalyzer(struct)
            symm_struct = sga.get_symmetrized_structure()
            inequivalent_indices = [
                indices[0] for indices in symm_struct.equivalent_indices
            ]
            wyckoffs = symm_struct.wyckoff_symbols

            lgf = LocalGeometryFinder()
            lgf.setup_structure(structure=struct)

            se = lgf.compute_structure_environments(
                maximum_distance_factor=distance_cutoff + 0.01,
                only_indices=inequivalent_indices,
                valences=get_valences(struct),
            )
            strategy = SimplestChemenvStrategy(distance_cutoff=distance_cutoff,
                                               angle_cutoff=angle_cutoff)
            lse = LightStructureEnvironments.from_structure_environments(
                strategy=strategy, structure_environments=se)
            all_ce = AllCoordinationGeometries()

            envs = []
            unknown_sites = []

            for index, wyckoff in zip(inequivalent_indices, wyckoffs):

                datalist = {
                    "Site": unicodeify_species(struct[index].species_string),
                    "Wyckoff Label": wyckoff,
                }

                if not lse.neighbors_sets[index]:
                    unknown_sites.append(
                        f"{struct[index].species_string} ({wyckoff})")
                    continue

                # represent the local environment as a molecule
                mol = Molecule.from_sites(
                    [struct[index]] +
                    lse.neighbors_sets[index][0].neighb_sites)
                mol = mol.get_centered_molecule()
                mg = MoleculeGraph.with_empty_graph(molecule=mol)
                for i in range(1, len(mol)):
                    mg.add_edge(0, i)

                view = html.Div(
                    [
                        StructureMoleculeComponent(
                            struct_or_mol=mg,
                            disable_callbacks=True,
                            id=
                            f"{struct.composition.reduced_formula}_site_{index}",
                            scene_settings={
                                "enableZoom": False,
                                "defaultZoom": 0.6
                            },
                        )._sub_layouts["struct"]
                    ],
                    style={
                        "width": "300px",
                        "height": "300px"
                    },
                )

                env = lse.coordination_environments[index]
                co = all_ce.get_geometry_from_mp_symbol(env[0]["ce_symbol"])
                name = co.name
                if co.alternative_names:
                    name += f" (also known as {', '.join(co.alternative_names)})"

                datalist.update({
                    "Environment":
                    name,
                    "IUPAC Symbol":
                    co.IUPAC_symbol_str,
                    get_tooltip(
                        "CSM",
                        "The continuous symmetry measure (CSM) describes the similarity to an "
                        "ideal coordination environment. It can be understood as a 'distance' to "
                        "a shape and ranges from 0 to 100 in which 0 corresponds to a "
                        "coordination environment that is exactly identical to the ideal one. A "
                        "CSM larger than 5.0 already indicates a relatively strong distortion of "
                        "the investigated coordination environment.",
                    ):
                    f"{env[0]['csm']:.2f}",
                    "Interactive View":
                    view,
                })

                envs.append(get_data_list(datalist))

            # TODO: switch to tiles?
            envs_grouped = [envs[i:i + 2] for i in range(0, len(envs), 2)]
            analysis_contents = []
            for env_group in envs_grouped:
                analysis_contents.append(
                    Columns([Column(e, size=6) for e in env_group]))

            if unknown_sites:
                unknown_sites = html.Strong(
                    f"The following sites were not identified: {', '.join(unknown_sites)}. "
                    f"Please try changing the distance or angle cut-offs to identify these sites, "
                    f"or try an alternative algorithm such as LocalEnv.")
            else:
                unknown_sites = html.Span()

            return html.Div(
                [html.Div(analysis_contents),
                 html.Br(), unknown_sites])
Esempio n. 27
0
    def run(self, sn):
        """
        Args:
            sn (SiteNetwork)
        Returns:
            ``sn``, with type information.
        """
        # -- Determine local environments
        # Get an ASE structure with a single mobile site that we'll move around
        if sn.n_sites == 0:
            logger.warning("Site network had no sites.")
            return sn
        site_struct, site_species = sn[0:1].get_structure_with_sites()
        pymat_struct = AseAtomsAdaptor.get_structure(site_struct)
        lgf = cgf.LocalGeometryFinder()
        site_atom_index = len(site_struct) - 1

        coord_envs = []
        vertices = []

        valences = 'undefined'
        if self._guess_ionic_bonds:
            sim_struct = AseAtomsAdaptor.get_structure(sn.structure)
            valences = np.zeros(shape = len(site_struct), dtype = np.int)
            bv = BVAnalyzer()
            try:
                struct_valences = np.asarray(bv.get_valences(sim_struct))
            except ValueError as ve:
                logger.warning("Failed to compute bond valences: %s" % ve)
            else:
                valences = np.zeros(shape = len(site_struct), dtype = np.int)
                valences[:site_atom_index] = struct_valences[sn.static_mask]
                mob_val = struct_valences[sn.mobile_mask]
                if np.any(mob_val != mob_val[0]):
                    logger.warning("Mobile atom estimated valences (%s) not uniform; arbitrarily taking first." % mob_val)
                valences[site_atom_index] = mob_val[0]
            finally:
                valences = list(valences)

        logger.info("Running site coordination environment analysis...")
        # Do this once.
        # __init__ here defaults to disabling structure refinement, so all this
        # method is doing is making a copy of the structure and setting some
        # variables to None.
        lgf.setup_structure(structure = pymat_struct)

        for site in tqdm(range(sn.n_sites), desc = 'Site'):
            # Update the position of the site
            lgf.structure[site_atom_index].coords = sn.centers[site]
            # Compute structure environments for the site
            struct_envs = lgf.compute_structure_environments(
                only_indices = [site_atom_index],
                valences = valences,
                additional_conditions = [AdditionalConditions.ONLY_ANION_CATION_BONDS],
                **self._kwargs
            )
            struct_envs = LightStructureEnvironments.from_structure_environments(
                strategy = cgf.LocalGeometryFinder.DEFAULT_STRATEGY,
                structure_environments = struct_envs
            )
            # Store the results
            # We take the first environment for each site since it's the most likely
            this_site_envs = struct_envs.coordination_environments[site_atom_index]
            if len(this_site_envs) > 0:
                coord_envs.append(this_site_envs[0])
                vertices.append(
                    [n['index'] for n in struct_envs.neighbors_sets[site_atom_index][0].neighb_indices_and_images]
                )
            else:
                coord_envs.append({'ce_symbol' : 'BAD:0', 'ce_fraction' : 0.})
                vertices.append([])

        del lgf
        del struct_envs

        # -- Postprocess
        # TODO: allow user to ask for full fractional breakdown
        str_coord_environments = [env['ce_symbol'] for env in coord_envs]
        # The closer to 1 this is, the better
        site_type_confidences = np.array([env['ce_fraction'] for env in coord_envs])
        coordination_numbers = np.array([int(env['ce_symbol'].split(':')[1]) for env in coord_envs])
        assert np.all(coordination_numbers == [len(v) for v in vertices])

        typearr = str_coord_environments if self._full_chemenv_site_types else coordination_numbers
        unique_envs = list(set(typearr))
        site_types = np.array([unique_envs.index(t) for t in typearr])

        n_types = len(unique_envs)
        logger.info(("Type         " + "{:<8}" * n_types).format(*unique_envs))
        logger.info(("# of sites   " + "{:<8}" * n_types).format(*np.bincount(site_types)))

        sn.site_types = site_types
        sn.vertices = vertices
        sn.add_site_attribute("coordination_environments", str_coord_environments)
        sn.add_site_attribute("site_type_confidences", site_type_confidences)
        sn.add_site_attribute("coordination_numbers", coordination_numbers)

        return sn