<jupyter_start><jupyter_text>Composition generationHere, we generate a set of quaternary oxide compositions using a modified `smact_test` function and then turn the results into a dataframe with features that can be read by a machine learning algorithm. For a fully-worked example see https://github.com/WMD-group/Solar_oxides_data<jupyter_code>### Imports ###
import smact
from smact import screening
from itertools import combinations, product
import multiprocessing
from pymatgen import Composition
import pandas as pd
from matminer.utils.conversions import str_to_composition
from matminer.featurizers.base import MultipleFeaturizer
from matminer.featurizers import composition as cf
# Define the elements we are interested in
all_el = smact.element_dictionary()
symbol_list = [k for k,i in all_el.items()]
do_not_want = ['H', 'He', 'B', 'C', 'O', 'Ne', 'Ar', 'Kr', 'Tc', 'Xe', 'Rn',
              'Ac', 'Th', 'Pa', 'U', 'Np', 'Pu', 'Am', 'Cm', 'Bk', 
              'Cf', 'Es', 'Fm', 'Md', 'No', 'Lr',
              'Ra', 'Fr', 'At', 'Po', 'Pm', 'Eu', 'Tb', 'Yb']
good_elements = [all_el[x] for x in symbol_list if x not in do_not_want]

all_el_combos = combinations(good_elements,3)

def smact_test(els):
    all_compounds = []
    elements = [e.symbol for e in els] + ['O']
    
    # Get Pauling electronegativities
    paul_a, paul_b, paul_c = els[0].pauling_eneg, els[1].pauling_eneg, els[2].pauling_eneg
    electronegativities = [paul_a, paul_b, paul_c, 3.44]
    
    # For each set of species (in oxidation states) apply both SMACT tests
    for ox_a, ox_b, ox_c in product(els[0].oxidation_states, 
                    els[1].oxidation_states, els[2].oxidation_states):      
        ox_states = [ox_a, ox_b, ox_c, -2]
        # Test for charge balance
        cn_e, cn_r = smact.neutral_ratios(ox_states, threshold = 8)
        if cn_e:
            # Electronegativity test
            electroneg_OK = screening.pauling_test(ox_states, electronegativities)
            if electroneg_OK:
                compound = tuple([elements,cn_r[0]])
                all_compounds.append(compound)
    return all_compounds<jupyter_output><empty_output><jupyter_text>Multiprocessing is used to speed things up (generation of all compositions takes ~40 minutes on a 4GHz Intel core i7 iMac).<jupyter_code>with multiprocessing.Pool() as p:
    result = p.map(smact_test, all_el_combos)
    
flat_list = [item for sublist in result for item in sublist]
print("Number of compositions: {0}".format(len(flat_list)))<jupyter_output><empty_output><jupyter_text>We turn our generated compositions into pretty formulas, again using multiprocessing. There should be ~1.1M unique formulas.<jupyter_code>def comp_maker(comp):
    form = []
    for el, ammt in zip(comp[0], comp[1]):
        form.append(el)
        form.append(ammt)
    form = ''.join(str(e) for e in form)
    pmg_form = Composition(form).reduced_formula
    return pmg_form

with multiprocessing.Pool() as p:
    pretty_formulas = p.map(comp_maker, flat_list)
    
unique_pretty_formulas = list(set(pretty_formulas))
print("Number of unique compositions formulas: {0}".format(len(unique_pretty_formulas)))
new_data = pd.DataFrame(unique_pretty_formulas).rename(columns={0: 'pretty_formula'})
new_data = new_data.drop_duplicates(subset = 'pretty_formula')
new_data.describe()
# Add descriptor columns
# this will take a little time as we have over 1 million rows
new_data['composition_obj'] = str_to_composition(new_data['pretty_formula'])
feature_calculators = MultipleFeaturizer([cf.Stoichiometry(), 
                                          cf.ElementProperty.from_preset("magpie"),
                                          cf.ValenceOrbital(props=['avg']), 
                                          cf.IonProperty(fast=True),
                                          cf.BandCenter(), cf.AtomicOrbitals()])

feature_labels = feature_calculators.feature_labels()
feature_calculators.featurize_dataframe(new_data, col_id='composition_obj');
# Save as .csv file 
new_data.to_csv('All_oxide_comps_dataframe_featurized.csv', chunksize=10000)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.10941660614863229, 'fraction_numerical': 0.007262164124909223, 'mean_word_length': 3.6901248581157775, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 13, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '3', 'dir': 'jupyter-structured-clean-dedup', 'id': '202526', 'license': 'MIT', 'n_tokens_mistral': 1407, 'n_tokens_neox': 1338, 'n_words': 344, 'path': 'Solar_oxides/SolarOxides.ipynb', 'repo_name': 'WMD-group/SMACT_workflows', 'size': '4131'}