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.

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