def run_task(self, fw_spec): db = SPStructuresMongoAdapter.auto_load() tstructs = [] species = fw_spec['species'] t = fw_spec['threshold'] for p in SubstitutionPredictor(threshold=t).list_prediction(species): subs = p['substitutions'] if len(set(subs.values())) < len(species): continue st = SubstitutionTransformation(subs) target = map(str, subs.keys()) for snl in db.get_snls(target): ts = TransformedStructure.from_snl(snl) ts.append_transformation(st) if ts.final_structure.charge == 0: tstructs.append(ts) transmuter = StandardTransmuter(tstructs) f = RemoveDuplicatesFilter(structure_matcher=StructureMatcher( comparator=ElementComparator(), primitive_cell=False)) transmuter.apply_filter(f) results = [] for ts in transmuter.transformed_structures: results.append(ts.to_snl([]).to_dict) submissions = SPSubmissionsMongoAdapter.auto_load() submissions.insert_results(fw_spec['submission_id'], results)
def test_filter(self): transmuter = StandardTransmuter.from_structures(self._struct_list) fil = RemoveDuplicatesFilter() transmuter.apply_filter(fil) out = self._sm.group_structures(transmuter.transformed_structures) self.assertEqual( self._sm.find_indexes(transmuter.transformed_structures, out), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
def pred_from_structures(self, target_species, structures_list, remove_duplicates=True, remove_existing=False): """ performs a structure prediction targeting compounds containing all of the target_species, based on a list of structure (those structures can for instance come from a database like the ICSD). It will return all the structures formed by ionic substitutions with a probability higher than the threshold Notes: If the default probability model is used, input structures must be oxidation state decorated. See AutoOxiStateDecorationTransformation This method does not change the number of species in a structure. i.e if the number of target species is 3, only input structures containing 3 species will be considered. Args: target_species: a list of species with oxidation states e.g., [Specie('Li',1),Specie('Ni',2), Specie('O',-2)] structures_list: a list of dictionnary of the form {'structure':Structure object ,'id':some id where it comes from} the id can for instance refer to an ICSD id. remove_duplicates: if True, the duplicates in the predicted structures will be removed remove_existing: if True, the predicted structures that already exist in the structures_list will be removed Returns: a list of TransformedStructure objects. """ target_species = get_el_sp(target_species) result = [] transmuter = StandardTransmuter([]) if len(list(set(target_species) & set(self.get_allowed_species()))) \ != len(target_species): raise ValueError("the species in target_species are not allowed " + "for the probability model you are using") for permut in itertools.permutations(target_species): for s in structures_list: # check if: species are in the domain, # and the probability of subst. is above the threshold els = s['structure'].composition.elements if len(els) == len(permut) and len(list(set(els) & set(self.get_allowed_species()))) == \ len(els) and self._sp.cond_prob_list(permut, els) > self._threshold: clean_subst = { els[i]: permut[i] for i in range(0, len(els)) if els[i] != permut[i] } if len(clean_subst) == 0: continue transf = SubstitutionTransformation(clean_subst) if Substitutor._is_charge_balanced( transf.apply_transformation(s['structure'])): ts = TransformedStructure(s['structure'], [transf], history=[{ "source": s['id'] }], other_parameters={ 'type': 'structure_prediction', 'proba': self._sp.cond_prob_list( permut, els) }) result.append(ts) transmuter.append_transformed_structures([ts]) if remove_duplicates: transmuter.apply_filter( RemoveDuplicatesFilter(symprec=self._symprec)) if remove_existing: # Make the list of structures from structures_list that corresponds to the # target species chemsys = list(set([sp.symbol for sp in target_species])) structures_list_target = [ st['structure'] for st in structures_list if Substitutor._is_from_chemical_system( chemsys, st['structure']) ] transmuter.apply_filter( RemoveExistingFilter(structures_list_target, symprec=self._symprec)) return transmuter.transformed_structures
def test_to_from_dict(self): fil = RemoveDuplicatesFilter() d = fil.as_dict() self.assertIsInstance(RemoveDuplicatesFilter().from_dict(d), RemoveDuplicatesFilter)
def test_filter(self): transmuter = StandardTransmuter.from_structures(self._struct_list) fil = RemoveDuplicatesFilter() transmuter.apply_filter(fil) self.assertEqual(len(transmuter.transformed_structures), 11)
def pred_from_structures(self, target_species, structures_list, remove_duplicates=True): """ performs a structure prediction targeting compounds containing the target_species and based on a list of structure (those structures can for instance come from a database like the ICSD). It will return all the structures formed by ionic substitutions with a probability higher than the threshold Args: target_species: a list of species with oxidation states e.g., [Specie('Li',1),Specie('Ni',2), Specie('O',-2)] structures_list: a list of dictionnary of the form {'structure':Structure object ,'id':some id where it comes from} the id can for instance refer to an ICSD id Returns: a list of TransformedStructure objects. """ result = [] transmuter = StandardTransmuter([]) if len(list(set(target_species) & set(self.get_allowed_species()))) \ != len(target_species): raise ValueError("the species in target_species are not allowed" + "for the probability model you are using") for permut in itertools.permutations(target_species): for s in structures_list: #check if: species are in the domain, #and the probability of subst. is above the threshold els = s['structure'].composition.elements if len(els) == len(permut) and \ len(list(set(els) & set(self.get_allowed_species()))) == \ len(els) and self._sp.cond_prob_list(permut, els) > \ self._threshold: clean_subst = {els[i]: permut[i] for i in xrange(0, len(els)) if els[i] != permut[i]} if len(clean_subst) == 0: continue transf = SubstitutionTransformation(clean_subst) if Substitutor._is_charge_balanced( transf.apply_transformation(s['structure'])): ts = TransformedStructure( s['structure'], [transf], history=[s['id']], other_parameters={ 'type': 'structure_prediction', 'proba': self._sp.cond_prob_list(permut, els)} ) result.append(ts) transmuter.append_transformed_structures([ts]) if remove_duplicates: transmuter.apply_filter(RemoveDuplicatesFilter( symprec=self._symprec)) return transmuter.transformed_structures
def make_all_substituted_configurations(self): substituted_count = 0 while substituted_count < self.number_of_substitutions: self.substituted_sites = [] unique = 0 _list_holder = copy.deepcopy(self.supercells) self.supercells = [] if substituted_count < 2: for k, supercell in enumerate(_list_holder): for extra_doped_supercell in self.make_one_substitution( supercell): self.supercells.append(extra_doped_supercell) #if self.write_vasp: # dir_name = "SC_" + str(self.sc_size[0]) + "_" + str(self.sc_size[1]) + "_" + str( # self.sc_size[2]) + '_' + self.prefix + '_' + str(substituted_count + 1) + "_str_" + str( # len(self.supercells)) # self._write_vasp_files(extra_doped_supercell, dir_name=dir_name) # unique += 1 else: import random filter = RemoveDuplicatesFilter(symprec=1e-5) extra_doped_supercells = [] doped_sites = [] if len(_list_holder) > self.throttle: _list_holder = random.choices(_list_holder, k=self.throttle) for counter, supercell in enumerate(_list_holder): extra_doped_supercells += self.make_one_substitution( supercell) for s in extra_doped_supercells: __site_no = [] for no, site in enumerate(s.__dict__['_sites']): if site.__dict__["_species"] == Composition( self.atom_substitute_to): __site_no.append(no) __site_no = list(sorted(__site_no)) if __site_no not in doped_sites: doped_sites.append(__site_no) self.supercells.append(s) print(len(self.supercells)) if self.max_structures is not None: if len(self.supercells) > self.max_structures: import random self.supercells = random.sample(self.supercells, self.max_structures) if self.write_vasp: for i, cell in enumerate(self.supercells): dir_name = "SC_" + str(self.sc_size[0]) + "_" + str( self.sc_size[1]) + "_" + str( self.sc_size[2]) + '_' + self.prefix + '_' + str( substituted_count + 1) + "_str_" + str(i) self._write_vasp_files(cell, dir_name=dir_name) unique += 1 print("number of dopants:" + str(substituted_count + 1) + ' number of configurations:' + str(unique)) substituted_count += 1 #self.supercells = [map_pymatgen_IStructure_to_crystal(s) for s in self.supercells] return self.supercells