def setUp(self):
     self.lgf = LocalGeometryFinder()
     self.lgf.setup_parameters(
         centering_type="standard",
         structure_refinement=self.lgf.STRUCTURE_REFINEMENT_NONE,
     )
     self.lgf2 = LocalGeometryFinder(print_citation=True)
Ejemplo n.º 2
0
 def setUp(self):
     self.lgf = LocalGeometryFinder()
     self.lgf.setup_parameters(centering_type='standard')
     self.strategies = [
         SimplestChemenvStrategy(),
         SimpleAbundanceChemenvStrategy()
     ]
Ejemplo n.º 3
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)
Ejemplo n.º 4
0
    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 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}
Ejemplo n.º 6
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
Ejemplo n.º 7
0
 def from_preset(preset):
     """
     Use a standard collection of CE types and
     choose your ChemEnv neighbor-finding strategy.
     Args:
         preset (str): preset types ("simple" or
                       "multi_weights").
     Returns:
         ChemEnvSiteFingerprint object from a preset.
     """
     cetypes = [
         'S:1', 'L:2', 'A:2', 'TL:3', 'TY:3', 'TS:3', 'T:4', 'S:4', 'SY:4',
         'SS:4', 'PP:5', 'S:5', 'T:5', 'O:6', 'T:6', 'PP:6', 'PB:7', 'ST:7',
         'ET:7', 'FO:7', 'C:8', 'SA:8', 'SBT:8', 'TBT:8', 'DD:8', 'DDPN:8',
         'HB:8', 'BO_1:8', 'BO_2:8', 'BO_3:8', 'TC:9', 'TT_1:9', 'TT_2:9',
         'TT_3:9', 'HD:9', 'TI:9', 'SMA:9', 'SS:9', 'TO_1:9', 'TO_2:9',
         'TO_3:9', 'PP:10', 'PA:10', 'SBSA:10', 'MI:10', 'S:10', 'H:10',
         'BS_1:10', 'BS_2:10', 'TBSA:10', 'PCPA:11', 'H:11', 'SH:11',
         'CO:11', 'DI:11', 'I:12', 'PBP:12', 'TT:12', 'C:12', 'AC:12',
         'SC:12', 'S:12', 'HP:12', 'HA:12', 'SH:13', 'DD:20'
     ]
     lgf = LocalGeometryFinder()
     lgf.setup_parameters(
         centering_type='centroid',
         include_central_site_in_centroid=True,
         structure_refinement=lgf.STRUCTURE_REFINEMENT_NONE)
     if preset == "simple":
         return ChemEnvSiteFingerprint(
             cetypes,
             SimplestChemenvStrategy(distance_cutoff=1.4, angle_cutoff=0.3),
             lgf)
     elif preset == "multi_weights":
         return ChemEnvSiteFingerprint(
             cetypes,
             MultiWeightsChemenvStrategy.stats_article_weights_parameters(),
             lgf)
     else:
         raise RuntimeError('unknown neighbor-finding strategy preset.')
Ejemplo n.º 8
0
def compute_environments(chemenv_configuration):
    string_sources = {
        'cif': {
            'string': 'a Cif file',
            'regexp': '.*\.cif$'
        },
        'mp': {
            'string': 'the Materials Project database',
            'regexp': 'mp-[0-9]+$'
        }
    }
    questions = {'c': 'cif'}
    if chemenv_configuration.has_materials_project_access:
        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(chemenv_configuration.materials_project_api_key)
            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':
                test = input(
                    'Enter index of site(s) for which you want to see the grid of parameters : '
                )
                indices = list(map(int, test.split()))
                print(indices)
                for isite in indices:
                    se.plot_environments(isite,
                                         additional_condition=se.AC.ONLY_ACB)
            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 = []
                    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))
                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('')
Ejemplo n.º 9
0
    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"}
Ejemplo n.º 10
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'
                    )
                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.º 11
0
def extract_average_spectra(species,
                            transition,
                            path=None,
                            save_as='avg_data.pkl',
                            verbose=1):
    """Documentation is identical to extract_sites_o6_s5_t4 except that this
    function extracts the average spectra for all site-types for every
    crystal structure.
    """

    logger = logging.getLogger()
    logger.setLevel(logging.CRITICAL)

    # set the path to where the extracted data is located
    if path is None:
        path = t4iss_defaults['t4iss_data']

    if verbose == 1:
        print("path is ", path)

    cell_counter = 0
    total_counter = 0
    key_site_counter = 0
    directory_counter = 0

    # initialize an empty dictionary which can be thought of as one hot
    # encoding the key will be of form O:6, T:4, etc. and the value will be
    # the index of the basis vector corresponding to that site - the labels
    # will be generated after this block is run
    key_site = {}

    # empty lists for all the cn data
    all_site_data = []
    all_cell_data = []

    # these files will end up raising errors during execution of the
    # following loops - avoid them
    forbidden = [".DS_Store", "CONTCAR", "*.pkl"]

    # assert that only strings with the correct species and transition are
    # added to the training dataset
    correct_string = str(species) + "-" + str(transition)

    # for cell (e.g. mp-390) in the desired data directory
    os_list_directory = os.listdir(path)
    N_os_list_directory = len(os_list_directory)

    for ii, cell in enumerate(os_list_directory[:5]):

        if verbose == 1:
            if ii % 20 == 0.0:
                print("%i/%i" % (ii, N_os_list_directory))

        # reset the cell counter
        cell_counter = 0
        pass_cell = False
        current_cell_data = []

        # define a path if cell isn't = forbidden
        if cell not in forbidden:
            cell_path = os.path.join(path, str(cell))

            try:
                xanes_data = read_xanes(cell_path, absorption_specie=species)
            except (ValueError, FileNotFoundError):
                # print("No %s in %s. Passing." % (species, cell_path))
                pass_cell = True

            # get the structure
            try:
                structure = mg.Structure.from_file(cell_path + "/CONTCAR")
            except (FileNotFoundError, NotADirectoryError):
                # skip if CONTCAR does not exist in the directory
                # or if it isn't a directory at all, there are a few of those
                pass_cell = True

            # skip if directory is empty
            if not pass_cell:  # call this first to avoid NotADirectoryError
                if os.listdir(cell_path) == []:
                    pass_cell = True

            if not pass_cell:
                # define a path to a given spectra/pickle file
                for sample in os.listdir(cell_path):
                    if sample not in forbidden:

                        pass_sample = False

                        # cell sample path
                        csp = os.path.join(cell_path, str(sample))

                        # assert that we're reading the correct species
                        # and correct transition
                        if correct_string in csp:
                            try:
                                with open(csp + "/xanes.pkl",
                                          'rb') as pickle_file:
                                    content = pickle.load(pickle_file)

                                # ensure we end up with content to analyze,
                                # if not pass it
                                try:
                                    save_stdout = sys.stdout
                                    sys.stdout = open('.trash', 'w')
                                    lgf = LocalGeometryFinder()
                                    cesym = get_cesym(lgf, structure,
                                                      content.structure[1])
                                    sys.stdout = save_stdout
                                except IndexError:
                                    pass_sample = True

                                # print(all_cn_data[key[cesym[0]]])
                                # raise ValueError

                                if pass_sample:
                                    pass
                                else:
                                    # add in the average data if this is the
                                    # first time the
                                    # directory / cell has been looked at
                                    if cell_counter == 0:
                                        all_cell_data.\
                                            append([cell, directory_counter,
                                                    deepcopy(xanes_data[0])])

                                    # if the symmetry label does not exist,
                                    # append it to the dictionary with its
                                    # type and index, and initialize a new
                                    # list in all_cn_data with key_counter as
                                    # its index
                                    if cesym[0] not in key_site.keys():
                                        key_site[cesym[0]] = key_site_counter
                                        all_site_data.append([])
                                        key_site_counter += 1

                                    x = [
                                        cell, directory_counter, cell_counter,
                                        deepcopy(content), cesym,
                                        content.multiplicity
                                    ]
                                    all_site_data[key_site[cesym[0]]].append(x)
                                    current_cell_data.append(x)
                                    cell_counter += 1
                                    total_counter += 1

                            except FileNotFoundError:
                                pass

        if pass_cell or (pass_sample and cell_counter == 0):
            pass
        else:
            # sanity check - can cross-reference with the atom id's using
            # VESTA
            # finder = SpacegroupAnalyzer(structure)
            # struct = finder.get_symmetrized_structure()
            # [sites, indices]  = struct.equivalent_sites,
            # struct.equivalent_indices
            # print(directory_counter, indices)

            # for every cell / directory (e.g. mvc-16746), generate an
            # individual dictionary which labels the proportion of each
            # coordination number present in the crystal structure
            temp_dictionary = {}

            # running counter of all the multiplicity numbers
            total_multiplicity = 0

            for xx in current_cell_data:

                # current multiplicity of xx
                cm = xx[3].multiplicity

                # if the current ce symbol does not exist in the
                # temp_dictionary, create it and initialize its counter equal
                # to the multiplicity of that entry
                if xx[4][0] not in temp_dictionary.keys():
                    temp_dictionary[xx[4][0]] = cm

                # else, it must have been previously initialized, and so we
                # should add the multiplicity to it
                else:
                    temp_dictionary[xx[4][0]] += cm

                # append the total multiplicity for normalizing later
                total_multiplicity += cm

            # next, modify each value in the dictionary: normalize by total
            # multiplicity
            for xx in temp_dictionary:
                temp_dictionary[xx] /= float(total_multiplicity)

            all_cell_data[directory_counter].append(temp_dictionary)
            directory_counter += 1

    path_save = os.path.join(path, save_as)

    with open(path_save, 'wb') as f:
        pickle.dump(all_cell_data, f)
Ejemplo n.º 12
0
 def setUpClass(cls):
     cls.lgf = LocalGeometryFinder()
     cls.lgf.setup_parameters(centering_type="standard")
     os.makedirs("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()
Ejemplo n.º 14
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])
Ejemplo n.º 15
0
def extract_sites_o6_s5_t4(species,
                           transition,
                           path=None,
                           save_as='site_data.pkl',
                           verbose=0):
    """From a directory containing structure/spectra data of various crystal
    structures from the Materials Project, extract and store all site data
    corresponding to the O:6, S:5 and T:4 chemical environments.

    ~ Note: this script takes a long time to run, be patient! ~

    :Input:
    - species (string) the atom of focus for the XANES spectrum. For example:
      'Ti'.
    - path (string) override the default path if desired. Should be the
      absolute path.
    - transition (string) for example: 'K'.
    - save_as (string) the output pkl file name.
    - verbose (int) qqual to 0 or 1. 0 for silent running, 1 for a progress
      indicator. 1 by default.
    """

    logger = logging.getLogger()
    logger.setLevel(logging.CRITICAL)

    # set the path to where the extracted data is located
    if path is None:
        path = t4iss_defaults['t4iss_xanes_data']
    # e.g.
    # path = os.path.join(os.environ['HOME'], "datasets", "FEFF_data_June7")

    cell_counter = 0
    total_counter = 0

    t4_data = []
    s5_data = []
    o6_data = []

    forbidden = [".DS_Store", "CONTCAR", "collection.pkl"]
    correct_string = str(species) + "-" + str(transition)

    # for cell (e.g. mp-390) in the desired data directory
    os_list_directory = os.listdir(path)
    N_os_list_directory = len(os_list_directory)

    for ii in tqdm(range(N_os_list_directory)):

        cell = os_list_directory[ii]

        if verbose == 1:
            if ii % 100 == 0:
                print("%i/%i samples analyzed" % (ii, N_os_list_directory))

        # reset the cell counter
        cell_counter = 0
        pass_cell = False

        # define a path if cell isn't = forbidden
        if cell not in forbidden:
            cell_path = os.path.join(path, str(cell))

            # get the structure
            try:
                structure = mg.Structure.from_file(cell_path + "/CONTCAR")
            except (FileNotFoundError, NotADirectoryError):
                # skip if CONTCAR does not exist in the directory
                # or if it isn't a directory at all, there are a few of those
                pass_cell = True

            # skip if directory is empty
            if not pass_cell:  # call this first to avoid NotADirectoryError
                if os.listdir(cell_path) == []:
                    pass_cell = True

            if not pass_cell:
                # define a path to a given spectra/pickle file
                for sample in os.listdir(cell_path):
                    if sample not in forbidden:
                        pass_sample = False

                        # cell sample path
                        csp = os.path.join(cell_path, str(sample))

                        # assert that we're reading the correct species
                        # and correct transition
                        if correct_string in csp:
                            try:
                                with open(csp + "/xanes.pkl", 'rb') \
                                    as pickle_file:
                                    content = pickle.load(pickle_file)

                                # ensure we end up with content to analyze
                                # if not pass it
                                try:
                                    save_stdout = sys.stdout
                                    sys.stdout = open('.trash', 'w')
                                    lgf = LocalGeometryFinder()
                                    cesym = get_cesym(lgf, structure,
                                                      content.structure[1])
                                    sys.stdout = save_stdout
                                except IndexError:
                                    pass_sample = True

                                if pass_sample:
                                    pass
                                elif cesym[0] == "T:4":
                                    t4_data.append([
                                        cell, cell_counter,
                                        deepcopy(content), cesym
                                    ])
                                    cell_counter += 1
                                    total_counter += 1
                                elif cesym[0] == "S:5":
                                    s5_data.append([
                                        cell, cell_counter,
                                        deepcopy(content), cesym
                                    ])
                                    cell_counter += 1
                                    total_counter += 1
                                elif cesym[0] == "O:6":
                                    o6_data.append([
                                        cell, cell_counter,
                                        deepcopy(content), cesym
                                    ])
                                    cell_counter += 1
                                    total_counter += 1
                            except FileNotFoundError:
                                pass

    all_data = [t4_data, s5_data, o6_data]
    path_save = os.path.join(path, save_as)

    with open(path_save, 'wb') as f:
        pickle.dump(all_data, f)
Ejemplo n.º 16
0
from pymatgen.analysis.chemenv.coordination_environments.coordination_geometries import AllCoordinationGeometries
from pymatgen.analysis.chemenv.coordination_environments.coordination_geometry_finder import LocalGeometryFinder
import logging

allcg = AllCoordinationGeometries()

lgf = LocalGeometryFinder()
logging.basicConfig(format="%(levelname)s:%(module)s:%(funcName)s:%(message)s",
                    level="DEBUG")

mp_symbol = "DD:20"
coordination = 20
myindices = [
    8, 12, 11, 0, 14, 10, 13, 6, 18, 1, 9, 17, 3, 19, 5, 7, 15, 2, 16, 4
]
cg = allcg.get_geometry_from_mp_symbol(mp_symbol=mp_symbol)
lgf.allcg = AllCoordinationGeometries(only_symbols=[mp_symbol])
lgf.setup_test_perfect_environment(
    mp_symbol,
    randomness=False,
    indices=myindices,
    random_translation="NONE",
    random_rotation="NONE",
    random_scale="NONE",
)
se = 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],
Ejemplo n.º 17
0
 def setUp(self):
     self.lgf = LocalGeometryFinder()
     self.lgf.setup_parameters(
         centering_type='standard',
         structure_refinement=self.lgf.STRUCTURE_REFINEMENT_NONE)
Ejemplo n.º 18
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
                    # 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.frac_coords + 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("")
Ejemplo n.º 19
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])
Ejemplo n.º 20
0
    def get_light_structure_environment(self, only_cation_environments=False):
        """
        will return a LobsterLightStructureEnvironments object
        if the structure only contains coordination environments smaller 13
        Args:
            only_cation_environments: only data for cations will be returned

        Returns: LobsterLightStructureEnvironments Object

        """

        lgf = LocalGeometryFinder()
        lgf.setup_structure(structure=self.structure)
        list_ce_symbols = []
        list_csm = []
        list_permut = []
        for ival, _neigh_coords in enumerate(self.list_coords):

            if (len(_neigh_coords)) > 13:
                raise ValueError("Environment cannot be determined. Number of neighbors is larger than 13.")
            lgf.setup_local_geometry(isite=ival, coords=_neigh_coords, optimization=2)
            cncgsm = lgf.get_coordination_symmetry_measures(optimization=2)

            list_ce_symbols.append(min(cncgsm.items(), key=lambda t: t[1]["csm_wcs_ctwcc"])[0])
            list_csm.append(min(cncgsm.items(), key=lambda t: t[1]["csm_wcs_ctwcc"])[1]["csm_wcs_ctwcc"])
            list_permut.append(min(cncgsm.items(), key=lambda t: t[1]["csm_wcs_ctwcc"])[1]["indices"])

        if not only_cation_environments:
            lse = LobsterLightStructureEnvironments.from_Lobster(
                list_ce_symbol=list_ce_symbols,
                list_csm=list_csm,
                list_permutation=list_permut,
                list_neighsite=self.list_neighsite,
                list_neighisite=self.list_neighisite,
                structure=self.structure,
                valences=self.valences,
            )
        else:
            new_list_ce_symbols = []
            new_list_csm = []
            new_list_permut = []
            new_list_neighsite = []
            new_list_neighisite = []

            for ival, val in enumerate(self.valences):

                if val >= 0.0:

                    new_list_ce_symbols.append(list_ce_symbols[ival])
                    new_list_csm.append(list_csm[ival])
                    new_list_permut.append(list_permut[ival])
                    new_list_neighisite.append(self.list_neighisite[ival])
                    new_list_neighsite.append(self.list_neighsite[ival])
                else:
                    new_list_ce_symbols.append(None)
                    new_list_csm.append(None)
                    new_list_permut.append([])
                    new_list_neighisite.append([])
                    new_list_neighsite.append([])

            lse = LobsterLightStructureEnvironments.from_Lobster(
                list_ce_symbol=new_list_ce_symbols,
                list_csm=new_list_csm,
                list_permutation=new_list_permut,
                list_neighsite=new_list_neighsite,
                list_neighisite=new_list_neighisite,
                structure=self.structure,
                valences=self.valences,
            )

        return lse