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)
def setUp(self): self.lgf = LocalGeometryFinder() self.lgf.setup_parameters(centering_type='standard') self.strategies = [ SimplestChemenvStrategy(), SimpleAbundanceChemenvStrategy() ]
class CoordinationGeometryFinderTest(unittest2.TestCase): def setUp(self): self.lgf = LocalGeometryFinder() self.lgf.setup_parameters(centering_type='standard') self.strategies = [SimplestChemenvStrategy(), SimpleAbundanceChemenvStrategy()] # def _strategy_test(self, strategy): # files = [] # for (dirpath, dirnames, filenames) in os.walk(json_files_dir): # files.extend(filenames) # break # # for ifile, json_file in enumerate(files): # with self.subTest(json_file=json_file): # f = open("{}/{}".format(json_files_dir, json_file), 'r') # dd = json.load(f) # f.close() # # atom_indices = dd['atom_indices'] # expected_geoms = dd['expected_geoms'] # # struct = Structure.from_dict(dd['structure']) # # struct = self.lgf.setup_structure(struct) # se = self.lgf.compute_structure_environments_detailed_voronoi(only_indices=atom_indices, # maximum_distance_factor=1.5) # # #All strategies should get the correct environment with their default parameters # strategy.set_structure_environments(se) # for ienv, isite in enumerate(atom_indices): # ce = strategy.get_site_coordination_environment(struct[isite]) # try: # coord_env = ce[0] # except TypeError: # coord_env = ce # #Check that the environment found is the expected one # self.assertEqual(coord_env, expected_geoms[ienv]) # # def test_simplest_chemenv_strategy(self): # strategy = SimplestChemenvStrategy() # self._strategy_test(strategy) # # def test_simple_abundance_chemenv_strategy(self): # strategy = SimpleAbundanceChemenvStrategy() # self._strategy_test(strategy) def test_perfect_environments(self): for coordination in range(1, 13): for mp_symbol in AllCoordinationGeometries().get_implemented_geometries(coordination=coordination, returned='mp_symbol'): with self.subTest(msg=mp_symbol, mp_symbol=mp_symbol): self.lgf.setup_test_perfect_environment(mp_symbol, randomness=False, indices='RANDOM', random_translation=True, random_rotation=True, random_scale=True) se = self.lgf.compute_structure_environments_detailed_voronoi(only_indices=[0], maximum_distance_factor=1.5) self.assertAlmostEqual(se.get_csm(0, mp_symbol)['symmetry_measure'], 0.0, msg='mp_symbol {} not recognized ...'.format(mp_symbol))
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)
class CoordinationGeometryFinderTest(unittest2.TestCase): def setUp(self): self.lgf = LocalGeometryFinder() self.lgf.setup_parameters(centering_type='standard') self.strategies = [ SimplestChemenvStrategy(), SimpleAbundanceChemenvStrategy() ]
class LightStructureEnvironmentsTest(unittest.TestCase): @classmethod def setUpClass(cls): os.makedirs('tmp_dir') def setUp(self): self.lgf = LocalGeometryFinder() self.lgf.setup_parameters(centering_type='standard') self.strategies = [SimplestChemenvStrategy(), SimpleAbundanceChemenvStrategy()] def test_read_structure_environments(self): f = open("{}/{}".format(json_files_dir, 'test_T--4_FePO4_icsd_4266.json'), 'r') dd = json.load(f) f.close() atom_indices = dd['atom_indices'] struct = Structure.from_dict(dd['structure']) self.lgf.setup_structure(struct) se = self.lgf.compute_structure_environments_detailed_voronoi(only_indices=atom_indices, maximum_distance_factor=2.25) f = open('tmp_dir/se.json', 'w') json.dump(se.as_dict(), f) f.close() f = open('tmp_dir/se.json', 'r') dd = json.load(f) f.close() se2 = StructureEnvironments.from_dict(dd) self.assertEqual(se, se2) _strategy = SimplestChemenvStrategy() light_se = LightStructureEnvironments(_strategy, se) f = open('tmp_dir/light_se.json', 'w') json.dump(light_se.as_dict(), f) f.close() f = open('tmp_dir/light_se.json', 'r') dd = json.load(f) f.close() light_se2 = LightStructureEnvironments.from_dict(dd) self.assertEqual(light_se, light_se2) @classmethod def tearDownClass(cls): #Remove the directory in which the temporary files have been created shutil.rmtree('tmp_dir')
def 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('No csm found for {}'.format(self.initial_environment_symbol)) csm_info.sort(key=lambda x: x['other_symmetry_measures'][symmetry_measure_type]) csm_initial_min_dist = csm_info[0]['other_symmetry_measures'][symmetry_measure_type] csm_info = se.get_csms(isite=0, mp_symbol=self.expected_final_environment_symbol) if len(csm_info) == 0: raise ValueError('No csm found for {}'.format(self.initial_environment_symbol)) csm_info.sort(key=lambda x: x['other_symmetry_measures'][symmetry_measure_type]) csm_final = csm_info[0]['other_symmetry_measures'][symmetry_measure_type] if not np.isclose(csm_final, 0.0, rtol=0.0, atol=1e-10): raise ValueError('Final coordination is not perfect !') # Get the StructureEnvironments for the structure with dist_factor_max struct = self.get_structure(morphing_factor=dist_factor_max) lgf.setup_structure(structure=struct) se = lgf.compute_structure_environments(only_indices=[0], valences=fake_valences, only_symbols=only_symbols) csm_info = se.get_csms(isite=0, mp_symbol=self.initial_environment_symbol) if len(csm_info) == 0: raise ValueError('No csm found for {}'.format(self.initial_environment_symbol)) csm_info.sort(key=lambda x: x['other_symmetry_measures'][symmetry_measure_type]) csm_initial_max_dist = csm_info[0]['other_symmetry_measures'][symmetry_measure_type] csm_info = se.get_csms(isite=0, mp_symbol=self.expected_final_environment_symbol) if len(csm_info) == 0: raise ValueError('No csm found for {}'.format(self.initial_environment_symbol)) csm_info.sort(key=lambda x: x['other_symmetry_measures'][symmetry_measure_type]) csm_final = csm_info[0]['other_symmetry_measures'][symmetry_measure_type] if not np.isclose(csm_final, 0.0, rtol=0.0, atol=1e-10): raise ValueError('Final coordination is not perfect !') return {'delta_csm_min': csm_initial_min_dist, 'self_weight_max_csm': csm_initial_max_dist}
def estimate_parameters(self, dist_factor_min, dist_factor_max, symmetry_measure_type="csm_wcs_ctwcc"): only_symbols = [self.initial_environment_symbol, self.expected_final_environment_symbol] # Set up the local geometry finder lgf = LocalGeometryFinder() lgf.setup_parameters(structure_refinement=lgf.STRUCTURE_REFINEMENT_NONE) # Get the StructureEnvironments fake_valences = [-1] * (self.coordination_geometry.coordination_number + 1) fake_valences[0] = 1 # Get the StructureEnvironments for the structure with dist_factor_min struct = self.get_structure(morphing_factor=dist_factor_min) lgf.setup_structure(structure=struct) se = lgf.compute_structure_environments(only_indices=[0], valences=fake_valences, only_symbols=only_symbols) csm_info = se.get_csms(isite=0, mp_symbol=self.initial_environment_symbol) if len(csm_info) == 0: raise ValueError(f"No csm found for {self.initial_environment_symbol}") csm_info.sort(key=lambda x: x["other_symmetry_measures"][symmetry_measure_type]) csm_initial_min_dist = csm_info[0]["other_symmetry_measures"][symmetry_measure_type] csm_info = se.get_csms(isite=0, mp_symbol=self.expected_final_environment_symbol) if len(csm_info) == 0: raise ValueError(f"No csm found for {self.initial_environment_symbol}") csm_info.sort(key=lambda x: x["other_symmetry_measures"][symmetry_measure_type]) csm_final = csm_info[0]["other_symmetry_measures"][symmetry_measure_type] if not np.isclose(csm_final, 0.0, rtol=0.0, atol=1e-10): raise ValueError("Final coordination is not perfect !") # Get the StructureEnvironments for the structure with dist_factor_max struct = self.get_structure(morphing_factor=dist_factor_max) lgf.setup_structure(structure=struct) se = lgf.compute_structure_environments(only_indices=[0], valences=fake_valences, only_symbols=only_symbols) csm_info = se.get_csms(isite=0, mp_symbol=self.initial_environment_symbol) if len(csm_info) == 0: raise ValueError(f"No csm found for {self.initial_environment_symbol}") csm_info.sort(key=lambda x: x["other_symmetry_measures"][symmetry_measure_type]) csm_initial_max_dist = csm_info[0]["other_symmetry_measures"][symmetry_measure_type] csm_info = se.get_csms(isite=0, mp_symbol=self.expected_final_environment_symbol) if len(csm_info) == 0: raise ValueError(f"No csm found for {self.initial_environment_symbol}") csm_info.sort(key=lambda x: x["other_symmetry_measures"][symmetry_measure_type]) csm_final = csm_info[0]["other_symmetry_measures"][symmetry_measure_type] if not np.isclose(csm_final, 0.0, rtol=0.0, atol=1e-10): raise ValueError("Final coordination is not perfect !") return {"delta_csm_min": csm_initial_min_dist, "self_weight_max_csm": csm_initial_max_dist}
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.')
def figure_fractions(self, weights_options, morphing_factors=None): if morphing_factors is None: morphing_factors = np.linspace(1.0, 2.0, 21) # Set up the local geometry finder lgf = LocalGeometryFinder() lgf.setup_parameters(structure_refinement=lgf.STRUCTURE_REFINEMENT_NONE) # Set up the weights for the MultiWeights strategy weights = self.get_weights(weights_options) # Set up the strategy strat = MultiWeightsChemenvStrategy(dist_ang_area_weight=weights['DistAngArea'], self_csm_weight=weights['SelfCSM'], delta_csm_weight=weights['DeltaCSM'], cn_bias_weight=weights['CNBias'], angle_weight=weights['Angle'], normalized_angle_distance_weight=weights['NormalizedAngDist']) fake_valences = [-1] * (self.coordination_geometry.coordination_number + 1) fake_valences[0] = 1 fractions_initial_environment = np.zeros_like(morphing_factors) fractions_final_environment = np.zeros_like(morphing_factors) for ii, morphing_factor in enumerate(morphing_factors): print(ii) struct = self.get_structure(morphing_factor=morphing_factor) print(struct) # Get the StructureEnvironments lgf.setup_structure(structure=struct) se = lgf.compute_structure_environments(only_indices=[0], valences=fake_valences) strat.set_structure_environments(structure_environments=se) result = strat.get_site_coordination_environments_fractions(site=se.structure[0], isite=0, return_strategy_dict_info=True, return_all=True) for res in result: if res['ce_symbol'] == self.initial_environment_symbol: fractions_initial_environment[ii] = res['ce_fraction'] elif res['ce_symbol'] == self.expected_final_environment_symbol: fractions_final_environment[ii] = res['ce_fraction'] fig_width_cm = 8.25 fig_height_cm = 7.0 fig_width = fig_width_cm / 2.54 fig_height = fig_height_cm / 2.54 fig = plt.figure(num=1, figsize=(fig_width, fig_height)) subplot = fig.add_subplot(111) subplot.plot(morphing_factors, fractions_initial_environment, 'b-', label='{}'.format(self.initial_environment_symbol), linewidth=1.5) subplot.plot(morphing_factors, fractions_final_environment, 'g--', label='{}'.format(self.expected_final_environment_symbol), linewidth=1.5) plt.legend(fontsize=8.0, loc=7) plt.show()
def 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
def figure_fractions(self, weights_options, morphing_factors=None): if morphing_factors is None: morphing_factors = np.linspace(1.0, 2.0, 21) # Set up the local geometry finder lgf = LocalGeometryFinder() lgf.setup_parameters( structure_refinement=lgf.STRUCTURE_REFINEMENT_NONE) # Set up the weights for the MultiWeights strategy weights = self.get_weights(weights_options) # Set up the strategy strat = MultiWeightsChemenvStrategy( dist_ang_area_weight=weights['DistAngArea'], self_csm_weight=weights['SelfCSM'], delta_csm_weight=weights['DeltaCSM'], cn_bias_weight=weights['CNBias'], angle_weight=weights['Angle'], normalized_angle_distance_weight=weights['NormalizedAngDist']) fake_valences = [-1] * ( self.coordination_geometry.coordination_number + 1) fake_valences[0] = 1 fractions_initial_environment = np.zeros_like(morphing_factors) fractions_final_environment = np.zeros_like(morphing_factors) for ii, morphing_factor in enumerate(morphing_factors): print(ii) struct = self.get_structure(morphing_factor=morphing_factor) print(struct) # Get the StructureEnvironments lgf.setup_structure(structure=struct) se = lgf.compute_structure_environments(only_indices=[0], valences=fake_valences) strat.set_structure_environments(structure_environments=se) result = strat.get_site_coordination_environments_fractions( site=se.structure[0], isite=0, return_strategy_dict_info=True, return_all=True) for res in result: if res['ce_symbol'] == self.initial_environment_symbol: fractions_initial_environment[ii] = res['ce_fraction'] elif res[ 'ce_symbol'] == self.expected_final_environment_symbol: fractions_final_environment[ii] = res['ce_fraction'] fig_width_cm = 8.25 fig_height_cm = 7.0 fig_width = fig_width_cm / 2.54 fig_height = fig_height_cm / 2.54 fig = plt.figure(num=1, figsize=(fig_width, fig_height)) subplot = fig.add_subplot(111) subplot.plot(morphing_factors, fractions_initial_environment, 'b-', label='{}'.format(self.initial_environment_symbol), linewidth=1.5) subplot.plot(morphing_factors, fractions_final_environment, 'g--', label='{}'.format(self.expected_final_environment_symbol), linewidth=1.5) plt.legend(fontsize=8.0, loc=7) plt.show()
def 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)
class CoordinationGeometryFinderTest(PymatgenTest): def setUp(self): self.lgf = LocalGeometryFinder() self.lgf.setup_parameters( centering_type="standard", structure_refinement=self.lgf.STRUCTURE_REFINEMENT_NONE, ) # self.strategies = [SimplestChemenvStrategy(), SimpleAbundanceChemenvStrategy()] def test_abstract_geometry(self): cg_ts3 = self.lgf.allcg["TS:3"] cg_tet = self.lgf.allcg["T:4"] abstract_geom = AbstractGeometry.from_cg(cg=cg_ts3, centering_type="central_site") self.assertArrayAlmostEqual(abstract_geom.centre, [0.0, 0.0, 0.0]) abstract_geom = AbstractGeometry.from_cg(cg=cg_ts3, centering_type="centroid") self.assertArrayAlmostEqual(abstract_geom.centre, [0.0, 0.0, 0.33333333333]) with self.assertRaises(ValueError) as cm: AbstractGeometry.from_cg( cg=cg_ts3, centering_type="central_site", include_central_site_in_centroid=True, ) self.assertEqual( str(cm.exception), "The center is the central site, no calculation of the centroid, " "variable include_central_site_in_centroid should be set to False", ) abstract_geom = AbstractGeometry.from_cg( cg=cg_ts3, centering_type="centroid", include_central_site_in_centroid=True) self.assertArrayAlmostEqual(abstract_geom.centre, [0.0, 0.0, 0.25]) # WHY ARE WE TESTING STRINGS???? # self.assertEqual(abstract_geom.__str__(), # '\nAbstract Geometry with 3 points :\n' # ' [-1. 0. -0.25]\n' # ' [ 1. 0. -0.25]\n' # ' [ 0. 0. 0.75]\n' # 'Points are referenced to the centroid (calculated with the central site) :\n' # ' [ 0. 0. 0.25]\n') symm_dict = symmetry_measure([[0.0, 0.0, 0.0]], [1.1, 2.2, 3.3]) self.assertAlmostEqual(symm_dict["symmetry_measure"], 0.0) self.assertEqual(symm_dict["scaling_factor"], None) self.assertEqual(symm_dict["rotation_matrix"], None) tio2_struct = self.get_structure("TiO2") envs = self.lgf.compute_coordination_environments( structure=tio2_struct, indices=[0]) self.assertAlmostEqual(envs[0][0]["csm"], 1.5309987846957258) self.assertAlmostEqual(envs[0][0]["ce_fraction"], 1.0) self.assertEqual(envs[0][0]["ce_symbol"], "O:6") self.assertEqual(sorted(envs[0][0]["permutation"]), sorted([0, 4, 1, 5, 2, 3])) self.lgf.setup_random_structure(coordination=5) self.assertEqual(len(self.lgf.structure), 6) self.lgf.setup_random_indices_local_geometry(coordination=5) self.assertEqual(self.lgf.icentral_site, 0) self.assertEqual(len(self.lgf.indices), 5) self.lgf.setup_ordered_indices_local_geometry(coordination=5) self.assertEqual(self.lgf.icentral_site, 0) self.assertEqual(self.lgf.indices, list(range(1, 6))) self.lgf.setup_explicit_indices_local_geometry( explicit_indices=[3, 5, 2, 0, 1, 4]) self.assertEqual(self.lgf.icentral_site, 0) self.assertEqual(self.lgf.indices, [4, 6, 3, 1, 2, 5]) LiFePO4_struct = self.get_structure("LiFePO4") isite = 10 envs_LiFePO4 = self.lgf.compute_coordination_environments( structure=LiFePO4_struct, indices=[isite]) self.assertAlmostEqual(envs_LiFePO4[isite][0]["csm"], 0.140355832317) nbs_coords = [ np.array([6.16700437, -4.55194317, -5.89031356]), np.array([4.71588167, -4.54248093, -3.75553856]), np.array([6.88012571, -5.79877503, -3.73177541]), np.array([6.90041188, -3.32797839, -3.71812416]), ] self.lgf.setup_structure(LiFePO4_struct) self.lgf.setup_local_geometry(isite, coords=nbs_coords) perfect_tet = AbstractGeometry.from_cg( cg=cg_tet, centering_type="centroid", include_central_site_in_centroid=False) points_perfect_tet = perfect_tet.points_wcs_ctwcc() res = self.lgf.coordination_geometry_symmetry_measures_fallback_random( coordination_geometry=cg_tet, NRANDOM=5, points_perfect=points_perfect_tet) ( permutations_symmetry_measures, permutations, algos, local2perfect_maps, perfect2local_maps, ) = res for perm_csm_dict in permutations_symmetry_measures: self.assertAlmostEqual(perm_csm_dict["symmetry_measure"], 0.140355832317) # # def _strategy_test(self, strategy): # files = [] # for (dirpath, dirnames, filenames) in os.walk(json_files_dir): # files.extend(filenames) # break # # for ifile, json_file in enumerate(files): # with self.subTest(json_file=json_file): # f = open("{}/{}".format(json_files_dir, json_file), 'r') # dd = json.load(f) # f.close() # # atom_indices = dd['atom_indices'] # expected_geoms = dd['expected_geoms'] # # struct = Structure.from_dict(dd['structure']) # # struct = self.lgf.setup_structure(struct) # se = self.lgf.compute_structure_environments_detailed_voronoi(only_indices=atom_indices, # maximum_distance_factor=1.5) # # #All strategies should get the correct environment with their default parameters # strategy.set_structure_environments(se) # for ienv, isite in enumerate(atom_indices): # ce = strategy.get_site_coordination_environment(struct[isite]) # try: # coord_env = ce[0] # except TypeError: # coord_env = ce # #Check that the environment found is the expected one # self.assertEqual(coord_env, expected_geoms[ienv]) # # def test_simplest_chemenv_strategy(self): # strategy = SimplestChemenvStrategy() # self._strategy_test(strategy) # # def test_simple_abundance_chemenv_strategy(self): # strategy = SimpleAbundanceChemenvStrategy() # self._strategy_test(strategy) def test_perfect_environments(self): allcg = AllCoordinationGeometries() indices_CN = { 1: [0], 2: [1, 0], 3: [1, 0, 2], 4: [2, 0, 3, 1], 5: [2, 3, 1, 0, 4], 6: [0, 2, 3, 1, 5, 4], 7: [2, 6, 0, 3, 4, 5, 1], 8: [1, 2, 6, 3, 7, 0, 4, 5], 9: [5, 2, 6, 0, 4, 7, 3, 8, 1], 10: [8, 5, 6, 3, 0, 7, 2, 4, 9, 1], 11: [7, 6, 4, 1, 2, 5, 0, 8, 9, 10, 3], 12: [5, 8, 9, 0, 3, 1, 4, 2, 6, 11, 10, 7], 13: [4, 11, 5, 12, 1, 2, 8, 3, 0, 6, 9, 7, 10], 20: [ 8, 12, 11, 0, 14, 10, 13, 6, 18, 1, 9, 17, 3, 19, 5, 7, 15, 2, 16, 4 ], } for coordination in range(1, 21): for mp_symbol in allcg.get_implemented_geometries( coordination=coordination, returned="mp_symbol"): cg = allcg.get_geometry_from_mp_symbol(mp_symbol=mp_symbol) self.lgf.allcg = AllCoordinationGeometries( only_symbols=[mp_symbol]) self.lgf.setup_test_perfect_environment( mp_symbol, randomness=False, indices=indices_CN[coordination], random_translation="NONE", random_rotation="NONE", random_scale="NONE", ) se = self.lgf.compute_structure_environments( only_indices=[0], maximum_distance_factor=1.01 * cg.distfactor_max, min_cn=cg.coordination_number, max_cn=cg.coordination_number, only_symbols=[mp_symbol], ) self.assertAlmostEqual( se.get_csm(0, mp_symbol)["symmetry_measure"], 0.0, delta=1e-8, msg= f"Failed to get perfect environment with mp_symbol {mp_symbol}", ) def test_disable_hints(self): allcg = AllCoordinationGeometries() mp_symbol = "SH:13" mp_symbols = ["SH:13", "HP:12"] cg = allcg.get_geometry_from_mp_symbol(mp_symbol=mp_symbol) mypoints = cg.points mypoints[-1] = [0.9 * cc for cc in mypoints[-1]] self.lgf.allcg = AllCoordinationGeometries(only_symbols=[mp_symbol]) self.lgf.setup_test_perfect_environment( mp_symbol, randomness=False, indices=[4, 11, 5, 12, 1, 2, 8, 3, 0, 6, 9, 7, 10], random_translation="NONE", random_rotation="NONE", random_scale="NONE", points=mypoints, ) se_nohints = self.lgf.compute_structure_environments( only_indices=[0], maximum_distance_factor=1.02 * cg.distfactor_max, min_cn=12, max_cn=13, only_symbols=mp_symbols, get_from_hints=False, ) se_hints = self.lgf.compute_structure_environments( only_indices=[0], maximum_distance_factor=1.02 * cg.distfactor_max, min_cn=12, max_cn=13, only_symbols=mp_symbols, get_from_hints=True, ) with self.assertRaises(KeyError): abc = se_nohints.ce_list[0][12] abc.minimum_geometries() self.assertAlmostEqual(se_hints.ce_list[0][13][0], se_nohints.ce_list[0][13][0]) self.assertTrue( set(se_nohints.ce_list[0].keys()).issubset( set(se_hints.ce_list[0].keys())))
def setUp(self): self.lgf = LocalGeometryFinder() self.lgf.setup_parameters(centering_type='standard', structure_refinement=self.lgf.STRUCTURE_REFINEMENT_NONE)
if sepplanealgo.algorithm_type != "SEPARATION_PLANE": raise ValueError("Should all be separation plane") permsonfile = f"Permutations on file in this algorithm ({len(sepplanealgo._permutations):d}) " print(permsonfile) print(sepplanealgo._permutations) permutations = sepplanealgo.safe_separation_permutations( ordered_plane=sepplanealgo.ordered_plane, ordered_point_groups=sepplanealgo.ordered_point_groups ) sepplanealgo._permutations = permutations print(f"Test permutations ({len(permutations):d}) :") print(permutations) lgf = LocalGeometryFinder() lgf.setup_parameters(structure_refinement=lgf.STRUCTURE_REFINEMENT_NONE) lgf.setup_test_perfect_environment( cg_symbol, randomness=True, indices=range(cg.coordination_number), max_random_dist=0.05 ) lgf.perfect_geometry = AbstractGeometry.from_cg(cg=cg) # Setting up the plane of separation local_plane = None found = False for npoints in range(sepplanealgo.minimum_number_of_points, min(sepplanealgo.maximum_number_of_points, 4) + 1): if found: break for ipoints in itertools.combinations(sepplanealgo.plane_points, npoints): points_combination = [lgf.local_geometry.coords[ipoint] for ipoint in ipoints]
class CoordinationGeometryFinderTest(unittest2.TestCase): def setUp(self): self.lgf = LocalGeometryFinder() self.lgf.setup_parameters(centering_type='standard') self.strategies = [ SimplestChemenvStrategy(), SimpleAbundanceChemenvStrategy() ] # def _strategy_test(self, strategy): # files = [] # for (dirpath, dirnames, filenames) in os.walk(json_files_dir): # files.extend(filenames) # break # # for ifile, json_file in enumerate(files): # with self.subTest(json_file=json_file): # f = open("{}/{}".format(json_files_dir, json_file), 'r') # dd = json.load(f) # f.close() # # atom_indices = dd['atom_indices'] # expected_geoms = dd['expected_geoms'] # # struct = Structure.from_dict(dd['structure']) # # struct = self.lgf.setup_structure(struct) # se = self.lgf.compute_structure_environments_detailed_voronoi(only_indices=atom_indices, # maximum_distance_factor=1.5) # # #All strategies should get the correct environment with their default parameters # strategy.set_structure_environments(se) # for ienv, isite in enumerate(atom_indices): # ce = strategy.get_site_coordination_environment(struct[isite]) # try: # coord_env = ce[0] # except TypeError: # coord_env = ce # #Check that the environment found is the expected one # self.assertEqual(coord_env, expected_geoms[ienv]) # # def test_simplest_chemenv_strategy(self): # strategy = SimplestChemenvStrategy() # self._strategy_test(strategy) # # def test_simple_abundance_chemenv_strategy(self): # strategy = SimpleAbundanceChemenvStrategy() # self._strategy_test(strategy) def test_perfect_environments(self): for coordination in range(1, 13): for mp_symbol in AllCoordinationGeometries( ).get_implemented_geometries(coordination=coordination, returned='mp_symbol'): with self.subTest(msg=mp_symbol, mp_symbol=mp_symbol): self.lgf.setup_test_perfect_environment( mp_symbol, randomness=False, indices='RANDOM', random_translation=True, random_rotation=True, random_scale=True) se = self.lgf.compute_structure_environments_detailed_voronoi( only_indices=[0], maximum_distance_factor=1.5) self.assertAlmostEqual( se.get_csm(0, mp_symbol)['symmetry_measure'], 0.0, 4)
# Define the coordination geometry cg_symbol = raw_input('Enter symbol of the geometry for which you want to get the optimized permutations ' 'or "q" to quit : ') if cg_symbol == 'q': break if cg_symbol not in sepplane_cgs: print('Wrong geometry, try again ...') continue cg = allcg[cg_symbol] print('Getting explicit permutations for geometry "{}" (symbol : "{}")\n'.format(cg.name, cg_symbol)) # Setup of the local geometry finder lgf = LocalGeometryFinder() lgf.setup_parameters(structure_refinement=lgf.STRUCTURE_REFINEMENT_NONE) # Setup the random environment lgf.setup_test_perfect_environment(cg_symbol, randomness=True, indices=range(cg.coordination_number), max_random_dist=0.05) lgf.perfect_geometry = AbstractGeometry.from_cg(cg=cg) points_perfect = lgf.perfect_geometry.points_wocs_ctwocc() # 1. Check the algorithms defined for this coordination geometry and get the explicit permutations original_nexplicit_perms = [] original_nexplicit_optimized_perms = [] for ialgo, algo in enumerate(cg.algorithms): algo._permutations = algo.explicit_permutations if algo.algorithm_type == 'EXPLICIT_PERMUTATIONS': raise ValueError('Do something for the explicit ones ... (these should anyway be by far ok!)')
# print(row.id) key_value_pairs = row.key_value_pairs structure_id = key_value_pairs["structure_id"] if structure_id in ids_to_run: print("RUNNING!") atoms = row.toatoms() 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:
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("")
def compute_environments(chemenv_configuration): string_sources = {'cif': {'string': 'a Cif file', 'regexp': r'.*\.cif$'}, 'mp': {'string': 'the Materials Project database', 'regexp': r'mp-[0-9]+$'}} questions = {'c': 'cif'} questions['m'] = 'mp' lgf = LocalGeometryFinder() lgf.setup_parameters() allcg = AllCoordinationGeometries() strategy_class = strategies_class_lookup[chemenv_configuration.package_options['default_strategy']['strategy']] #TODO: Add the possibility to change the parameters and save them in the chemenv_configuration default_strategy = strategy_class() default_strategy.setup_options(chemenv_configuration.package_options['default_strategy']['strategy_options']) max_dist_factor = chemenv_configuration.package_options['default_max_distance_factor'] firsttime = True while True: if len(questions) > 1: found = False print('Enter the source from which the structure is coming or <q> to quit :') for key_character, qq in questions.items(): print(' - <{}> for a structure from {}'.format(key_character, string_sources[qq]['string'])) test = input(' ... ') if test == 'q': break if test not in list(questions.keys()): for key_character, qq in questions.items(): if re.match(string_sources[qq]['regexp'], str(test)) is not None: found = True source_type = qq if not found: print('Wrong key, try again ...') continue else: source_type = questions[test] else: found = False source_type = list(questions.values())[0] if found and len(questions) > 1: input_source = test if source_type == 'cif': if not found: input_source = input('Enter path to cif file : ') cp = CifParser(input_source) structure = cp.get_structures()[0] elif source_type == 'mp': if not found: input_source = input('Enter materials project id (e.g. "mp-1902") : ') a = MPRester() structure = a.get_structure_by_material_id(input_source) lgf.setup_structure(structure) print('Computing environments for {} ... '.format(structure.composition.reduced_formula)) se = lgf.compute_structure_environments(maximum_distance_factor=max_dist_factor) print('Computing environments finished') while True: test = input('See list of environments determined for each (unequivalent) site ? ' '("y" or "n", "d" with details, "g" to see the grid) : ') strategy = default_strategy if test in ['y', 'd', 'g']: strategy.set_structure_environments(se) for eqslist in se.equivalent_sites: site = eqslist[0] isite = se.structure.index(site) try: if strategy.uniquely_determines_coordination_environments: ces = strategy.get_site_coordination_environments(site) else: ces = strategy.get_site_coordination_environments_fractions(site) except NeighborsNotComputedChemenvError: continue if ces is None: continue if len(ces) == 0: continue comp = site.species_and_occu #ce = strategy.get_site_coordination_environment(site) if strategy.uniquely_determines_coordination_environments: ce = ces[0] if ce is None: continue thecg = allcg.get_geometry_from_mp_symbol(ce[0]) mystring = 'Environment for site #{} {} ({}) : {} ({})\n'.format(str(isite), comp.get_reduced_formula_and_factor()[0], str(comp), thecg.name, ce[0]) else: mystring = 'Environments for site #{} {} ({}) : \n'.format(str(isite), comp.get_reduced_formula_and_factor()[0], str(comp)) for ce in ces: cg = allcg.get_geometry_from_mp_symbol(ce[0]) csm = ce[1]['other_symmetry_measures']['csm_wcs_ctwcc'] mystring += ' - {} ({}): {:.2f} % (csm : {:2f})\n'.format(cg.name, cg.mp_symbol, 100.0*ce[2], csm) if test in ['d', 'g'] and strategy.uniquely_determines_coordination_environments: if thecg.mp_symbol != UNCLEAR_ENVIRONMENT_SYMBOL: mystring += ' <Continuous symmetry measures> ' mingeoms = se.ce_list[isite][thecg.coordination_number][0].minimum_geometries() for mingeom in mingeoms: csm = mingeom[1]['other_symmetry_measures']['csm_wcs_ctwcc'] mystring += '{} : {:.2f} '.format(mingeom[0], csm) print(mystring) if test == 'g': while True: test = input('Enter index of site(s) (e.g. 0 1 2, separated by spaces) for which you want to see the grid of parameters : ') try: indices=[int(x) for x in test.split()] print(str(indices)) for isite in indices: if isite <0: raise IndexError se.plot_environments(isite, additional_condition=se.AC.ONLY_ACB) break except ValueError: print('This is not a valid site') except IndexError: print('This site is out of the site range') if no_vis: test = input('Go to next structure ? ("y" to do so)') if test == 'y': break continue test = input('View structure with environments ? ("y" for the unit cell or "m" for a supercell or "n") : ') if test in ['y', 'm']: if test == 'm': mydeltas = [] while True: try: test = input('Enter multiplicity (e.g. 3 2 2) : ') nns = test.split() for i0 in range(int(nns[0])): for i1 in range(int(nns[1])): for i2 in range(int(nns[2])): mydeltas.append(np.array([1.0*i0, 1.0*i1, 1.0*i2], np.float)) break except (ValueError,IndexError): print('Not a valid multiplicity') else: mydeltas = [np.zeros(3, np.float)] if firsttime: vis = StructureVis(show_polyhedron=False, show_unit_cell=True) vis.show_help = False firsttime = False vis.set_structure(se.structure) strategy.set_structure_environments(se) for isite, site in enumerate(se.structure): try: ces = strategy.get_site_coordination_environments(site) except NeighborsNotComputedChemenvError: continue if len(ces) == 0: continue ce = strategy.get_site_coordination_environment(site) if ce is not None and ce[0] != UNCLEAR_ENVIRONMENT_SYMBOL: for mydelta in mydeltas: psite = PeriodicSite(site._species, site._fcoords + mydelta, site._lattice, properties=site._properties) vis.add_site(psite) neighbors = strategy.get_site_neighbors(psite) draw_cg(vis, psite, neighbors, cg=lgf.allcg.get_geometry_from_mp_symbol(ce[0]), perm=ce[1]['permutation']) vis.show() test = input('Go to next structure ? ("y" to do so) : ') if test == 'y': break print('')
class CoordinationGeometryFinderTest(PymatgenTest): def setUp(self): self.lgf = LocalGeometryFinder() self.lgf.setup_parameters(centering_type='standard', structure_refinement=self.lgf.STRUCTURE_REFINEMENT_NONE) # self.strategies = [SimplestChemenvStrategy(), SimpleAbundanceChemenvStrategy()] def test_abstract_geometry(self): cg_ts3 = self.lgf.allcg['TS:3'] cg_tet = self.lgf.allcg['T:4'] abstract_geom = AbstractGeometry.from_cg(cg=cg_ts3, centering_type='central_site') self.assertArrayAlmostEqual(abstract_geom.centre, [0.0, 0.0, 0.0]) abstract_geom = AbstractGeometry.from_cg(cg=cg_ts3, centering_type='centroid') self.assertArrayAlmostEqual(abstract_geom.centre, [0.0, 0.0, 0.33333333333]) with self.assertRaises(ValueError) as cm: AbstractGeometry.from_cg(cg=cg_ts3, centering_type='central_site', include_central_site_in_centroid=True) self.assertEqual(str(cm.exception), 'The center is the central site, no calculation of the centroid, ' 'variable include_central_site_in_centroid should be set to False') abstract_geom = AbstractGeometry.from_cg(cg=cg_ts3, centering_type='centroid', include_central_site_in_centroid=True) self.assertArrayAlmostEqual(abstract_geom.centre, [0.0, 0.0, 0.25]) self.assertEqual(abstract_geom.__str__(), '\nAbstract Geometry with 3 points :\n' ' [-1. 0. -0.25]\n' ' [ 1. 0. -0.25]\n' ' [0. 0. 0.75]\n' 'Points are referenced to the centroid (calculated with the central site) :\n' ' [0. 0. 0.25]\n') symm_dict = symmetry_measure([[0.0, 0.0, 0.0]], [1.1, 2.2, 3.3]) self.assertAlmostEqual(symm_dict['symmetry_measure'], 0.0) self.assertEqual(symm_dict['scaling_factor'], None) self.assertEqual(symm_dict['rotation_matrix'], None) tio2_struct = self.get_structure('TiO2') envs = self.lgf.compute_coordination_environments(structure=tio2_struct, indices=[0]) self.assertAlmostEqual(envs[0][0]['csm'], 1.5309987846957258) self.assertAlmostEqual(envs[0][0]['ce_fraction'], 1.0) self.assertEqual(envs[0][0]['ce_symbol'], 'O:6') self.assertEqual(sorted(envs[0][0]['permutation']), sorted([0, 4, 1, 5, 2, 3])) self.lgf.setup_random_structure(coordination=5) self.assertEqual(len(self.lgf.structure), 6) self.lgf.setup_random_indices_local_geometry(coordination=5) self.assertEqual(self.lgf.icentral_site, 0) self.assertEqual(len(self.lgf.indices), 5) self.lgf.setup_ordered_indices_local_geometry(coordination=5) self.assertEqual(self.lgf.icentral_site, 0) self.assertEqual(self.lgf.indices, list(range(1, 6))) self.lgf.setup_explicit_indices_local_geometry(explicit_indices=[3, 5, 2, 0, 1, 4]) self.assertEqual(self.lgf.icentral_site, 0) self.assertEqual(self.lgf.indices, [4, 6, 3, 1, 2, 5]) LiFePO4_struct = self.get_structure('LiFePO4') isite = 10 envs_LiFePO4 = self.lgf.compute_coordination_environments(structure=LiFePO4_struct, indices=[isite]) self.assertAlmostEqual(envs_LiFePO4[isite][0]['csm'], 0.140355832317) nbs_coords = [np.array([6.16700437, -4.55194317, -5.89031356]), np.array([4.71588167, -4.54248093, -3.75553856]), np.array([6.88012571, -5.79877503, -3.73177541]), np.array([6.90041188, -3.32797839, -3.71812416])] self.lgf.setup_structure(LiFePO4_struct) self.lgf.setup_local_geometry(isite, coords=nbs_coords) perfect_tet = AbstractGeometry.from_cg(cg=cg_tet, centering_type='centroid', include_central_site_in_centroid=False) points_perfect_tet = perfect_tet.points_wcs_ctwcc() res = self.lgf.coordination_geometry_symmetry_measures_fallback_random(coordination_geometry=cg_tet, NRANDOM=5, points_perfect=points_perfect_tet) permutations_symmetry_measures, permutations, algos, local2perfect_maps, perfect2local_maps = res for perm_csm_dict in permutations_symmetry_measures: self.assertAlmostEqual(perm_csm_dict['symmetry_measure'], 0.140355832317) # # def _strategy_test(self, strategy): # files = [] # for (dirpath, dirnames, filenames) in os.walk(json_files_dir): # files.extend(filenames) # break # # for ifile, json_file in enumerate(files): # with self.subTest(json_file=json_file): # f = open("{}/{}".format(json_files_dir, json_file), 'r') # dd = json.load(f) # f.close() # # atom_indices = dd['atom_indices'] # expected_geoms = dd['expected_geoms'] # # struct = Structure.from_dict(dd['structure']) # # struct = self.lgf.setup_structure(struct) # se = self.lgf.compute_structure_environments_detailed_voronoi(only_indices=atom_indices, # maximum_distance_factor=1.5) # # #All strategies should get the correct environment with their default parameters # strategy.set_structure_environments(se) # for ienv, isite in enumerate(atom_indices): # ce = strategy.get_site_coordination_environment(struct[isite]) # try: # coord_env = ce[0] # except TypeError: # coord_env = ce # #Check that the environment found is the expected one # self.assertEqual(coord_env, expected_geoms[ienv]) # # def test_simplest_chemenv_strategy(self): # strategy = SimplestChemenvStrategy() # self._strategy_test(strategy) # # def test_simple_abundance_chemenv_strategy(self): # strategy = SimpleAbundanceChemenvStrategy() # self._strategy_test(strategy) def test_perfect_environments(self): allcg = AllCoordinationGeometries() indices_CN = {1: [0], 2: [1, 0], 3: [1, 0, 2], 4: [2, 0, 3, 1], 5: [2, 3, 1, 0, 4], 6: [0, 2, 3, 1, 5, 4], 7: [2, 6, 0, 3, 4, 5, 1], 8: [1, 2, 6, 3, 7, 0, 4, 5], 9: [5, 2, 6, 0, 4, 7, 3, 8, 1], 10: [8, 5, 6, 3, 0, 7, 2, 4, 9, 1], 11: [7, 6, 4, 1, 2, 5, 0, 8, 9, 10, 3], 12: [5, 8, 9, 0, 3, 1, 4, 2, 6, 11, 10, 7], 13: [4, 11, 5, 12, 1, 2, 8, 3, 0, 6, 9, 7, 10], } for coordination in range(1, 14): for mp_symbol in allcg.get_implemented_geometries(coordination=coordination, returned='mp_symbol'): cg = allcg.get_geometry_from_mp_symbol(mp_symbol=mp_symbol) self.lgf.allcg = AllCoordinationGeometries(only_symbols=[mp_symbol]) self.lgf.setup_test_perfect_environment(mp_symbol, randomness=False, indices=indices_CN[coordination], random_translation='NONE', random_rotation='NONE', random_scale='NONE') se = self.lgf.compute_structure_environments(only_indices=[0], maximum_distance_factor=1.01*cg.distfactor_max, min_cn=cg.coordination_number, max_cn=cg.coordination_number, only_symbols=[mp_symbol] ) self.assertAlmostEqual(se.get_csm(0, mp_symbol)['symmetry_measure'], 0.0, delta=1e-8, msg='Failed to get perfect environment with mp_symbol {}'.format(mp_symbol)) def test_disable_hints(self): allcg = AllCoordinationGeometries() mp_symbol = 'SH:13' mp_symbols = ['SH:13', 'HP:12'] cg = allcg.get_geometry_from_mp_symbol(mp_symbol=mp_symbol) mypoints = cg.points mypoints[-1] = [0.9*cc for cc in mypoints[-1]] self.lgf.allcg = AllCoordinationGeometries(only_symbols=[mp_symbol]) self.lgf.setup_test_perfect_environment(mp_symbol, randomness=False, indices=[4, 11, 5, 12, 1, 2, 8, 3, 0, 6, 9, 7, 10], random_translation='NONE', random_rotation='NONE', random_scale='NONE', points=mypoints) se_nohints = self.lgf.compute_structure_environments(only_indices=[0], maximum_distance_factor=1.02 * cg.distfactor_max, min_cn=12, max_cn=13, only_symbols=mp_symbols, get_from_hints=False ) se_hints = self.lgf.compute_structure_environments(only_indices=[0], maximum_distance_factor=1.02 * cg.distfactor_max, min_cn=12, max_cn=13, only_symbols=mp_symbols, get_from_hints=True ) with self.assertRaises(KeyError): abc = se_nohints.ce_list[0][12] abc.minimum_geometries() self.assertAlmostEqual(se_hints.ce_list[0][13][0], se_nohints.ce_list[0][13][0]) self.assertTrue(set(se_nohints.ce_list[0].keys()).issubset(set(se_hints.ce_list[0].keys())))
if __name__ == "__main__": allcg = AllCoordinationGeometries() while True: cg_symbol = raw_input("Enter symbol of the geometry for which you want to get the explicit permutations : ") try: cg = allcg[cg_symbol] break except LookupError: print("Wrong geometry, try again ...") continue lgf = LocalGeometryFinder() lgf.setup_parameters(structure_refinement=lgf.STRUCTURE_REFINEMENT_NONE) myindices = range(cg.coordination_number) test = raw_input( 'Enter if you want to test all possible permutations ("all" or "a") or a given number of random permutations (i.e. "25")' ) if test == "all" or test == "a": perms_iterator = itertools.permutations(myindices) nperms = factorial(cg.coordination_number) else: try: nperms = int(test) except:
def setUp(self): self.lgf = LocalGeometryFinder() self.lgf.setup_parameters(centering_type='standard') self.strategies = [SimplestChemenvStrategy(), SimpleAbundanceChemenvStrategy()]
break except LookupError: print('Wrong geometry, try again ...') continue # Check if the algorithm currently defined for this geometry corresponds to the explicit permutation algorithm for algo in cg.algorithms: if algo.algorithm_type != 'EXPLICIT_PERMUTATIONS': raise ValueError('WRONG ALGORITHM !') algo = Algo() algo.permutations = [] for perm in itertools.permutations(range(cg.coordination)): algo.permutations.append(perm) lgf = LocalGeometryFinder() lgf.setup_parameters(structure_refinement=lgf.STRUCTURE_REFINEMENT_NONE) lgf.setup_test_perfect_environment(cg_symbol, randomness=True, indices='ORDERED') lgf.perfect_geometry = AbstractGeometry.from_cg(cg=cg) points_perfect = lgf.perfect_geometry.points_wocs_ctwocc() res = lgf.coordination_geometry_symmetry_measures_standard( coordination_geometry=cg, algo=algo, points_perfect=points_perfect) (csms, perms, algos, local2perfect_maps, perfect2local_maps) = res csms_with_recorded_permutation = [] explicit_permutations = [] for icsm, csm in enumerate(csms):
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"}
class CoordinationGeometryFinderTest(unittest.TestCase): def setUp(self): self.lgf = LocalGeometryFinder() self.lgf.setup_parameters( centering_type='standard', structure_refinement=self.lgf.STRUCTURE_REFINEMENT_NONE) # self.strategies = [SimplestChemenvStrategy(), SimpleAbundanceChemenvStrategy()] # # def _strategy_test(self, strategy): # files = [] # for (dirpath, dirnames, filenames) in os.walk(json_files_dir): # files.extend(filenames) # break # # for ifile, json_file in enumerate(files): # with self.subTest(json_file=json_file): # f = open("{}/{}".format(json_files_dir, json_file), 'r') # dd = json.load(f) # f.close() # # atom_indices = dd['atom_indices'] # expected_geoms = dd['expected_geoms'] # # struct = Structure.from_dict(dd['structure']) # # struct = self.lgf.setup_structure(struct) # se = self.lgf.compute_structure_environments_detailed_voronoi(only_indices=atom_indices, # maximum_distance_factor=1.5) # # #All strategies should get the correct environment with their default parameters # strategy.set_structure_environments(se) # for ienv, isite in enumerate(atom_indices): # ce = strategy.get_site_coordination_environment(struct[isite]) # try: # coord_env = ce[0] # except TypeError: # coord_env = ce # #Check that the environment found is the expected one # self.assertEqual(coord_env, expected_geoms[ienv]) # # def test_simplest_chemenv_strategy(self): # strategy = SimplestChemenvStrategy() # self._strategy_test(strategy) # # def test_simple_abundance_chemenv_strategy(self): # strategy = SimpleAbundanceChemenvStrategy() # self._strategy_test(strategy) def test_perfect_environments(self): allcg = AllCoordinationGeometries() indices_CN = { 1: [0], 2: [1, 0], 3: [1, 0, 2], 4: [2, 0, 3, 1], 5: [2, 3, 1, 0, 4], 6: [0, 2, 3, 1, 5, 4], 7: [2, 6, 0, 3, 4, 5, 1], 8: [1, 2, 6, 3, 7, 0, 4, 5], 9: [5, 2, 6, 0, 4, 7, 3, 8, 1], 10: [8, 5, 6, 3, 0, 7, 2, 4, 9, 1], 11: [7, 6, 4, 1, 2, 5, 0, 8, 9, 10, 3], 12: [5, 8, 9, 0, 3, 1, 4, 2, 6, 11, 10, 7], 13: [4, 11, 5, 12, 1, 2, 8, 3, 0, 6, 9, 7, 10], } for coordination in range(1, 14): for mp_symbol in allcg.get_implemented_geometries( coordination=coordination, returned='mp_symbol'): cg = allcg.get_geometry_from_mp_symbol(mp_symbol=mp_symbol) self.lgf.allcg = AllCoordinationGeometries( only_symbols=[mp_symbol]) self.lgf.setup_test_perfect_environment( mp_symbol, randomness=False, indices=indices_CN[coordination], random_translation='NONE', random_rotation='NONE', random_scale='NONE') se = self.lgf.compute_structure_environments( only_indices=[0], maximum_distance_factor=1.01 * cg.distfactor_max, min_cn=cg.coordination_number, max_cn=cg.coordination_number, only_symbols=[mp_symbol]) self.assertAlmostEqual( se.get_csm(0, mp_symbol)['symmetry_measure'], 0.0, delta=1e-8, msg='Failed to get perfect environment with mp_symbol {}'. format(mp_symbol))
break except LookupError: print('Wrong geometry, try again ...') continue # Check if the algorithm currently defined for this geometry corresponds to the explicit permutation algorithm for algo in cg.algorithms: if algo.algorithm_type != 'EXPLICIT_PERMUTATIONS': raise ValueError('WRONG ALGORITHM !') algo = Algo() algo.permutations = [] for perm in itertools.permutations(range(cg.coordination)): algo.permutations.append(perm) lgf = LocalGeometryFinder() lgf.setup_parameters(structure_refinement=lgf.STRUCTURE_REFINEMENT_NONE) lgf.setup_test_perfect_environment(cg_symbol, randomness=True, indices='ORDERED') lgf.perfect_geometry = AbstractGeometry.from_cg(cg=cg) points_perfect = lgf.perfect_geometry.points_wocs_ctwocc() res = lgf.coordination_geometry_symmetry_measures_standard(coordination_geometry=cg, algo=algo, points_perfect=points_perfect) (csms, perms, algos, local2perfect_maps, perfect2local_maps) = res csms_with_recorded_permutation = [] explicit_permutations = [] for icsm, csm in enumerate(csms): found = False
def setUpClass(cls): cls.lgf = LocalGeometryFinder() cls.lgf.setup_parameters(centering_type="standard") os.makedirs("tmp_dir")
for ii in range(nperms): shuffle(myindices) perms_iterator.append(list(myindices)) for cg_symbol, cg_name in symbol_name_mapping.items(): cg = allcg[cg_symbol] if cg.deactivate: continue print('Testing {} ({})'.format(cg_symbol, cg_name)) cg = allcg[cg_symbol] if cg.points is None: continue lgf = LocalGeometryFinder() lgf.setup_parameters( structure_refinement=lgf.STRUCTURE_REFINEMENT_NONE) # Reinitialize the itertools permutations if perms_type == 'all': perms_iterator = itertools.permutations(myindices) #Loop on the permutations iperm = 1 for indices_perm in perms_iterator: lgf.setup_test_perfect_environment(cg_symbol, indices=indices_perm, randomness=True, max_random_dist=0.1,
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)
class CoordinationGeometryFinderTest(unittest.TestCase): def setUp(self): self.lgf = LocalGeometryFinder() self.lgf.setup_parameters(centering_type='standard', structure_refinement=self.lgf.STRUCTURE_REFINEMENT_NONE) # self.strategies = [SimplestChemenvStrategy(), SimpleAbundanceChemenvStrategy()] # # def _strategy_test(self, strategy): # files = [] # for (dirpath, dirnames, filenames) in os.walk(json_files_dir): # files.extend(filenames) # break # # for ifile, json_file in enumerate(files): # with self.subTest(json_file=json_file): # f = open("{}/{}".format(json_files_dir, json_file), 'r') # dd = json.load(f) # f.close() # # atom_indices = dd['atom_indices'] # expected_geoms = dd['expected_geoms'] # # struct = Structure.from_dict(dd['structure']) # # struct = self.lgf.setup_structure(struct) # se = self.lgf.compute_structure_environments_detailed_voronoi(only_indices=atom_indices, # maximum_distance_factor=1.5) # # #All strategies should get the correct environment with their default parameters # strategy.set_structure_environments(se) # for ienv, isite in enumerate(atom_indices): # ce = strategy.get_site_coordination_environment(struct[isite]) # try: # coord_env = ce[0] # except TypeError: # coord_env = ce # #Check that the environment found is the expected one # self.assertEqual(coord_env, expected_geoms[ienv]) # # def test_simplest_chemenv_strategy(self): # strategy = SimplestChemenvStrategy() # self._strategy_test(strategy) # # def test_simple_abundance_chemenv_strategy(self): # strategy = SimpleAbundanceChemenvStrategy() # self._strategy_test(strategy) def test_perfect_environments(self): allcg = AllCoordinationGeometries() indices_CN = {1: [0], 2: [1, 0], 3: [1, 0, 2], 4: [2, 0, 3, 1], 5: [2, 3, 1, 0, 4], 6: [0, 2, 3, 1, 5, 4], 7: [2, 6, 0, 3, 4, 5, 1], 8: [1, 2, 6, 3, 7, 0, 4, 5], 9: [5, 2, 6, 0, 4, 7, 3, 8, 1], 10: [8, 5, 6, 3, 0, 7, 2, 4, 9, 1], 11: [7, 6, 4, 1, 2, 5, 0, 8, 9, 10, 3], 12: [5, 8, 9, 0, 3, 1, 4, 2, 6, 11, 10, 7], 13: [4, 11, 5, 12, 1, 2, 8, 3, 0, 6, 9, 7, 10], } for coordination in range(1, 14): for mp_symbol in allcg.get_implemented_geometries(coordination=coordination, returned='mp_symbol'): cg = allcg.get_geometry_from_mp_symbol(mp_symbol=mp_symbol) self.lgf.allcg = AllCoordinationGeometries(only_symbols=[mp_symbol]) self.lgf.setup_test_perfect_environment(mp_symbol, randomness=False, indices=indices_CN[coordination], random_translation='NONE', random_rotation='NONE', random_scale='NONE') se = self.lgf.compute_structure_environments(only_indices=[0], maximum_distance_factor=1.01*cg.distfactor_max, min_cn=cg.coordination_number, max_cn=cg.coordination_number, only_symbols=[mp_symbol] ) self.assertAlmostEqual(se.get_csm(0, mp_symbol)['symmetry_measure'], 0.0, delta=1e-8, msg='Failed to get perfect environment with mp_symbol {}'.format(mp_symbol))
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)
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('')
for ii in range(nperms): shuffle(myindices) perms_iterator.append(list(myindices)) for cg_symbol, cg_name in symbol_name_mapping.items(): cg = allcg[cg_symbol] if cg.deactivate: continue print('Testing {} ({})'.format(cg_symbol, cg_name)) cg = allcg[cg_symbol] if cg.points is None: continue lgf = LocalGeometryFinder() lgf.setup_parameters(structure_refinement=lgf.STRUCTURE_REFINEMENT_NONE) # Reinitialize the itertools permutations if perms_type == 'all': perms_iterator = itertools.permutations(myindices) #Loop on the permutations iperm = 1 for indices_perm in perms_iterator: lgf.setup_test_perfect_environment(cg_symbol, indices=indices_perm, randomness=True, max_random_dist=0.1,
if __name__ == '__main__': allcg = AllCoordinationGeometries() while True: cg_symbol = input( 'Enter symbol of the geometry for which you want to get the explicit permutations : ' ) try: cg = allcg[cg_symbol] break except LookupError: print('Wrong geometry, try again ...') continue lgf = LocalGeometryFinder() lgf.setup_parameters(structure_refinement=lgf.STRUCTURE_REFINEMENT_NONE) myindices = range(cg.coordination_number) test = input( 'Enter if you want to test all possible permutations ("all" or "a") or a given number of random permutations (i.e. "25")' ) if test == 'all' or test == 'a': perms_iterator = itertools.permutations(myindices) nperms = factorial(cg.coordination_number) else: try: nperms = int(test) except Exception:
class CoordinationGeometryFinderTest(unittest2.TestCase): def setUp(self): self.lgf = LocalGeometryFinder() self.lgf.setup_parameters(centering_type='standard') self.strategies = [SimplestChemenvStrategy(), SimpleAbundanceChemenvStrategy()]
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],
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 setUp(self): self.lgf = LocalGeometryFinder() self.lgf.setup_parameters( centering_type='standard', structure_refinement=self.lgf.STRUCTURE_REFINEMENT_NONE)
def run_task(self, fw_spec): logging.basicConfig(filename='chemenv_structure_environments.log', format='%(levelname)s:%(module)s:%(funcName)s:%(message)s', level=logging.DEBUG) lgf = LocalGeometryFinder() lgf.setup_parameters(centering_type='centroid', include_central_site_in_centroid=True, structure_refinement=lgf.STRUCTURE_REFINEMENT_NONE) if 'chemenv_parameters' in fw_spec: for param, value in fw_spec['chemenv_parameters'].items(): lgf.setup_parameter(param, value) identifier = fw_spec['identifier'] if 'structure' in fw_spec: structure = fw_spec['structure'] else: if identifier['source'] == 'MaterialsProject' and 'material_id' in identifier: if not 'mapi_key' in fw_spec: raise ValueError('The mapi_key should be provided to get the structure from the Materials Project') # FIXME: Use MPRester from pymatgen from pymatgen.matproj.rest import MPRester a = MPRester(fw_spec['mapi_key']) structure = a.get_structure_by_material_id(identifier['material_id']) else: raise ValueError('Either structure or identifier with source = MaterialsProject and material_id ' 'should be provided') info = {} # Compute the structure environments lgf.setup_structure(structure) if 'valences' in fw_spec: valences = fw_spec['valences'] else: try: bva = BVAnalyzer() valences = bva.get_valences(structure=structure) info['valences'] = {'origin': 'BVAnalyzer'} except: valences = 'undefined' info['valences'] = {'origin': 'None'} excluded_atoms = None if 'excluded_atoms' in fw_spec: excluded_atoms = fw_spec['excluded_atoms'] se = lgf.compute_structure_environments(only_cations=False, valences=valences, excluded_atoms=excluded_atoms) # Write to json file if 'json_file' in fw_spec: json_file = fw_spec['json_file'] else: json_file = 'structure_environments.json' f = open(json_file, 'w') json.dump(se.as_dict(), f) f.close() # Save to database if 'mongo_database' in fw_spec: database = fw_spec['mongo_database'] entry = {'identifier': identifier, 'elements': [elmt.symbol for elmt in structure.composition.elements], 'nelements': len(structure.composition.elements), 'pretty_formula': structure.composition.reduced_formula, 'nsites': len(structure) } saving_option = fw_spec['saving_option'] if saving_option == 'gridfs': gridfs_msonables = {'structure': structure, 'structure_environments': se} elif saving_option == 'storefile': gridfs_msonables = None if 'se_prefix' in fw_spec: se_prefix = fw_spec['se_prefix'] if not se_prefix.isalpha(): raise ValueError('Prefix for structure_environments file is "{}" ' 'while it should be alphabetic'.format(se_prefix)) else: se_prefix = '' if se_prefix: se_rfilename = '{}_{}.json'.format(se_prefix, fw_spec['storefile_basename']) else: se_rfilename = '{}.json'.format(fw_spec['storefile_basename']) se_rfilepath = '{}/{}'.format(fw_spec['storefile_dirpath'], se_rfilename) storage_server = fw_spec['storage_server'] storage_server.put(localpath=json_file, remotepath=se_rfilepath, overwrite=True, makedirs=False) entry['structure_environments_file'] = se_rfilepath else: raise ValueError('Saving option is "{}" while it should be ' '"gridfs" or "storefile"'.format(saving_option)) criteria = {'identifier': identifier} if database.collection.find(criteria).count() == 1: database.update_entry(query=criteria, entry_update=entry, gridfs_msonables=gridfs_msonables) else: database.insert_entry(entry=entry, gridfs_msonables=gridfs_msonables)
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])
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