Skip to content

Repository to hold code and data for manuscript: "A Digital Tool for Liquid-Liquid Extraction Process Design"

License

Notifications You must be signed in to change notification settings

AstraZeneca/LLE_Digital_Tool

Repository files navigation

A Digital Tool for Liquid-Liquid Extraction Process Design

This is a repository to support the publication "A Digital Tool for Liquid-Liquid Extraction Process Design"

Below is a worked example for the code shared in this repository.

Use the "LLE_Digital_Tool_requirements.txt" file to create your virtual environment using pip and Python 3.10 or above.

For example:

pip install -r LLE_Digital_Tool_requirements.txt

Please feel free to amend the code to serve your respective data structures and objects.

Sections:

  1. Procedural Processing

Setting system and compounds dictionary objects. Loading solvents and compounds' physical properties data. Use of functions to get the data for each compound.

  1. Visualisations

Visualising speciation curves, fraction extracted, and extraction efficiency in each phase (aqueous or organic).

  1. Results

Generate results in tabulated form using defined functions.

  1. Contact

Contact Details for questions, comments, and suggestions.

Processing

The functions definitions can be found in the LLEFunctions.py file. Here is an example of their use.

First, let's load the data required:

# Define data objects using helper function
solvents, functional_groups, pred_pka, pivoted_solvents, structures = load_local_data()

Then, we need to define the system and compound dictionary objects:

system_panel_values = {
  "Aqueous Phase": 25,
  "Organic Phase": 25,
  "Total Volume": 50,
  "Aqueous Phase Proportion": 50,
  "Organic Phase Proportion": 50,
  "Relative Phase Volume": 1,
  "Extraction (Aqueous Phase) pH": 7,
  "Extraction Phase": "Aqueous",
  "Current Solvent": "2-MeTHF",
  "Number of compounds to separate": 2
}

compounds_panel_values = {
  "c0": {
    "Name": "PRODUCT 3",
    "Isolate": True,
    "Impurity": False,
    },
  "c1": {
    "Name": "AMINE 2",
    "Isolate": False,
    "Impurity": True,
    },
  "c2": {
    "Name": "ARYL BROMIDE 1",
    "Isolate": False,
    "Impurity": True,
    }
}

Now let's use the appropriate functions to get the data into the compounds dictionary object

for compound in compounds_panel_values.values():
    try:
        name = compound.get('Name').lower().title()  # get name to search for PPP data
        compound = RetrieveCompoundPhysChem(compound, pred_pka)  # add physchem data for compound to dictionary
        compound = RetrieveSmilesToMol(compound, structures)  # add mol data to dictionary
        compound['Vr'] = system_panel_values['Relative Phase Volume']
        logp_value = pivoted_solvents.loc[system_panel_values['Current Solvent'], name]
        compound['Kp'] = 10 ** logp_value
        compound['validity'] = True
    except:  # if any of the above fails, compound and system will not be valid
        compound['validity'] = False
        system_panel_values['Check'] = False

Let's call the object to make sure the necessary data have been added to each compound:

# check that it worked
compounds_panel_values
{'c0': {'Name': 'PRODUCT 3',
  'Isolate': True,
  'Impurity': False,
  'pka_data': True,
  'Forms': ['Product 3 (q= +3)',
   'Product 3 (q= +2)',
   'Product 3 (q= +1)',
   'Product 3 (neutral form)'],
  'pka_values': [4.0, 7.81, 9.24],
  'Kas': [0.0001, 1.5488166189124828e-08, 5.754399373371567e-10],
  'Neutral Form': 4,
  'Extraction': 'Extraction of Product 3 [Form 4]',
  'Structure': <rdkit.Chem.rdchem.Mol at 0x1ddde8cdbe0>,
  'Vr': 5.0,
  'Kp': 91754.88389387833,
  'validity': True},
 'c1': {'Name': 'AMINE 2',
  'Isolate': False,
  'Impurity': True,
  'pka_data': True,
  'Forms': ['Amine 2 (q= +2)', 'Amine 2 (q= +1)', 'Amine 2 (neutral form)'],
  'pka_values': [4.35, 9.27],
  'Kas': [4.466835921509635e-05, 5.370317963702532e-10],
  'Neutral Form': 3,
  'Extraction': 'Extraction of Amine 2 [Form 3]',
  'Structure': <rdkit.Chem.rdchem.Mol at 0x1ddde8cdee0>,
  'Vr': 5.0,
  'Kp': 0.4776670563746566,
  'validity': True},
 'c2': {'Name': 'ARYL BROMIDE 1',
  'Isolate': False,
  'Impurity': True,
  'pka_data': True,
  'Forms': ['Aryl Bromide 1 (q= +1)', 'Aryl Bromide 1 (neutral form)'],
  'pka_values': [9.03],
  'Kas': [9.332543007969924e-10],
  'Neutral Form': 2,
  'Extraction': 'Extraction of Aryl Bromide 1 [Form 2]',
  'Structure': <rdkit.Chem.rdchem.Mol at 0x1ddde8cd9a0>,
  'Vr': 5.0,
  'Kp': 301304.237796788,
  'validity': True}}

Visualisations

We can loop over the compounds dictionary object to visualise Ionic form fractions (speciation) and fraction extracted for each compound, as well as the extraction efficiency in the defined phase (currently set to "Aqueous").

# generate speciation curves
for compound in compounds_panel_values.values():
    if compound.get('Isolate'):
        fig_1 = PlotSpecies(compound)
        display(fig_1)

    elif compound.get('Impurity'):
        fig_1 = PlotSpecies(compound)
        display(fig_1)

# generate and plot fraction extracted curves
fig2 = PlotFractionExtracted(compounds_panel_values, system_panel_values)
display(fig2)

# generate and plot extraction efficiency
fig3 = PlotExtractionEfficiency(compounds_panel_values, system_panel_values)
display(fig3)

If you want to visualise the fraction extracted or the extraction efficiency in the organic phase, setting the appropriate key in the system dictionary is necessary, and can be done as follows:

system_panel_values['Extraction Phase'] = "Organic"

Now we can use the same functions for the visualisation:

# generate and plot fraction extracted curves
fig2 = PlotFractionExtracted(compounds_panel_values, system_panel_values)
display(fig2)

# generate and plot extraction efficiency
fig3 = PlotExtractionEfficiency(compounds_panel_values, system_panel_values)
display(fig3)

Results

If you would like to generate the results in tabular form you can use the following method

# Calculate extractions
_, results = CalculateExhaustiveExtractions(solvents, compounds_panel_values, system_panel_values)
results.head()
pH Solvent Product 3_logP Amine 2_logP Aryl Bromide 1_logP Extraction_eff_Product 3_aq Fraction_extracted_Product 3_aq Fraction_extracted_Amine 2_aq Fraction_extracted_Aryl Bromide 1_aq Volume_ratio
0 0.0 1,1,1-Trichloroethane 6.083062 -0.705796 6.639175 0.202480 1.0 1.0 0.995950 1.0
1 0.1 1,1,1-Trichloroethane 6.083062 -0.705796 6.639175 0.254640 1.0 1.0 0.994907 1.0
2 0.2 1,1,1-Trichloroethane 6.083062 -0.705796 6.639175 0.320151 1.0 1.0 0.993597 1.0
3 0.3 1,1,1-Trichloroethane 6.083062 -0.705796 6.639175 0.402379 1.0 1.0 0.991952 1.0
4 0.4 1,1,1-Trichloroethane 6.083062 -0.705796 6.639175 0.505512 1.0 1.0 0.989890 1.0
results.shape
(24252, 10)
# The same can be done looking at different volume ratios and calculating maximum extraction efficiency at each volume ratio:
# Define Valume Ratio limits
volume_ratios = (0.1, 5.0)

_, vr_results = CalculateExtractions(solvents, compounds_panel_values, system_panel_values, volume_ratios)
vr_results.head()
Product 3_logP Amine 2_logP Aryl Bromide 1_logP Max_eff_pH Max_ext_eff PRODUCT 3_fraction_org AMINE 2_fraction_org ARYL BROMIDE 1_fraction_org Volume_ratio
1,1,1-Trichloroethane 6.083062 -0.705796 6.639175 5.0 48.326346 0.990299 8.638695e-07 0.975994 0.1
1,1-Dichloroethane 6.417474 -0.202966 6.693888 4.9 48.044607 0.987121 2.085380e-06 0.973427 0.1
1,1-Dichloroethene 6.544878 -0.476505 7.012580 4.8 48.666290 0.989383 8.348416e-07 0.983769 0.1
1,2-Dichlorobenzene 5.912347 -0.879814 6.725937 5.1 48.692852 0.989438 7.569705e-07 0.984252 0.1
1,2-Dichloroethane 6.303173 -0.180649 6.589213 5.0 47.878858 0.983998 2.894641e-06 0.973146 0.1

Contact

For questions, comments and suggestions please contact: George Karageorgis

About

Repository to hold code and data for manuscript: "A Digital Tool for Liquid-Liquid Extraction Process Design"

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published