Example #1
0
    def find_all_chemsys(original_species, threshold=0.0001, max_num_subs=5):
        """
        Determines chemical systems to consider via data-mined ionic substitution probabilities (see lambda.json)

        Args:
            original_species (list): a list of species, e.g. [Specie('Li',1), Specie('Ni',2), Specie('O',-2)]
            threshold (float): Probability threshold for generating ionic substitutions. Defaults to 0.0001
            max_num_subs (int): Limits maximum number of substitutions wanted. Defaults to 5

        Returns:
            (set): A set of all chemical systems to predict from
        """
        num_species = len(original_species)

        sub_elems = set()
        for specie in original_species:
            subs = SubstitutionPredictor(threshold=threshold).list_prediction(
                [specie])

            # sort and cap number of substitutions
            subs.sort(key=lambda x: x["probability"], reverse=True)
            subs = subs[0:max_num_subs]

            for sub in subs:
                for new_species in sub["substitutions"]:
                    sub_elems.add(new_species.element)

        all_chemsys = set()
        for chemsys in combinations(sub_elems, num_species):
            all_chemsys.add("-".join(sorted([str(el) for el in chemsys])))

        return all_chemsys
Example #2
0
    def substitution_structures(self, mp_struct, mpid):
        
        ''' Predicts substituted compounds from a given Materials Project structure (mp_struct) and ID (mpid) '''
        ''' flat_predictions: a list of predicted structures as pymatgen.alchemy.materials.TransformedStructure objects '''
        
        auto_oxi = AutoOxiStateDecorationTransformation() #initialize the automatic oxidation state transformation
        structures = []
        
        try:
            oxi_struct = auto_oxi.apply_transformation(mp_struct) # get oxidized reference structure
            subs = SubstitutionPredictor().composition_prediction(oxi_struct.composition) # from a given charge-balanced
            trial_subs = [list(sub['substitutions'].keys()) for sub in subs] # returns the potential substitutions
            sbr = Substitutor()
            
            for sub in trial_subs:
                run = True
                
                for specie in sub:
                    if str(specie.element) not in self.elements:
                        run = False

                if run == True:
                    structs = sbr.pred_from_structures(sub, [{'structure':oxi_struct, 'id':mpid}])
                    structures.append(structs)
           
        except:
            pass
        
        flat_predictions = [structure for substitution in structures for structure in substitution]
        
        return flat_predictions
def get_dopants_from_substitution_probabilities(structure,
                                                num_dopants=5,
                                                threshold=0.001,
                                                match_oxi_sign=False):
    """
    Get dopant suggestions based on substitution probabilities.

    Args:
        structure (Structure): A pymatgen structure decorated with
            oxidation states.
        num_dopants (int): The number of suggestions to return for
            n- and p-type dopants.
        threshold (float): Probability threshold for substitutions.
        match_oxi_sign (bool): Whether to force the dopant and original species
            to have the same sign of oxidation state. E.g. If the original site
            is in a negative charge state, then only negative dopants will be
            returned.

    Returns:
        (dict): Dopant suggestions, given as a dictionary with keys "n_type" and
        "p_type". The suggestions for each doping type are given as a list of
        dictionaries, each with they keys:

        - "probability": The probability of substitution.
        - "dopant_species": The dopant species.
        - "original_species": The substituted species.
    """
    els_have_oxi_states = [hasattr(s, "oxi_state") for s in structure.species]

    if not all(els_have_oxi_states):
        raise ValueError(
            "All sites in structure must have oxidation states to "
            "predict dopants.")

    sp = SubstitutionPredictor(threshold=threshold)

    subs = [sp.list_prediction([s]) for s in set(structure.species)]
    subs = [{
        'probability': pred['probability'],
        'dopant_species': list(pred['substitutions'].keys())[0],
        'original_species': list(pred['substitutions'].values())[0]
    } for species_preds in subs for pred in species_preds]
    subs.sort(key=lambda x: x['probability'], reverse=True)

    return _get_dopants(subs, num_dopants, match_oxi_sign)
Example #4
0
def get_dopants_from_substitution_probabilities(structure, num_dopants=5,
                                                threshold=0.001,
                                                match_oxi_sign=False):
    """
    Get dopant suggestions based on substitution probabilities.

    Args:
        structure (Structure): A pymatgen structure decorated with
            oxidation states.
        num_dopants (int): The number of suggestions to return for
            n- and p-type dopants.
        threshold (float): Probability threshold for substitutions.
        match_oxi_sign (bool): Whether to force the dopant and original species
            to have the same sign of oxidation state. E.g. If the original site
            is in a negative charge state, then only negative dopants will be
            returned.

    Returns:
        (dict): Dopant suggestions, given as a dictionary with keys "n_type" and
        "p_type". The suggestions for each doping type are given as a list of
        dictionaries, each with they keys:

        - "probability": The probability of substitution.
        - "dopant_species": The dopant species.
        - "original_species": The substituted species.
    """
    els_have_oxi_states = [hasattr(s, "oxi_state") for s in structure.species]

    if not all(els_have_oxi_states):
        raise ValueError("All sites in structure must have oxidation states to "
                         "predict dopants.")

    sp = SubstitutionPredictor(threshold=threshold)

    subs = [sp.list_prediction([s]) for s in set(structure.species)]
    subs = [{'probability': pred['probability'],
             'dopant_species': list(pred['substitutions'].keys())[0],
             'original_species': list(pred['substitutions'].values())[0]}
            for species_preds in subs for pred in species_preds]
    subs.sort(key=lambda x: x['probability'], reverse=True)

    return _get_dopants(subs, num_dopants, match_oxi_sign)
    def test_prediction(self):
        sp = SubstitutionPredictor(threshold = 8e-3)
        result = sp.list_prediction(['Na+', 'Cl-'], to_this_composition = True)[5]
        cprob = sp.p.cond_prob_list(result['substitutions'].keys(),
                                    result['substitutions'].values())
        self.assertAlmostEqual(result['probability'], cprob)
        self.assertEqual(set(result['substitutions'].values()), set(['Na+', 'Cl-']))

        result = sp.list_prediction(['Na+', 'Cl-'], to_this_composition = False)[5]
        cprob = sp.p.cond_prob_list(result['substitutions'].keys(),
                                    result['substitutions'].values())
        self.assertAlmostEqual(result['probability'], cprob)
        self.assertNotEqual(set(result['substitutions'].values()),
                            set(['Na+', 'Cl-']))

        c = Composition({'Ag2+' : 1, 'Cl-' : 2})
        result = sp.composition_prediction(c, to_this_composition = True)[2]
        self.assertEqual(set(result['substitutions'].values()), set(c.elements))
        result = sp.composition_prediction(c, to_this_composition = False)[2]
        self.assertEqual(set(result['substitutions'].keys()), set(c.elements))
class SubstitutionPredictorTransformation(AbstractTransformation):
    """
    This transformation takes a structure and uses the structure
    prediction module to find likely site substitutions.

    Args:
        threshold: Threshold for substitution.
        **kwargs: Args for SubstitutionProbability class lambda_table, alpha
    """
    def __init__(self, threshold=1e-2, **kwargs):
        self.kwargs = kwargs
        self.threshold = threshold
        self._substitutor = SubstitutionPredictor(threshold=threshold,
                                                  **kwargs)

    def apply_transformation(self, structure, return_ranked_list=False):
        if not return_ranked_list:
            raise ValueError("SubstitutionPredictorTransformation doesn't"
                             " support returning 1 structure")

        preds = self._substitutor.composition_prediction(
            structure.composition, to_this_composition=False)
        preds.sort(key=lambda x: x['probability'], reverse=True)

        outputs = []
        for pred in preds:
            st = SubstitutionTransformation(pred['substitutions'])
            output = {
                'structure': st.apply_transformation(structure),
                'probability': pred['probability'],
                'threshold': self.threshold,
                'substitutions': {}
            }
            # dictionary keys have to be converted to strings for JSON
            for key, value in pred['substitutions'].items():
                output['substitutions'][str(key)] = str(value)
            outputs.append(output)
        return outputs

    def __str__(self):
        return "SubstitutionPredictorTransformation"

    def __repr__(self):
        return self.__str__()

    @property
    def inverse(self):
        return None

    @property
    def is_one_to_many(self):
        return True
class SubstitutionPredictorTransformation(AbstractTransformation):
    """
    This transformation takes a structure and uses the structure
    prediction module to find likely site substitutions.

    Args:
        threshold: Threshold for substitution.
        **kwargs: Args for SubstitutionProbability class lambda_table, alpha
    """

    def __init__(self, threshold=1e-2, scale_volumes=True, **kwargs):
        self.kwargs = kwargs
        self.threshold = threshold
        self.scale_volumes = scale_volumes
        self._substitutor = SubstitutionPredictor(threshold=threshold,
                                                  **kwargs)

    def apply_transformation(self, structure, return_ranked_list=False):
        if not return_ranked_list:
            raise ValueError("SubstitutionPredictorTransformation doesn't"
                             " support returning 1 structure")

        preds = self._substitutor.composition_prediction(
            structure.composition, to_this_composition=False)
        preds.sort(key=lambda x: x['probability'], reverse=True)

        outputs = []
        for pred in preds:
            st = SubstitutionTransformation(pred['substitutions'])
            output = {'structure': st.apply_transformation(structure),
                      'probability': pred['probability'],
                      'threshold': self.threshold, 'substitutions': {}}
            
            # dictionary keys have to be converted to strings for JSON
            for key, value in pred['substitutions'].items():
                output['substitutions'][str(key)] = str(value)
            outputs.append(output)
        return outputs

    def __str__(self):
        return "SubstitutionPredictorTransformation"

    def __repr__(self):
        return self.__str__()

    @property
    def inverse(self):
        return None

    @property
    def is_one_to_many(self):
        return True
Example #8
0
    def test_prediction(self):
        sp = SubstitutionPredictor(threshold=8e-3)
        result = sp.list_prediction(["Na+", "Cl-"], to_this_composition=True)[5]
        cprob = sp.p.cond_prob_list(result["substitutions"].keys(), result["substitutions"].values())
        self.assertAlmostEqual(result["probability"], cprob)
        self.assertEqual(set(result["substitutions"].values()), {"Na+", "Cl-"})

        result = sp.list_prediction(["Na+", "Cl-"], to_this_composition=False)[5]
        cprob = sp.p.cond_prob_list(result["substitutions"].keys(), result["substitutions"].values())
        self.assertAlmostEqual(result["probability"], cprob)
        self.assertNotEqual(set(result["substitutions"].values()), {"Na+", "Cl-"})

        c = Composition({"Ag2+": 1, "Cl-": 2})
        result = sp.composition_prediction(c, to_this_composition=True)[2]
        self.assertEqual(set(result["substitutions"].values()), set(c.elements))
        result = sp.composition_prediction(c, to_this_composition=False)[2]
        self.assertEqual(set(result["substitutions"].keys()), set(c.elements))
    def test_prediction(self):
        sp = SubstitutionPredictor(threshold=8e-3)
        result = sp.list_prediction(['Na+', 'Cl-'], to_this_composition=True)[5]
        cprob = sp.p.cond_prob_list(result['substitutions'].keys(),
                                    result['substitutions'].values())
        self.assertAlmostEqual(result['probability'], cprob)
        self.assertEqual(set(result['substitutions'].values()), set(['Na+', 'Cl-']))

        result = sp.list_prediction(['Na+', 'Cl-'], to_this_composition=False)[5]
        cprob = sp.p.cond_prob_list(result['substitutions'].keys(),
                                    result['substitutions'].values())
        self.assertAlmostEqual(result['probability'], cprob)
        self.assertNotEqual(set(result['substitutions'].values()),
                            set(['Na+', 'Cl-']))

        c = Composition({'Ag2+': 1, 'Cl-': 2})
        result = sp.composition_prediction(c, to_this_composition=True)[2]
        self.assertEqual(set(result['substitutions'].values()), set(c.elements))
        result = sp.composition_prediction(c, to_this_composition=False)[2]
        self.assertEqual(set(result['substitutions'].keys()), set(c.elements))
 def __init__(self, threshold=1e-2, **kwargs):
     self.kwargs = kwargs
     self.threshold = threshold
     self._substitutor = SubstitutionPredictor(threshold=threshold,
                                               **kwargs)
 def __init__(self, threshold=1e-2, **kwargs):
     self.kwargs = kwargs
     self.threshold = threshold
     self._substitutor = SubstitutionPredictor(threshold=threshold,
                                               **kwargs)
Example #12
0
 def __init__(self, threshold=1e-2, scale_volumes=True, **kwargs):
     self.kwargs = kwargs
     self.threshold = threshold
     self.scale_volumes = scale_volumes
     self._substitutor = SubstitutionPredictor(threshold=threshold,
                                               **kwargs)