diff --git a/legacy_code/tim_baybe-inhibitor.ipynb b/legacy_code/tim_baybe-inhibitor.ipynb new file mode 100644 index 0000000..4f8b481 --- /dev/null +++ b/legacy_code/tim_baybe-inhibitor.ipynb @@ -0,0 +1,1057 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Introduction" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This project will focus on exploring the capabilities of Bayesian optimization, specifically employing BayBE, in the discovery of novel corrosion inhibitors for materials design. Initially, we will work with a randomly chosen subset from a comprehensive database of electrochemical responses of small organic molecules. Our goal is to assess how Bayesian optimization can speed up the screening process across the design space to identify promising compounds. We will compare different strategies for incorporating alloy information, while optimizing the experimental parameters with respect to the inhibitive performance of the screened compounds." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Initialization" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Loading libraries and data files:" + ] + }, + { + "cell_type": "code", + "execution_count": 68, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import numpy as np\n", + "from baybe import Campaign\n", + "\n", + "df_AA2024 = pd.read_excel('../data/averaged_filtered_AA2024.xlsx')\n", + "df_AA1000 = pd.read_excel('../data/averaged_filtered_AA1000.xlsx')\n", + "df_Al = pd.read_excel('../data/averaged_filtered_Al.xlsx')\n", + "\n", + "df_active = df_AA2024\n", + "lookup = df_active" + ] + }, + { + "cell_type": "code", + "execution_count": 69, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "\n", + "def random_subsample(df, num_samples):\n", + " np.random.seed(42)\n", + " indices = np.random.choice(df.index, num_samples, replace=False)\n", + " subsampled_df = df.loc[indices]\n", + " return subsampled_df " + ] + }, + { + "cell_type": "code", + "execution_count": 70, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
SMILESTime_hpHInhib_Concentrat_MSalt_Concentrat_MEfficiency
0C(=O)(C(=O)[O-])[O-]24.04.00.00100.1020.00
1C(=O)(C(=O)[O-])[O-]24.07.00.00050.0512.35
2C(=O)(C(=O)[O-])[O-]24.010.00.00100.1020.00
3C(C(=O)[O-])C(CC(=O)[O-])(C(=O)[O-])O24.04.00.00100.1030.00
4C(C(=O)[O-])C(CC(=O)[O-])(C(=O)[O-])O24.07.00.00050.05-23.95
\n", + "
" + ], + "text/plain": [ + " SMILES Time_h pH Inhib_Concentrat_M \\\n", + "0 C(=O)(C(=O)[O-])[O-] 24.0 4.0 0.0010 \n", + "1 C(=O)(C(=O)[O-])[O-] 24.0 7.0 0.0005 \n", + "2 C(=O)(C(=O)[O-])[O-] 24.0 10.0 0.0010 \n", + "3 C(C(=O)[O-])C(CC(=O)[O-])(C(=O)[O-])O 24.0 4.0 0.0010 \n", + "4 C(C(=O)[O-])C(CC(=O)[O-])(C(=O)[O-])O 24.0 7.0 0.0005 \n", + "\n", + " Salt_Concentrat_M Efficiency \n", + "0 0.10 20.00 \n", + "1 0.05 12.35 \n", + "2 0.10 20.00 \n", + "3 0.10 30.00 \n", + "4 0.05 -23.95 " + ] + }, + "execution_count": 70, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df_active.head()" + ] + }, + { + "cell_type": "code", + "execution_count": 71, + "metadata": {}, + "outputs": [], + "source": [ + "unique_smiles = df_active.SMILES.unique()\n", + "unique_times = df_active.Time_h.unique()\n", + "unique_pH = df_active.pH.unique()\n", + "unique_inhib_conc = df_active.Inhib_Concentrat_M.unique()\n", + "unique_salt_conc = df_active.Salt_Concentrat_M.unique()\n", + "\n", + "time_min, time_max = df_active.Time_h.min(), df_active.Time_h.max()\n", + "pH_min, pH_max = df_active.pH.min(), df_active.pH.max()\n", + "inhib_conc_min, inhib_conc_max = df_active.Inhib_Concentrat_M.min(), df_active.Inhib_Concentrat_M.max()\n", + "salt_conc_min, salt_conc_max = df_active.Salt_Concentrat_M.min(), df_active.Salt_Concentrat_M.max()\n", + "efficiency_min, efficiency_max = df_active.Efficiency.min(), df_active.Efficiency.max()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Data Processing" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Data Anaylsis" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Bayesian Optimization" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 72, + "metadata": {}, + "outputs": [], + "source": [ + "from baybe import Campaign\n", + "\n", + "from baybe.targets import NumericalTarget\n", + "from baybe.objective import Objective\n", + "from baybe.searchspace import SearchSpace\n", + "from baybe.parameters import NumericalDiscreteParameter\n", + "from baybe.parameters import SubstanceParameter\n", + "\n", + "import matplotlib.pyplot as plt\n", + "import seaborn as sns\n", + "\n", + "def list_to_dict(input_list):\n", + " return {item: item for item in input_list}\n", + "\n", + "smiles_dict =list_to_dict(unique_smiles)\n", + "\n", + "\n", + "target = NumericalTarget(name=\"Efficiency\", mode=\"MAX\", bounds=(efficiency_min, efficiency_max), transformation=\"LINEAR\")\n", + "objective = Objective(mode=\"SINGLE\", targets=[target])\n", + "\n", + "\n", + "\n", + "parameters = [\n", + "NumericalDiscreteParameter(\n", + " name=\"Time_h\",\n", + " values=df_active['Time_h'].unique(),\n", + " # tolerance = 0.004, assume certain experimental noise for each parameter measurement?\n", + "),\n", + "NumericalDiscreteParameter(\n", + " name=\"pH\",\n", + " values=df_active['pH'].unique(),\n", + " # tolerance = 0.004\n", + " ), \n", + "NumericalDiscreteParameter( # Set this as continuous, the values seem quite small?\n", + " name=\"Inhib_Concentrat_M\",\n", + " values= df_active['Inhib_Concentrat_M'].unique(),\n", + " # tolerance = 0.004\n", + " ),\n", + "NumericalDiscreteParameter(\n", + " name=\"Salt_Concentrat_M\",\n", + " values=df_active['Salt_Concentrat_M'].unique(),\n", + " # tolerance = 0.004\n", + " ),\n", + "SubstanceParameter(\n", + " name=\"SMILES\",\n", + " data=smiles_dict,\n", + " encoding=\"MORGAN_FP\", # optional\n", + " decorrelate=0.7, # optional\n", + " ) \n", + " ]\n", + "# searchspace = SubspaceDiscrete.from_product(parameters=parameters)\n", + "df_no_target = df_active.drop('Efficiency', axis=1)\n", + "\n", + "searchspace = SearchSpace.from_dataframe(df = df_no_target, parameters=parameters)\n", + "\n", + "campaign = Campaign(\n", + " searchspace=searchspace, # Required\n", + " objective=objective, # Required\n", + " # recommender=recommender, # Optional\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 73, + "metadata": {}, + "outputs": [], + "source": [ + "from baybe.recommenders import RandomRecommender\n", + "\n", + "campaign_rand = Campaign(\n", + " searchspace=searchspace,\n", + " recommender=RandomRecommender(),\n", + " objective=objective,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 74, + "metadata": {}, + "outputs": [], + "source": [ + "substance_encodings = [\"MORDRED\", \"RDKIT\", \"MORGAN_FP\"]\n", + "scenarios = {\n", + " encoding: Campaign(\n", + " searchspace=SearchSpace.from_dataframe(df = df_no_target,\n", + " parameters=[\n", + " NumericalDiscreteParameter(\n", + " name=\"Time_h\",\n", + " values=df_active[\"Time_h\"].unique(),\n", + " # tolerance = 0.004, assume certain experimental noise for each parameter measurement?\n", + " ),\n", + " NumericalDiscreteParameter(\n", + " name=\"pH\",\n", + " values=df_active[\"pH\"].unique(),\n", + " # tolerance = 0.004\n", + " ),\n", + " NumericalDiscreteParameter( # Set this as continuous, the values seem quite small?\n", + " name=\"Inhib_Concentrat_M\",\n", + " values=df_active[\"Inhib_Concentrat_M\"].unique(),\n", + " # tolerance = 0.004\n", + " ),\n", + " NumericalDiscreteParameter(\n", + " name=\"Salt_Concentrat_M\",\n", + " values=df_active[\"Salt_Concentrat_M\"].unique(),\n", + " # tolerance = 0.004\n", + " ),\n", + " SubstanceParameter(\n", + " name=\"SMILES\",\n", + " data=smiles_dict,\n", + " encoding=encoding, # optional\n", + " decorrelate=0.7, # optional\n", + " ),\n", + " ]\n", + " ),\n", + " objective=objective,\n", + " )\n", + " for encoding in substance_encodings\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 75, + "metadata": {}, + "outputs": [], + "source": [ + "scenarios.update({\"Random Baseline\": campaign_rand})" + ] + }, + { + "cell_type": "code", + "execution_count": 76, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|##########| 4/4 [01:05<00:00, 16.27s/it]\n" + ] + } + ], + "source": [ + "from baybe.simulation import simulate_experiment\n", + "from baybe.simulation import simulate_scenarios\n", + "\n", + "\n", + "BATCH_SIZE = 1\n", + "N_DOE_ITERATIONS = 50\n", + "N_MC_ITERATIONS = 10\n", + "\n", + "# results = simulate_experiment(\n", + "# campaign,\n", + "# df_AA2024,\n", + "# initial_data=initial_dataset,\n", + "# batch_size=BATCH_SIZE,\n", + "# n_doe_iterations=N_DOE_ITERATIONS,\n", + "# impute_mode=\"best\",\n", + "# )\n", + "initial_dataset = random_subsample(df_active, 5)\n", + "\n", + "results = simulate_scenarios(\n", + " scenarios,\n", + " lookup,\n", + " initial_data=[initial_dataset],\n", + " batch_size=BATCH_SIZE,\n", + " n_doe_iterations=N_DOE_ITERATIONS,\n", + " # n_mc_iterations=N_MC_ITERATIONS,\n", + " impute_mode=\"best\",\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 77, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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Dw94enqiU6dOGD16NI4fP47U1NQy91vy4eTkpBXj7OwMDw8P1KtXD7169cLPP/+M0NBQTJgwAUlJSXodz5qOxY6RabLZoExEpkEIgcycvEo/snPzIYRAdm5+mc8r+yh5mqgqwsLCsH79evn5119/jVGjRsnPHzx4gD/++AOvv/46bP81vYeHhwdCQ0Pxww8/lLl/IQQOHTqEf/75p1KT2SkUCrz55puIjY0t99TSnTt3sG3bNlhYWMDCwqKyb7NCkydPRlpaWpkFGRXjPDtGxkkFichUZOXmo8ncP6r0mi6BtfDZ0Nb44UQcBrf3wavfnsShqHtV2sbl93rDzqrqf46GDx+OmTNnIjY2FgBw+PBhbN68Gfv37wcAREVFQQiBoKCgMl8fFBSEpKQk3L17F3Xq1AEArFq1CmvXrkVOTg5yc3NhY2ODiRMnViqfxo0bAyjo63nssccAACkpKXBwcCgoJAtnqp44cSLs7e21Xlu035K++OILhIaGVnqfVD4WO0ZWPKkgix0ievQcirqHH07EYWy3BvjiQHSVCx191K5dG/369cOGDRsghEC/fv1Qq1atUnFVGTkKDQ3FrFmzkJSUhHnz5qFTp07o1KlTpV5btJ+SM1E7Ojri9OnTyM3Nxc6dO/H9999jwYIF5e63JHd3d532SaWx2DGy4kkF2aBMRMZla2mBy+/1rtJrFJIEa6UCufkajOlaHyM61YOmiqelbC11P6UTFhaGCRMmAABWrlyptS4gIACSJCEiIgIDBw4s9dqIiAi4uLigdu3a8jKVSoWAgAAAwI8//oiAgAB07NgRISEh/5lLREQEAMDf319eplAo5O0FBQUhOjoar732Gr777jut15bcb1WUtU8qjT07RlY8qSDveE5ExiVJEuyslFV62FhaQJIkWFooCi7ZtrSo8jb0GZXo06ePfMqpd2/tQs3NzQ1PPvkkVq1apXXVFgAkJibi+++/x+DBg8vdv4ODA958801MmzbtP0eHNBoNVqxYAX9/f60G6X97++238cMPP+D06dOVfIcVW758OZycnCpVjJkzFjtGVjypIEd2iIiqysLCAhEREbh8+XKZTb+ff/451Go1evfujYMHDyIuLg67du3Ck08+CW9v7zJPKZU0duxYXLlyBVu2bNFafv/+fSQmJuLatWv45ZdfEBISguPHj2PdunUVNh/7+Phg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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "max_efficiency = lookup[\"Efficiency\"].max()\n", + "# plot_results = results[results['Scenario'].isin(['Mordred', 'Morgan', 'RDKIT'])]\n", + "\n", + "sns.lineplot(\n", + " data=results, x=\"Num_Experiments\", y=\"Efficiency_CumBest\", hue=\"Scenario\", marker=\"x\"\n", + ")\n", + "plt.plot([0.5, N_DOE_ITERATIONS+0.5], [max_efficiency, max_efficiency], \"--r\")\n", + "plt.legend(loc=\"lower right\")\n", + "import matplotlib.pyplot as plt\n", + "\n", + "plt.xlim(0, N_DOE_ITERATIONS+1)\n", + "plt.savefig(\"./AA1000_simulation_10MC_50exp_1batch.png\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Search Space" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Target & Objective" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Recommender" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Benchmarking" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Transfer Learning" + ] + }, + { + "cell_type": "code", + "execution_count": 110, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import sys\n", + "from pathlib import Path\n", + "\n", + "import numpy as np\n", + "import pandas as pd\n", + "import seaborn as sns\n", + "from botorch.test_functions.synthetic import Hartmann\n", + "\n", + "from baybe import Campaign\n", + "from baybe.objective import Objective\n", + "from baybe.parameters import NumericalDiscreteParameter, TaskParameter, CategoricalParameter\n", + "from baybe.searchspace import SearchSpace\n", + "from baybe.simulation import simulate_scenarios, simulate_transfer_learning\n", + "from baybe.targets import NumericalTarget\n", + "from baybe.utils.botorch_wrapper import botorch_function_wrapper\n", + "from baybe.utils.plotting import create_example_plots\n" + ] + }, + { + "cell_type": "code", + "execution_count": 111, + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "\n", + "SMOKE_TEST = \"SMOKE_TEST\" in os.environ # reduce the problem complexity in CI pipelines\n", + "DIMENSION = 3 # input dimensionality of the test function\n", + "BATCH_SIZE = 1 # batch size of recommendations per DOE iteration\n", + "N_MC_ITERATIONS = 2 if SMOKE_TEST else 50 # number of Monte Carlo runs\n", + "N_DOE_ITERATIONS = 2 if SMOKE_TEST else 10 # number of DOE iterations\n", + "POINTS_PER_DIM = 3 if SMOKE_TEST else 7 # number of grid points per input dimension\n" + ] + }, + { + "cell_type": "code", + "execution_count": 112, + "metadata": {}, + "outputs": [], + "source": [ + "df_AA2024 = pd.read_excel('../data/averaged_filtered_AA2024.xlsx')\n", + "df_AA2024[\"alloy\"] = \"AA2024\"\n", + "df_AA1000 = pd.read_excel('../data/averaged_filtered_AA1000.xlsx')\n", + "df_AA1000[\"alloy\"] = \"AA1000\"\n", + "df_AA5000 = pd.read_excel('../data/averaged_filtered_AA5000.xlsx')\n", + "df_AA5000[\"alloy\"] = \"AA5000\"\n", + "df_AA6000 = pd.read_excel('../data/averaged_filtered_AA6000.xlsx')\n", + "df_AA6000[\"alloy\"] = \"AA6000\"\n", + "df_AA7075 = pd.read_excel('../data/averaged_filtered_AA7075.xlsx')\n", + "df_AA7075[\"alloy\"] = \"AA7075\"\n", + "df_Al = pd.read_excel('../data/averaged_filtered_Al.xlsx')" + ] + }, + { + "cell_type": "code", + "execution_count": 113, + "metadata": {}, + "outputs": [], + "source": [ + "target = NumericalTarget(name=\"Efficiency\", mode=\"MAX\", bounds=(efficiency_min, efficiency_max), transformation=\"LINEAR\")\n", + "objective = Objective(mode=\"SINGLE\", targets=[target])" + ] + }, + { + "cell_type": "code", + "execution_count": 133, + "metadata": {}, + "outputs": [], + "source": [ + "df_combined = pd.concat([df_AA2024, df_AA1000, df_AA5000, df_AA6000, df_AA7075], axis=0).reset_index(drop=True)\n", + "# df_active = df_AA2024\n", + "lookup = df_combined" + ] + }, + { + "cell_type": "code", + "execution_count": 145, + "metadata": {}, + "outputs": [], + "source": [ + "def list_to_dict(input_list):\n", + " return {item: item for item in input_list}\n", + "\n", + "smiles_dict =list_to_dict(df_combined.SMILES.unique())\n", + "\n", + "discrete_params = [\n", + "NumericalDiscreteParameter(\n", + " name=\"Time_h\",\n", + " values=df_combined['Time_h'].unique(),\n", + " # tolerance = 0.004, assume certain experimental noise for each parameter measurement?\n", + "),\n", + "NumericalDiscreteParameter(\n", + " name=\"pH\",\n", + " values=df_combined['pH'].unique(),\n", + " # tolerance = 0.004\n", + " ), \n", + "NumericalDiscreteParameter( # Set this as continuous, the values seem quite small?\n", + " name=\"Inhib_Concentrat_M\",\n", + " values= df_combined['Inhib_Concentrat_M'].unique(),\n", + " # tolerance = 0.004\n", + " ),\n", + "NumericalDiscreteParameter(\n", + " name=\"Salt_Concentrat_M\",\n", + " values=df_combined['Salt_Concentrat_M'].unique(),\n", + " # tolerance = 0.004\n", + " ),\n", + "# CategoricalParameter(\n", + "# name=\"alloy\",\n", + "# values=df_combined['alloy'].unique(),\n", + "# ),\n", + "SubstanceParameter(\n", + " name=\"SMILES\",\n", + " data=smiles_dict,\n", + " encoding=\"MORDRED\", # optional\n", + " decorrelate=0.7, # optional\n", + " ) \n", + " ]\n", + "# searchspace = SubspaceDiscrete.from_product(parameters=parameters)\n", + "df_no_target = df_combined.drop('Efficiency', axis=1).reset_index(drop=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 147, + "metadata": {}, + "outputs": [], + "source": [ + "task_param = TaskParameter(\n", + " name=\"alloy\",\n", + " values=[\"AA1000\", \"AA2024\", \"AA5000\", \"AA6000\", \"AA7075\"],\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 149, + "metadata": {}, + "outputs": [], + "source": [ + "parameters = [*discrete_params, task_param]\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 150, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
SMILESTime_hpHInhib_Concentrat_MSalt_Concentrat_MEfficiencyalloy
0C(=O)(C(=O)[O-])[O-]24.04.00.00100.1020.00AA2024
1C(=O)(C(=O)[O-])[O-]24.07.00.00050.0512.35AA2024
2C(=O)(C(=O)[O-])[O-]24.010.00.00100.1020.00AA2024
3C(C(=O)[O-])C(CC(=O)[O-])(C(=O)[O-])O24.04.00.00100.1030.00AA2024
4C(C(=O)[O-])C(CC(=O)[O-])(C(=O)[O-])O24.07.00.00050.05-23.95AA2024
\n", + "
" + ], + "text/plain": [ + " SMILES Time_h pH Inhib_Concentrat_M \\\n", + "0 C(=O)(C(=O)[O-])[O-] 24.0 4.0 0.0010 \n", + "1 C(=O)(C(=O)[O-])[O-] 24.0 7.0 0.0005 \n", + "2 C(=O)(C(=O)[O-])[O-] 24.0 10.0 0.0010 \n", + "3 C(C(=O)[O-])C(CC(=O)[O-])(C(=O)[O-])O 24.0 4.0 0.0010 \n", + "4 C(C(=O)[O-])C(CC(=O)[O-])(C(=O)[O-])O 24.0 7.0 0.0005 \n", + "\n", + " Salt_Concentrat_M Efficiency alloy \n", + "0 0.10 20.00 AA2024 \n", + "1 0.05 12.35 AA2024 \n", + "2 0.10 20.00 AA2024 \n", + "3 0.10 30.00 AA2024 \n", + "4 0.05 -23.95 AA2024 " + ] + }, + "execution_count": 150, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "lookup.head()" + ] + }, + { + "cell_type": "code", + "execution_count": 151, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
SMILESTime_hpHInhib_Concentrat_MSalt_Concentrat_Malloy
0C(=O)(C(=O)[O-])[O-]24.04.00.00100.10AA2024
1C(=O)(C(=O)[O-])[O-]24.07.00.00050.05AA2024
2C(=O)(C(=O)[O-])[O-]24.010.00.00100.10AA2024
3C(C(=O)[O-])C(CC(=O)[O-])(C(=O)[O-])O24.04.00.00100.10AA2024
4C(C(=O)[O-])C(CC(=O)[O-])(C(=O)[O-])O24.07.00.00050.05AA2024
.....................
1180c1ccc2c(c1)[nH]nn224.04.00.00100.10AA7075
1181c1ccc2c(c1)[nH]nn224.010.00.00100.10AA7075
1182c1ccc2c(c1)[nH]nn2672.07.00.00100.10AA7075
1183c1ncn[nH]124.04.00.00100.10AA7075
1184c1ncn[nH]124.010.00.00100.10AA7075
\n", + "

1185 rows × 6 columns

\n", + "
" + ], + "text/plain": [ + " SMILES Time_h pH Inhib_Concentrat_M \\\n", + "0 C(=O)(C(=O)[O-])[O-] 24.0 4.0 0.0010 \n", + "1 C(=O)(C(=O)[O-])[O-] 24.0 7.0 0.0005 \n", + "2 C(=O)(C(=O)[O-])[O-] 24.0 10.0 0.0010 \n", + "3 C(C(=O)[O-])C(CC(=O)[O-])(C(=O)[O-])O 24.0 4.0 0.0010 \n", + "4 C(C(=O)[O-])C(CC(=O)[O-])(C(=O)[O-])O 24.0 7.0 0.0005 \n", + "... ... ... ... ... \n", + "1180 c1ccc2c(c1)[nH]nn2 24.0 4.0 0.0010 \n", + "1181 c1ccc2c(c1)[nH]nn2 24.0 10.0 0.0010 \n", + "1182 c1ccc2c(c1)[nH]nn2 672.0 7.0 0.0010 \n", + "1183 c1ncn[nH]1 24.0 4.0 0.0010 \n", + "1184 c1ncn[nH]1 24.0 10.0 0.0010 \n", + "\n", + " Salt_Concentrat_M alloy \n", + "0 0.10 AA2024 \n", + "1 0.05 AA2024 \n", + "2 0.10 AA2024 \n", + "3 0.10 AA2024 \n", + "4 0.05 AA2024 \n", + "... ... ... \n", + "1180 0.10 AA7075 \n", + "1181 0.10 AA7075 \n", + "1182 0.10 AA7075 \n", + "1183 0.10 AA7075 \n", + "1184 0.10 AA7075 \n", + "\n", + "[1185 rows x 6 columns]" + ] + }, + "execution_count": 151, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df_combined.drop('Efficiency', axis=1).reset_index(drop=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 152, + "metadata": {}, + "outputs": [], + "source": [ + "searchspace = SearchSpace.from_dataframe(df = df_combined.drop('Efficiency', axis=1), parameters=parameters)" + ] + }, + { + "cell_type": "code", + "execution_count": 153, + "metadata": {}, + "outputs": [], + "source": [ + "campaign = Campaign(searchspace=searchspace, objective=objective)" + ] + }, + { + "cell_type": "code", + "execution_count": 154, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + " 0%| | 0/250 [00:00