diff --git a/baybe_hack.ipynb b/baybe_hack.ipynb new file mode 100644 index 0000000..272c339 --- /dev/null +++ b/baybe_hack.ipynb @@ -0,0 +1,362 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Imports" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "\n", + "from baybe.targets import NumericalTarget\n", + "from baybe.objective import Objective\n", + "\n", + "from baybe.parameters import NumericalDiscreteParameter, NumericalContinuousParameter\n", + "from baybe.searchspace import SearchSpace\n", + "\n", + "from baybe.recommenders import RandomRecommender, SequentialGreedyRecommender, NaiveHybridRecommender\n", + "from baybe.surrogates import GaussianProcessSurrogate\n", + "\n", + "from baybe.strategies import TwoPhaseStrategy\n", + "from baybe import Campaign" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Setting the objectives" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The DESIRABILITY mode enables the combination multiple targets via scalarization into a single value.\n", + "\n", + "See MATCH mode, instead of MAX/MIN + For more details on transformation functions: \n", + "https://emdgroup.github.io/baybe/userguide/targets.html" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Set targets/objectives, efficiency?" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"\n", + "overpotential = NumericalTarget(\n", + " name=\"overpotential\", \n", + " mode=\"MAX\", \n", + " bounds=(-400, 0),\n", + " transformation=\"LINEAR\" # optional, will be applied if bounds are not None, LINEAR only one available for MAX/MIN\n", + " ) \n", + "\n", + "overpotential_slope = NumericalTarget(\n", + " name=\"overpotential_slope\", \n", + " mode=\"MAX\", \n", + " bounds=(-0.05, 0.05),\n", + " transformation=\"LINEAR\" # optional, will be applied if bounds are not None, LINEAR only one available for MAX/MIN\n", + " )\n", + "\n", + "objective = Objective(\n", + " mode=\"DESIRABILITY\",\n", + " targets=[overpotential, overpotential_slope],\n", + " weights=[1.0, 1.0], # optional, by default all weights are equal\n", + " combine_func=\"GEOM_MEAN\", # optional, geometric mean is the default\n", + ")\n", + "\"\"\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Search Space" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "parameters = [\n", + "NumericalDiscreteParameter(\n", + " name=\"Time (h)\",\n", + " values=np.arange(6, 25, 1) # Assuming time below 6 hours is discarded\n", + "),\n", + "NumericalDiscreteParameter(\n", + " name=\"pH\",\n", + " values=np.arange(-1, 15.1, 0.1)\n", + " ), \n", + "NumericalContinuousParameter( # Set this as continuous, the values seem quite small?\n", + " name=\"Inhibitor Concentration (M)\",\n", + " bounds=(0, 0.02)\n", + " ),\n", + "NumericalDiscreteParameter(\n", + " name=\"Salt Concentration (M)\",\n", + " values=np.arange(0, 2.01, 0.01),\n", + " )\n", + "]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Substance parameter**\n", + "\n", + "Instead of values, this parameter accepts data in form of a dictionary. The items correspond to pairs of labels and SMILES. SMILES are string-based representations of molecular structures. Based on these, BayBE can assign each label a set of molecular descriptors as encoding.\n", + "\n", + "For instance, a parameter corresponding to a choice of solvents can be initialized with:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from baybe.parameters import SubstanceParameter\n", + "\n", + "SubstanceParameter(\n", + " name=\"Solvent\",\n", + " data={\n", + " \"Water\": \"O\",\n", + " \"1-Octanol\": \"CCCCCCCCO\",\n", + " \"Toluene\": \"CC1=CC=CC=C1\",\n", + " },\n", + " encoding=\"MORDRED\", # optional\n", + " decorrelate=0.7, # optional\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "The encoding option defines what kind of descriptors are calculated:\n", + "\n", + "MORDRED: 2D descriptors from the Mordred package. Since the original package is now unmaintained, baybe requires the community replacement mordredcommunity\n", + "\n", + "RDKIT: 2D descriptors from the RDKit package\n", + "\n", + "MORGAN_FP: Morgan fingerprints calculated with RDKit (1024 bits, radius 4)\n", + "\n", + "These calculations will typically result in 500 to 1500 numbers per molecule. **To avoid detrimental effects on the surrogate model fit, we reduce the number of descriptors via decorrelation before using them.** For instance, the decorrelate option in the example above specifies that only descriptors with a correlation lower than 0.7 to any other descriptor will be kept. This usually reduces the number of descriptors to 10-50, depending on the specific items in data.\n", + "\n", + "**WARNING:**\n", + "The descriptors calculated for a SubstanceParameter were developed to describe small molecules and are not suitable for other substances. If you deal with large molecules like polymers or arbitrary substance mixtures, we recommend to provide your own descriptors via the CustomParameter." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The encoding concept introduced above is generalized by the CustomParameter. Here, the user is expected to provide their own descriptors for the encoding.\n", + "\n", + "Take, for instance, a parameter that corresponds to the choice of a polymer. Polymers are not well represented by the small molecule descriptors utilized in the SubstanceParameter. Still, one could provide experimental measurements or common metrics used to classify polymers:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "from baybe.parameters import CustomDiscreteParameter\n", + "\n", + "# Create or import new dataframe containing custom descriptors\n", + "\n", + "descriptors = pd.DataFrame(\n", + " {\n", + " \"Glass_Transition_TempC\": [20, -71, -39],\n", + " \"Weight_kDalton\": [120, 32, 241],\n", + " },\n", + " index=[\"Polymer A\", \"Polymer B\", \"Polymer C\"], # put labels in the index\n", + ")\n", + "\n", + "CustomDiscreteParameter(\n", + " name=\"Polymer\",\n", + " data=descriptors,\n", + " decorrelate=True, # optional, uses default correlation threshold = 0.7?\n", + ")\n", + "\n", + "# Add this to the parameters list afterwards" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "searchspace = SearchSpace.from_product(parameters)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Recommenders" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The **SequentialGreedyRecommender** is a powerful recommender that leverages BoTorch optimization functions to perform sequential Greedy optimization. It can be applied for discrete, continuous and hybrid sarch spaces. It is an implementation of the BoTorch optimization functions for discrete, continuous and mixed spaces. **It is important to note that this recommender performs a brute-force search when applied in hybrid search spaces, as it optimizes the continuous part of the space while exhaustively searching choices in the discrete subspace.** You can customize this behavior to only sample a certain percentage of the discrete subspace via the sample_percentage attribute and to choose different sampling strategies via the hybrid_sampler attribute. \n", + "\n", + "e.g.\n", + "strategy = TwoPhaseStrategy(recommender=SequentialGreedyRecommender(hybrid_sampler=\"Farthest\", sampling_percentage=0.3))\n", + "\n", + "The **NaiveHybridRecommender** can be applied to all search spaces, but is intended to be used in hybrid spaces. This recommender **combines individual recommenders for the continuous and the discrete subspaces. It independently optimizes each subspace and consolidates the best results to generate a candidate for the original hybrid space.** " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For implementing fully customized surrogate models e.g. from sklearn or PyTorch, see:\n", + "https://emdgroup.github.io/baybe/examples/Custom_Surrogates/Custom_Surrogates.html\n" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "c:\\Users\\lordm\\Desktop\\Projects\\baybe\\.venv\\lib\\site-packages\\baybe\\recommenders\\bayesian.py:492: UserWarning: The value of 'allow_recommending_already_measured' differs from what is specified in the discrete recommender. The value of the discrete recommender will be ignored.\n", + " warnings.warn(\n" + ] + } + ], + "source": [ + "available_surr_models = [\n", + " \"GaussianProcessSurrogate\", \n", + " \"BayesianLinearSurrogate\",\n", + " \"MeanPredictionSurrogate\",\n", + " \"NGBoostSurrogate\",\n", + " \"RandomForestSurrogate\"\n", + "]\n", + "\n", + "available_acq_functions = [\n", + " \"qPI\", # q-Probability Of Improvement\n", + " \"qEI\", # q-Expected Improvement\n", + " \"qUCB\", # q-upper confidence bound with beta of 1.0\n", + "]\n", + "\n", + "# Defaults anyway\n", + "SURROGATE_MODEL = GaussianProcessSurrogate()\n", + "ACQ_FUNCTION = \"qEI\" # q-Expected Improvement, only q-fuctions are available for batch_size > 1\n", + "\n", + "seq_greedy_recommender = SequentialGreedyRecommender(\n", + " surrogate_model=SURROGATE_MODEL,\n", + " acquisition_function_cls=ACQ_FUNCTION,\n", + " hybrid_sampler=\"Farthest\", # find more details in the documentation\n", + " sampling_percentage=0.3, # should be relatively low\n", + " allow_repeated_recommendations=False,\n", + " allow_recommending_already_measured=False,\n", + " )\n", + "\n", + "hybrid_recommender = NaiveHybridRecommender(\n", + " allow_repeated_recommendations=False,\n", + " allow_recommending_already_measured=False\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Campaign Strategy" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "strategy = TwoPhaseStrategy(\n", + " initial_recommender = RandomRecommender(), # Initial recommender, if no training data is available\n", + " # Other initial recommenders don't seem to work for my hybrid search space/set of parameters\n", + " # Doesn't matter since I already have training data\n", + " recommender = seq_greedy_recommender, # Bayesian model-based optimization\n", + " # recommender = hybrid_recommender,\n", + " switch_after=1 # Switch to the model-based recommender after 1 batch or iteration (so the initial training data)\n", + ")\n", + "\n", + "campaign = Campaign(searchspace, objective, strategy)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Import and read modified Excel file as dataframe? - Now containing only specific columns as training data - as in possibly this example: \n", + "\n", + "https://emdgroup.github.io/baybe/examples/Backtesting/full_initial_data.html\n", + "\n", + "\n", + "https://emdgroup.github.io/baybe/examples/Backtesting/full_lookup.html" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### For transfer learning see: \n", + "\n", + "https://emdgroup.github.io/baybe/userguide/transfer_learning\n", + "\n", + "&\n", + "\n", + "https://emdgroup.github.io/baybe/examples/Transfer_Learning/basic_transfer_learning.html" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.11" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/exploration.ipynb b/exploration.ipynb new file mode 100644 index 0000000..912d9c2 --- /dev/null +++ b/exploration.ipynb @@ -0,0 +1,1011 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Data Exploration" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import numpy as np" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "ename": "FileNotFoundError", + "evalue": "[Errno 2] No such file or directory: 'cordata.xlsx'", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mFileNotFoundError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[1;32mIn[2], line 1\u001b[0m\n\u001b[1;32m----> 1\u001b[0m df_full \u001b[38;5;241m=\u001b[39m \u001b[43mpd\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mread_excel\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mcordata.xlsx\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m)\u001b[49m \u001b[38;5;66;03m# contains all data\u001b[39;00m\n\u001b[0;32m 2\u001b[0m df_Al \u001b[38;5;241m=\u001b[39m pd\u001b[38;5;241m.\u001b[39mread_excel(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mcordata_Al.xlsx\u001b[39m\u001b[38;5;124m'\u001b[39m) \u001b[38;5;66;03m# only Al alloy class\u001b[39;00m\n", + "File \u001b[1;32mc:\\Users\\lordm\\Desktop\\Projects\\baybe\\.venv\\lib\\site-packages\\pandas\\io\\excel\\_base.py:495\u001b[0m, in \u001b[0;36mread_excel\u001b[1;34m(io, sheet_name, header, names, index_col, usecols, dtype, engine, converters, true_values, false_values, skiprows, nrows, na_values, keep_default_na, na_filter, verbose, parse_dates, date_parser, date_format, thousands, decimal, comment, skipfooter, storage_options, dtype_backend, engine_kwargs)\u001b[0m\n\u001b[0;32m 493\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(io, ExcelFile):\n\u001b[0;32m 494\u001b[0m should_close \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[1;32m--> 495\u001b[0m io \u001b[38;5;241m=\u001b[39m \u001b[43mExcelFile\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m 496\u001b[0m \u001b[43m \u001b[49m\u001b[43mio\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 497\u001b[0m \u001b[43m \u001b[49m\u001b[43mstorage_options\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstorage_options\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 498\u001b[0m \u001b[43m \u001b[49m\u001b[43mengine\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mengine\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 499\u001b[0m \u001b[43m \u001b[49m\u001b[43mengine_kwargs\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mengine_kwargs\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 500\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 501\u001b[0m \u001b[38;5;28;01melif\u001b[39;00m engine \u001b[38;5;129;01mand\u001b[39;00m engine \u001b[38;5;241m!=\u001b[39m io\u001b[38;5;241m.\u001b[39mengine:\n\u001b[0;32m 502\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\n\u001b[0;32m 503\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mEngine should not be specified when passing \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m 504\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124man ExcelFile - ExcelFile already has the engine set\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m 505\u001b[0m )\n", + "File \u001b[1;32mc:\\Users\\lordm\\Desktop\\Projects\\baybe\\.venv\\lib\\site-packages\\pandas\\io\\excel\\_base.py:1550\u001b[0m, in \u001b[0;36mExcelFile.__init__\u001b[1;34m(self, path_or_buffer, engine, storage_options, engine_kwargs)\u001b[0m\n\u001b[0;32m 1548\u001b[0m ext \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mxls\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m 1549\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m-> 1550\u001b[0m ext \u001b[38;5;241m=\u001b[39m \u001b[43minspect_excel_format\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m 1551\u001b[0m \u001b[43m \u001b[49m\u001b[43mcontent_or_path\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mpath_or_buffer\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mstorage_options\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstorage_options\u001b[49m\n\u001b[0;32m 1552\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 1553\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m ext \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[0;32m 1554\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\n\u001b[0;32m 1555\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mExcel file format cannot be determined, you must specify \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m 1556\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124man engine manually.\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m 1557\u001b[0m )\n", + "File \u001b[1;32mc:\\Users\\lordm\\Desktop\\Projects\\baybe\\.venv\\lib\\site-packages\\pandas\\io\\excel\\_base.py:1402\u001b[0m, in \u001b[0;36minspect_excel_format\u001b[1;34m(content_or_path, storage_options)\u001b[0m\n\u001b[0;32m 1399\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(content_or_path, \u001b[38;5;28mbytes\u001b[39m):\n\u001b[0;32m 1400\u001b[0m content_or_path \u001b[38;5;241m=\u001b[39m BytesIO(content_or_path)\n\u001b[1;32m-> 1402\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m \u001b[43mget_handle\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m 1403\u001b[0m \u001b[43m \u001b[49m\u001b[43mcontent_or_path\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mrb\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mstorage_options\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstorage_options\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mis_text\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\n\u001b[0;32m 1404\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m \u001b[38;5;28;01mas\u001b[39;00m handle:\n\u001b[0;32m 1405\u001b[0m stream \u001b[38;5;241m=\u001b[39m handle\u001b[38;5;241m.\u001b[39mhandle\n\u001b[0;32m 1406\u001b[0m stream\u001b[38;5;241m.\u001b[39mseek(\u001b[38;5;241m0\u001b[39m)\n", + "File \u001b[1;32mc:\\Users\\lordm\\Desktop\\Projects\\baybe\\.venv\\lib\\site-packages\\pandas\\io\\common.py:882\u001b[0m, in \u001b[0;36mget_handle\u001b[1;34m(path_or_buf, mode, encoding, compression, memory_map, is_text, errors, storage_options)\u001b[0m\n\u001b[0;32m 873\u001b[0m handle \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mopen\u001b[39m(\n\u001b[0;32m 874\u001b[0m handle,\n\u001b[0;32m 875\u001b[0m ioargs\u001b[38;5;241m.\u001b[39mmode,\n\u001b[1;32m (...)\u001b[0m\n\u001b[0;32m 878\u001b[0m newline\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[0;32m 879\u001b[0m )\n\u001b[0;32m 880\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m 881\u001b[0m \u001b[38;5;66;03m# Binary mode\u001b[39;00m\n\u001b[1;32m--> 882\u001b[0m handle \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mopen\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mhandle\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mioargs\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mmode\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 883\u001b[0m handles\u001b[38;5;241m.\u001b[39mappend(handle)\n\u001b[0;32m 885\u001b[0m \u001b[38;5;66;03m# Convert BytesIO or file objects passed with an encoding\u001b[39;00m\n", + "\u001b[1;31mFileNotFoundError\u001b[0m: [Errno 2] No such file or directory: 'cordata.xlsx'" + ] + } + ], + "source": [ + "df_full = pd.read_excel('cordata.xlsx') # contains all data\n", + "df_Al = pd.read_excel('cordata_Al.xlsx') # only Al alloy class" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "RangeIndex: 4973 entries, 0 to 4972\n", + "Data columns (total 17 columns):\n", + " # Column Non-Null Count Dtype \n", + "--- ------ -------------- ----- \n", + " 0 Index 4973 non-null int64 \n", + " 1 Inhibitor 4973 non-null object \n", + " 2 Mol._weight 4973 non-null float64\n", + " 3 SMILES 4973 non-null object \n", + " 4 Metal 4973 non-null object \n", + " 5 Alloy 4973 non-null object \n", + " 6 Time_h 4973 non-null float64\n", + " 7 Temperature_K 4973 non-null float64\n", + " 8 pH 4973 non-null float64\n", + " 9 Inhib_Concentrat_M 4973 non-null float64\n", + " 10 Salt_Concentrat_M 4973 non-null float64\n", + " 11 Synergistic_Inhib_type 265 non-null object \n", + " 12 Synergistic_Inhib_M 4925 non-null float64\n", + " 13 Methodology 4973 non-null object \n", + " 14 Reference 4973 non-null object \n", + " 15 Contributor 4973 non-null object \n", + " 16 Efficiency 4973 non-null float64\n", + "dtypes: float64(8), int64(1), object(8)\n", + "memory usage: 660.6+ KB\n", + "None\n" + ] + } + ], + "source": [ + "print(df_full.info())" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "RangeIndex: 2011 entries, 0 to 2010\n", + "Data columns (total 19 columns):\n", + " # Column Non-Null Count Dtype \n", + "--- ------ -------------- ----- \n", + " 0 Inhibitor 2011 non-null object \n", + " 1 SMILES 2011 non-null object \n", + " 2 Number 2011 non-null int64 \n", + " 3 Metal 2011 non-null object \n", + " 4 Alloy 2011 non-null object \n", + " 5 Time_h 2011 non-null float64\n", + " 6 Temperature_K 2011 non-null int64 \n", + " 7 pH 2011 non-null float64\n", + " 8 Inhib_Concentrat_M 2011 non-null float64\n", + " 9 Salt_Concentrat_M 2011 non-null float64\n", + " 10 Synergistic_inhib 2011 non-null object \n", + " 11 Synergistic_inhib_type 2011 non-null object \n", + " 12 Synergistic_inhib_Concentrat_M 2011 non-null float64\n", + " 13 Encapsulated 2011 non-null object \n", + " 14 Efficiency 2011 non-null float64\n", + " 15 Methodology 2011 non-null object \n", + " 16 Reference 2011 non-null object \n", + " 17 Link 2011 non-null object \n", + " 18 Contributor 2011 non-null object \n", + "dtypes: float64(6), int64(2), object(11)\n", + "memory usage: 298.6+ KB\n", + "None\n" + ] + } + ], + "source": [ + "print(df_Al.info())" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Al: 2001\n", + "Cu: 272\n", + "Fe: 1230\n", + "Mg: 1465\n", + "Zn: 5\n" + ] + } + ], + "source": [ + "# number of entries for every alloy class in the full dataset\n", + "for metal in df_full['Metal'].unique():\n", + " print(f\"{metal}: {len(df_full[df_full['Metal'] == metal])}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### since Al has the biggest number it is indeed smart to start the alloy specific analysis with Al" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "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", + "
Efficiency
medianstd
SMILES
Brc1ncccn113.96.407808
C(=O)(C(=O)[O-])[O-]33.066.649155
C(C(=O)O)(C)(CO)CO63.514.066509
C(C(=O)O)N-289.0NaN
C(C(=O)[O-])C(CC(=O)[O-])(C(=O)[O-])O63.6171.524937
.........
c1ncn[nH]1-16.5376.741314
c2ccc1[nH]cnc1c247.910.392243
c3ccc(Cn2cnc1ccccc12)cc397.50.223607
c4ccc(Cn3c(c1ccccc1)nc2ccccc23)cc497.80.316228
n1c2C(=O)NC(N)=Nc2ncc1CNc3ccc(cc3)C(=O)N[C@H](C(O)=O)CCC(O)=O82.420.836281
\n", + "

402 rows × 2 columns

\n", + "
" + ], + "text/plain": [ + " Efficiency \n", + " median std\n", + "SMILES \n", + "Brc1ncccn1 13.9 6.407808\n", + "C(=O)(C(=O)[O-])[O-] 33.0 66.649155\n", + "C(C(=O)O)(C)(CO)CO 63.5 14.066509\n", + "C(C(=O)O)N -289.0 NaN\n", + "C(C(=O)[O-])C(CC(=O)[O-])(C(=O)[O-])O 63.6 171.524937\n", + "... ... ...\n", + "c1ncn[nH]1 -16.5 376.741314\n", + "c2ccc1[nH]cnc1c2 47.9 10.392243\n", + "c3ccc(Cn2cnc1ccccc12)cc3 97.5 0.223607\n", + "c4ccc(Cn3c(c1ccccc1)nc2ccccc23)cc4 97.8 0.316228\n", + "n1c2C(=O)NC(N)=Nc2ncc1CNc3ccc(cc3)C(=O)N[C@H](C... 82.4 20.836281\n", + "\n", + "[402 rows x 2 columns]" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# unique compounds for full dataset\n", + "df_full.groupby('SMILES').agg({'Efficiency':['median', 'std']})" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "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", + "
Efficiency
medianstd
SMILES
C(=O)(C(=O)[O-])[O-]20.00015.146012
C(C(=O)[O-])C(CC(=O)[O-])(C(=O)[O-])O71.30033.074888
C(C(C(C(C(C(=O)[O-])O)O)O)O)O.C(C(C(C(C(C(=O)[O-])O)O)O)O)O.[Fe+2]65.00022.500907
C(C(C(C(C(C(=O)[O-])O)O)O)O)O.C(C(C(C(C(C(=O)[O-])O)O)O)O)O.[Zn+2]61.00032.650756
C(C(CO)([N+](=O)[O-])Br)O84.2859.737557
.........
[O-]S(=O)[O-].[Na+].[Na+]85.20015.171265
c1cc(ccc1c2[nH]c(nn2)S)[N+](=O)[O-]25.0005.773503
c1ccc(nc1)c1ccccn130.0008.164966
c1ccc2c(c1)[nH]nn291.00031.045126
c1ncn[nH]135.00034.034296
\n", + "

177 rows × 2 columns

\n", + "
" + ], + "text/plain": [ + " Efficiency \n", + " median std\n", + "SMILES \n", + "C(=O)(C(=O)[O-])[O-] 20.000 15.146012\n", + "C(C(=O)[O-])C(CC(=O)[O-])(C(=O)[O-])O 71.300 33.074888\n", + "C(C(C(C(C(C(=O)[O-])O)O)O)O)O.C(C(C(C(C(C(=O)[O... 65.000 22.500907\n", + "C(C(C(C(C(C(=O)[O-])O)O)O)O)O.C(C(C(C(C(C(=O)[O... 61.000 32.650756\n", + "C(C(CO)([N+](=O)[O-])Br)O 84.285 9.737557\n", + "... ... ...\n", + "[O-]S(=O)[O-].[Na+].[Na+] 85.200 15.171265\n", + "c1cc(ccc1c2[nH]c(nn2)S)[N+](=O)[O-] 25.000 5.773503\n", + "c1ccc(nc1)c1ccccn1 30.000 8.164966\n", + "c1ccc2c(c1)[nH]nn2 91.000 31.045126\n", + "c1ncn[nH]1 35.000 34.034296\n", + "\n", + "[177 rows x 2 columns]" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# unique compounds for Al only dataset\n", + "df_Al.groupby('SMILES').agg({'Efficiency':['median', 'std']})" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 402 compounds for full, 177 for only Al. How about if we work for the largest alloy group?" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Rank of unique values:\n", + "Mild steel 690\n", + "AA2024 590\n", + "Al 424\n", + "Cu 262\n", + "CP-Mg-220ppm 239\n", + "AA7075 227\n", + "AA1060 203\n", + "Cold rolled steel 182\n", + "AZ31 158\n", + "AlSi 155\n", + "ZE41 155\n", + "WE43 153\n", + "AM50 153\n", + "AZ91 145\n", + "Fe 143\n", + "E21 133\n", + "HP-Mg-50ppm 119\n", + "HP-Mg-51ppm 109\n", + "Carbon steel 92\n", + "AA5754 84\n", + "Steel 75\n", + "CP-Mg-342ppm 60\n", + "Al_rod 49\n", + "Stainless steel 48\n", + "AA6063 48\n", + "AA6061 48\n", + "AA5083 46\n", + "AA5052 45\n", + "Mg-0,8Ca 25\n", + "AA1100 25\n", + "AA3SR 18\n", + "AZ91E 15\n", + "AA63400 12\n", + "AA2014 12\n", + "Brass 10\n", + "AA5005 8\n", + "AA2017A 7\n", + "Galvanized 5\n", + "AZ91D 1\n", + "Name: Alloy, dtype: int64\n", + "\n", + "Unique alloys in full dataset: 39\n", + "Unique alloys in only Al dataset: 17\n" + ] + } + ], + "source": [ + "def value_counts(df, value):\n", + " # Count unique values in the 'value' column\n", + " value_counts = df[value].value_counts()\n", + " ranked_values = value_counts.sort_values(ascending=False)\n", + " print(\"Rank of unique values:\")\n", + " print(ranked_values)\n", + "\n", + "value_counts(df_full, 'Alloy')\n", + "print()\n", + "print(f'Unique alloys in full dataset: {len(df_full[\"Alloy\"].unique())}')\n", + "print(f'Unique alloys in only Al dataset: {len(df_Al[\"Alloy\"].unique())}')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### I suggest we start from AA2024, as mild steel is too general of a category." + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "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", + "
Efficiency
medianstd
SMILES
C(=O)(C(=O)[O-])[O-]20.0014.061383
C(C(=O)[O-])C(CC(=O)[O-])(C(=O)[O-])O12.5540.887682
C(C(C(C(C(C(=O)[O-])O)O)O)O)O.C(C(C(C(C(C(=O)[O-])O)O)O)O)O.[Fe+2]65.0022.500907
C(C(C(C(C(C(=O)[O-])O)O)O)O)O.C(C(C(C(C(C(=O)[O-])O)O)O)O)O.[Zn+2]61.0032.650756
C1=CC(=C(C=C1O)O)C=NNC(=S)N86.6026.204889
.........
[O-]S(=O)[O-].[Na+].[Na+]85.2015.171265
c1cc(ccc1c2[nH]c(nn2)S)[N+](=O)[O-]25.007.071068
c1ccc(nc1)c1ccccn135.007.071068
c1ccc2c(c1)[nH]nn297.8020.848309
c1ncn[nH]160.0042.426407
\n", + "

123 rows × 2 columns

\n", + "
" + ], + "text/plain": [ + " Efficiency \n", + " median std\n", + "SMILES \n", + "C(=O)(C(=O)[O-])[O-] 20.00 14.061383\n", + "C(C(=O)[O-])C(CC(=O)[O-])(C(=O)[O-])O 12.55 40.887682\n", + "C(C(C(C(C(C(=O)[O-])O)O)O)O)O.C(C(C(C(C(C(=O)[O... 65.00 22.500907\n", + "C(C(C(C(C(C(=O)[O-])O)O)O)O)O.C(C(C(C(C(C(=O)[O... 61.00 32.650756\n", + "C1=CC(=C(C=C1O)O)C=NNC(=S)N 86.60 26.204889\n", + "... ... ...\n", + "[O-]S(=O)[O-].[Na+].[Na+] 85.20 15.171265\n", + "c1cc(ccc1c2[nH]c(nn2)S)[N+](=O)[O-] 25.00 7.071068\n", + "c1ccc(nc1)c1ccccn1 35.00 7.071068\n", + "c1ccc2c(c1)[nH]nn2 97.80 20.848309\n", + "c1ncn[nH]1 60.00 42.426407\n", + "\n", + "[123 rows x 2 columns]" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# composition of AA2000 series is nearly identical, grab alloys from this series\n", + "df_AA2024 = df_Al[df_Al['Alloy'].isin(['AA2024', 'AA2014', 'AA2017A'])]\n", + "df_AA2024.groupby('SMILES').agg({'Efficiency':['median', 'std']})" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 177 compounds for all Al, to 123 compounds to only AA2024." + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[2.40e+01 6.72e+02 0.00e+00 1.67e+00 3.30e-01 5.80e-01 1.00e+00 5.00e-01\n", + " 1.50e+00 2.00e+00 2.50e+00 4.80e+01 9.60e+01 1.44e+02 1.92e+02 2.40e+02\n", + " 2.88e+02 3.36e+02 3.84e+02 4.00e+00 6.00e+00 8.00e+00 2.50e-01 7.50e-01\n", + " 7.20e+01 3.60e+02 4.80e+02 6.00e+02 1.68e+02 1.20e+02 1.00e+01 3.00e+00\n", + " 4.32e+02 5.28e+02 5.76e+02 6.24e+02 3.50e+00 4.50e+00 5.00e+00 5.50e+00\n", + " 7.20e+02 6.70e-01]\n", + "42\n" + ] + } + ], + "source": [ + "# you can play around with the column names to see what unique values are in each column\n", + "column_name = 'Time_h'\n", + "print(df_Al[column_name].unique())\n", + "print((len(df_Al[column_name].unique())))" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Rank of unique values:\n", + "24.00 656\n", + "0.50 306\n", + "2.00 268\n", + "1.00 134\n", + "672.00 54\n", + "3.00 48\n", + "144.00 48\n", + "48.00 47\n", + "72.00 41\n", + "1.67 40\n", + "168.00 28\n", + "0.33 28\n", + "240.00 25\n", + "96.00 22\n", + "336.00 20\n", + "4.00 19\n", + "288.00 19\n", + "6.00 17\n", + "480.00 16\n", + "0.67 16\n", + "0.00 14\n", + "192.00 14\n", + "384.00 14\n", + "576.00 13\n", + "432.00 13\n", + "10.00 9\n", + "360.00 8\n", + "120.00 8\n", + "528.00 8\n", + "624.00 8\n", + "600.00 7\n", + "0.58 7\n", + "2.50 6\n", + "1.50 6\n", + "720.00 5\n", + "5.00 4\n", + "8.00 4\n", + "4.50 3\n", + "3.50 3\n", + "5.50 3\n", + "0.25 1\n", + "0.75 1\n", + "Name: Time_h, dtype: int64\n" + ] + } + ], + "source": [ + "# previous counter fuinction to check distribution\n", + "value_counts(df_Al, 'Time_h')" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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119/jT59+tT6npBdu3ZZZXJEREREraFZgahz587yV2cQERERtXfNCkQbN2609jyIiIiIbKZZ1xABwN27d7F3716sW7cOt27dAgBcuXIF5eXlVpscERERUWto1hGiixcvYvjw4bh06RKMRiMiIiLg6uqKZcuW4c6dO1i7dq2150lERETUYpp1hGj27NkIDg5GcXEx1Gq1PD569Gh8++23VpscERERUWto9l1m//73v+Ho6Ggx7ufnh4KCAqtMjIiIiKi1NOsIkdlsRnV1da3x/Px8uLq6/uJJEREREbWmZgWiiIgIrFq1Sl5WKBQoLy/He++9x6/zICIionanWafMVq5cicGDB6N37964c+cOYmNjcf78eXh6emLHjh3WniMRERFRi2pWIPLx8UF2djZ27NiBEydOwGw2Y/LkyRg/frzFRdZERERE7UGzAhEAqNVqvPrqq3j11VetOR8iIiKiVtesQLRly5YG10+YMKFZkyEiIiKyhWYFotmzZ1ssm0wmVFRUwNHREc7OzgxERERE1K406y6z4uJii0d5eTlyc3PxzDPP8KJqIiIianea/V1mD/L398fSpUtrHT0iIiIiauusFogAwN7eHleuXLHmJomIiIhaXLOuIfryyy8tliVJgsFgwOrVq/Hb3/7WKhMjIiIiai3NCkTPP/+8xbJCocAjjzyCIUOG4MMPP7TGvIiIiIhaTbMCkdlstvY8iIiIiGzGqtcQEREREbVHzTpCNGfOnCbXrlixojm7ICIiImo1zQpEJ0+exIkTJ3D37l0EBAQAAH788UfY29vjqaeekusUCoV1ZklERETUgpoViEaNGgVXV1ds3rwZXbp0AXDvwxpfeeUV/O53v8PcuXOtOkkiIiKiltSsa4g+/PBDJCYmymEIALp06YLFixc/1F1miYmJ+M1vfgNXV1dotVo8//zzyM3NtaiRJAnx8fHw8fGBWq1GeHg4zp49a1FjNBoxc+ZMeHp6wsXFBTExMcjPz7eoKS4uhl6vh0ajgUajgV6vR0lJycM3T0RERB1OswJRWVkZrl69Wmu8qKgIt27davJ2Dhw4gOnTpyMzMxNpaWm4e/cuIiMjcfv2bblm2bJlWLFiBVavXo1jx45Bp9MhIiLCYj9xcXHYvXs3UlJScOjQIZSXlyM6OhrV1dVyTWxsLLKzs5GamorU1FRkZ2dDr9c3p30i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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjsAAAHFCAYAAAAUpjivAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAA54ElEQVR4nO3de1jUZd7H8c9wEIHQFONUamyRJ8xKy9LWQyodJEv3WWutVVOfNK2V1K3MbaW2wHQjWy3NctVy1bYtd32uZ0vRSDM6mKfUXLMyjxCZKCgIyNzPH17M0wgoDoMD97xf1zWXzv27Z37f7zDqx/v3+804jDFGAAAAlgrwdQEAAAB1ibADAACsRtgBAABWI+wAAACrEXYAAIDVCDsAAMBqhB0AAGA1wg4AALAaYQcAAFiNsAP4gYULF8rhcOiLL76ocntycrIuv/xyt7HLL79cw4cPP6/9ZGdnKzU1VUePHvWsUD/01ltvqUOHDgoNDZXD4dCWLVvO+ZgVK1bI4XAoMjJSJSUlVc7x5OcH2IqwA6BKy5cv11NPPXVej8nOztbTTz9N2KmhH3/8Ub/97W91xRVX6P3339cnn3yiq6666pyPmz9/viTpyJEj+uc//1nHVQINH2EHQJWuvfZaXXHFFb4u47yUlZXp1KlTvi6jxr7++muVlZXp/vvvV8+ePXXjjTcqLCzsrI/Jzc3Vv//9b91yyy1q3LixK/gAqB5hB0CVzjwM4nQ69eyzz6pNmzYKDQ3VxRdfrKuvvlovvfSSJCk1NVW///3vJUnx8fFyOBxyOBz68MMPXY+fPn262rZtq5CQEEVFRWno0KE6cOCA236NMUpLS1Pr1q3VuHFjdenSRZmZmerVq5d69erlmvfhhx/K4XDozTff1MSJE3XppZcqJCRE33zzjX788UeNHTtW7du310UXXaSoqCjdcsst+uijj9z29f3338vhcGjGjBl6/vnndfnllys0NFS9evVyBZEnnnhCcXFxatq0qQYOHKi8vLwavX4rVqzQTTfdpLCwMEVERKhfv3765JNPXNuHDx+um2++WZJ0zz33yOFwuPVXnUWLFunUqVN69NFHNWjQIK1Zs0Z79+6tUU2AvwrydQEALpzy8vIqVz6MMed87PTp05Wamqo//OEP6tGjh8rKyvSf//zHdchq1KhROnLkiGbNmqV3331XsbGxkqT27dtLkh566CHNmzdPDz/8sJKTk/X999/rqaee0ocffqhNmzapRYsWkqQpU6YoPT1dDz74oAYNGqT9+/dr1KhRKisrq/IQz+TJk3XTTTdp7ty5CggIUFRUlH788UdJ0tSpUxUTE6Pjx49r+fLl6tWrl9asWVMpVLz88su6+uqr9fLLL+vo0aOaOHGi7rzzTnXt2lXBwcH661//qr1792rSpEkaNWqUVqxYcdbXasmSJbrvvvuUlJSkpUuXqqSkRNOnT3ft/+abb9ZTTz2lG264QePGjVNaWpp69+6tJk2anPPn8Ne//lWxsbG6/fbbFRoaqiVLlmjhwoWaOnXqOR8L+C0DwHoLFiwwks56a926tdtjWrdubYYNG+a6n5ycbK655pqz7mfGjBlGktmzZ4/b+M6dO40kM3bsWLfxzz77zEgyTz75pDHGmCNHjpiQkBBzzz33uM375JNPjCTTs2dP11hWVpaRZHr06HHO/k+dOmXKyspMnz59zMCBA13je/bsMZJMp06dTHl5uWt85syZRpIZMGCA2/OkpKQYSebYsWPV7qu8vNzExcWZjh07uj1nYWGhiYqKMt26davUw9tvv33OHowxZt26dUaSeeKJJ4wxxjidThMfH29at25tnE6n29wzf36AP+MwFuBH3njjDW3YsKHSreJwytnccMMN2rp1q8aOHauVK1eqoKCgxvvNysqSpEpXB91www1q166d1qxZI0n69NNPVVJSosGDB7vNu/HGGytdLVbhV7/6VZXjc+fO1XXXXafGjRsrKChIwcHBWrNmjXbu3Flp7h133KGAgP//67Bdu3aSpP79+7vNqxjft29fNZ1Ku3bt0qFDh/Tb3/7W7Tkvuugi/epXv9Knn36qoqKiah9/NhXn54wYMUKS5HA4NHz4cO3du9f1GgKojLAD+JF27dqpS5culW5NmzY952MnT56sP//5z/r00091++23KzIyUn369Kn2cvaf++mnnyTJdWjr5+Li4lzbK36Njo6uNK+qseqeMyMjQw899JC6du2qd955R59++qk2bNig2267TcXFxZXmN2/e3O1+o0aNzjp+8uTJKmv5eQ/V9ep0OpWfn1/t46tTWFiot99+WzfccIMuueQSHT16VEePHtXAgQPlcDg4URk4C87ZAVAjQUFBmjBhgiZMmKCjR49q9erVevLJJ3Xrrbdq//79Z72KKDIyUpKUk5Ojyy67zG3boUOHXOfrVMz74YcfKj1Hbm5ulas7Doej0tjixYvVq1cvzZkzx228sLDw7E16wc97PdOhQ4cUEBCgZs2anffzLl26VEVFRfr888+rfPzy5cuVn5/v0XMDtmNlB8B5u/jii/Vf//VfGjdunI4cOaLvv/9ekhQSEiJJlVZPbrnlFkmnQ8jPbdiwQTt37lSfPn0kSV27dlVISIjeeustt3mffvrpeV1x5HA4XLVU+PLLL92uhqorbdq00aWXXqolS5a4nfh94sQJvfPOO64rtM7X/PnzFRERoTVr1igrK8vtNmPGDJWUlOhvf/ubN1sBrMHKDoAaufPOO5WYmKguXbrokksu0d69ezVz5ky1bt1aCQkJkqSOHTtKkl566SUNGzZMwcHBatOmjdq0aaMHH3xQs2bNUkBAgG6//XbX1VgtW7bUo48+Kun0YaMJEyYoPT1dzZo108CBA3XgwAE9/fTTio2NdTsH5mySk5P1pz/9SVOnTlXPnj21a9cuPfPMM4qPj6/zz+EJCAjQ9OnTdd999yk5OVmjR49WSUmJZsyYoaNHj2ratGnn/Zzbt2/X559/roceesgVHH+ue/fueuGFFzR//nw9/PDD3mgDsAphB0CN9O7dW++8845ef/11FRQUKCYmRv369dNTTz2l4OBgSVKvXr00efJkLVq0SK+99pqcTqeysrJch5SuuOIKzZ8/Xy+//LKaNm2q2267Tenp6a5DP5L03HPPKTw8XHPnztWCBQvUtm1bzZkzR1OmTNHFF19co1qnTJmioqIizZ8/X9OnT1f79u01d+5cLV++3PW5P3VpyJAhCg8PV3p6uu655x4FBgbqxhtvVFZWlrp163bez1dxPs7o0aOr3B4cHKzhw4dr2rRp2rRpk6677rpa1Q/YxmFMDT5gAwB8aM+ePWrbtq2mTp2qJ5980tflAGhgCDsA6pWtW7dq6dKl6tatm5o0aaJdu3Zp+vTpKigo0Pbt26u9KgsAqsNhLAD1Snh4uL744gvNnz9fR48eVdOmTdWrVy8999xzBB0AHmFlBwAAWI1LzwEAgNUIOwAAwGqEHQAAYDVOUJbkdDp16NAhRUREVPnR8wAAoP4xxqiwsFBxcXFn/dBRwo5Of19Ny5YtfV0GAADwwP79+yt9797PEXYkRURESDr9YjVp0sRrz1tWVqZVq1YpKSnJ9Qmz/oLe/a93f+1bond/7N1f+5bqV+8FBQVq2bKl69/x6hB29P/fmtykSROvh52wsDA1adLE52+IC43e/a93f+1bond/7N1f+5bqZ+/nOgWFE5QBAIDVCDsAAMBqhB0AAGA1wg4AALAaYQcAAFiNsAMAAKxG2AEAAFYj7AAAAKsRdgAAgNUIOwAAwGqEHQAAYDXCDgAAsBphBwAAWI2wAwAArBbk6wL8wdatWxUQUH2ubNGihVq1anUBKwIAwH8QdurQgQMHJEk9evRQcXFxtfNCw8L0n507CTwAANQBwk4d+umnnyRJA596Uc1bX1nlnLw9u/X3Pzykw4cPE3YAAKgDhJ0L4JLWVyimXSdflwEAgF/iBGUAAGA1wg4AALAaYQcAAFiNsAMAAKxG2AEAAFYj7AAAAKsRdgAAgNUIOwAAwGqEHQAAYDXCDgAAsBphBwAAWI2wAwAArEbYAQAAViPsAAAAqxF2AACA1Qg7AADAaoQdAABgNcIOAACwGmEHAABYjbADAACsRtgBAABWI+wAAACrEXYAAIDVCDsAAMBqhB0AAGA1wg4AALAaYQcAAFiNsAMAAKxG2AEAAFYj7AAAAKsRdgAAgNUIOwAAwGqEHQAAYDXCDgAAsBphBwAAWI2wAwAArEbYAQAAViPsAAAAqxF2AACA1Qg7AADAaoQdAABgNcIOAACwGmEHAABYjbADAACs5tOwc+rUKf3hD39QfHy8QkND9Ytf/ELPPPOMnE6na44xRqmpqYqLi1NoaKh69eqlHTt2uD1PSUmJHnnkEbVo0ULh4eEaMGCADhw4cKHbAQAA9ZBPw87zzz+vuXPnavbs2dq5c6emT5+uGTNmaNasWa4506dPV0ZGhmbPnq0NGzYoJiZG/fr1U2FhoWtOSkqKli9frmXLlmn9+vU6fvy4kpOTVV5e7ou2AABAPRLky51/8sknuuuuu9S/f39J0uWXX66lS5fqiy++kHR6VWfmzJmaMmWKBg0aJElatGiRoqOjtWTJEo0ePVrHjh3T/Pnz9eabb6pv376SpMWLF6tly5ZavXq1br31Vt80BwAA6gWfhp2bb75Zc+fO1ddff62rrrpKW7du1fr16zVz5kxJ0p49e5Sbm6ukpCTXY0JCQtSzZ09lZ2dr9OjR2rhxo8rKytzmxMXFKTExUdnZ2VWGnZKSEpWUlLjuFxQUSJLKyspUVlbmtf4qDscFyijAearKOYEyCg0NldPp9Oq+fa2iF5t6qil/7d1f+5bo/ee/+gt/7VuqX73XtAafhp3HH39cx44dU9u2bRUYGKjy8nI999xz+s1vfiNJys3NlSRFR0e7PS46Olp79+51zWnUqJGaNWtWaU7F48+Unp6up59+utL4qlWrFBYWVuu+ztQjvEg68FmV29qES72XLtXBgwd18OBBr+/b1zIzM31dgs/4a+/+2rdE7/7IX/uW6kfvRUVFNZrn07Dz1ltvafHixVqyZIk6dOigLVu2KCUlRXFxcRo2bJhrnsPhcHucMabS2JnONmfy5MmaMGGC635BQYFatmyppKQkNWnSpBYdudu8ebNycnK07kSYott0rHLOoV3bNW/UAK1bt06dOnXy2r59raysTJmZmerXr5+Cg4N9Xc4F5a+9+2vfEr37Y+/+2rdUv3qvODJzLj4NO7///e/1xBNP6N5775UkdezYUXv37lV6erqGDRummJgYSadXb2JjY12Py8vLc632xMTEqLS0VPn5+W6rO3l5eerWrVuV+w0JCVFISEil8eDgYK/+4AICTp//XS6HnAFVv9Tlcqi4uFgBAQE+f9PUBW+/pg2Jv/bur31L9O6Pvftr31L96L2m+/fp1VhFRUWuQFAhMDDQda5LfHy8YmJi3JbKSktLtXbtWleQ6dy5s4KDg93m5OTkaPv27dWGHQAA4D98urJz55136rnnnlOrVq3UoUMHbd68WRkZGRoxYoSk04evUlJSlJaWpoSEBCUkJCgtLU1hYWEaMmSIJKlp06YaOXKkJk6cqMjISDVv3lyTJk1Sx44dXVdnAQAA/+XTsDNr1iw99dRTGjt2rPLy8hQXF6fRo0frj3/8o2vOY489puLiYo0dO1b5+fnq2rWrVq1apYiICNecF198UUFBQRo8eLCKi4vVp08fLVy4UIGBgb5oCwAA1CM+DTsRERGaOXOm61LzqjgcDqWmpio1NbXaOY0bN9asWbPcPowQAABA4ruxAACA5Qg7AADAaoQdAABgNcIOAACwGmEHAABYjbADAACsRtgBAABWI+wAAACrEXYAAIDVCDsAAMBqhB0AAGA1wg4AALAaYQcAAFiNsAMAAKxG2AEAAFYj7AAAAKsRdgAAgNUIOwAAwGqEHQAAYDXCDgAAsBphBwAAWI2wAwAArEbYAQAAViPsAAAAqxF2AACA1Qg7AADAaoQdAABgNcIOAACwGmEHAABYjbADAACsRtgBAABWI+wAAACrEXYAAIDVCDsAAMBqhB0AAGA1wg4AALAaYQcAAFiNsAMAAKxG2AEAAFYj7AAAAKsRdgAAgNUIOwAAwGqEHQAAYDXCDgAAsBphBwAAWI2wAwAArBbk6wJw2s6dO8+6vUWLFmrVqtUFqgYAAHsQdnys8PAPcgQE6P777z/rvNCwMP1n504CDwAA54mw42PFhQUyTqcGPztHUfEJVc7J27Nbf//DQzp8+DBhBwCA80TYqSei4hN0abtOvi4DAADrcIIyAACwGmEHAABYjbADAACsRtgBAABWI+wAAACrEXYAAIDVCDsAAMBqhB0AAGA1wg4AALAaYQcAAFiNsAMAAKxG2AEAAFYj7AAAAKsRdgAAgNV8HnYOHjyo+++/X5GRkQoLC9M111yjjRs3urYbY5Samqq4uDiFhoaqV69e2rFjh9tzlJSU6JFHHlGLFi0UHh6uAQMG6MCBAxe6FQAAUA/5NOzk5+ere/fuCg4O1nvvvaevvvpKL7zwgi6++GLXnOnTpysjI0OzZ8/Whg0bFBMTo379+qmwsNA1JyUlRcuXL9eyZcu0fv16HT9+XMnJySovL/dBVwAAoD4J8uXOn3/+ebVs2VILFixwjV1++eWu3xtjNHPmTE2ZMkWDBg2SJC1atEjR0dFasmSJRo8erWPHjmn+/Pl688031bdvX0nS4sWL1bJlS61evVq33nrrBe0JAADULz4NOytWrNCtt96qX//611q7dq0uvfRSjR07Vv/93/8tSdqzZ49yc3OVlJTkekxISIh69uyp7OxsjR49Whs3blRZWZnbnLi4OCUmJio7O7vKsFNSUqKSkhLX/YKCAklSWVmZysrKvNaf0+mUJAXKKMB5qso5QQEOhYaGnnVOoIxCQ0PldDq9Wl9dqqizodTrTf7au7/2LdH7z3/1F/7at1S/eq9pDQ5jjKnjWqrVuHFjSdKECRP061//Wp9//rlSUlL06quvaujQocrOzlb37t118OBBxcXFuR734IMPau/evVq5cqWWLFmiBx54wC28SFJSUpLi4+P16quvVtpvamqqnn766UrjS5YsUVhYmJe7BAAAdaGoqEhDhgzRsWPH1KRJk2rn+XRlx+l0qkuXLkpLS5MkXXvttdqxY4fmzJmjoUOHuuY5HA63xxljKo2d6WxzJk+erAkTJrjuFxQUqGXLlkpKSjrri3W+Nm/erJycHK07EaboNh2rnLN11b+0/E+P6sHXVyiuTWKVcw7t2q55owZo3bp16tSpk9fqq0tlZWXKzMxUv379FBwc7OtyLih/7d1f+5bo3R9799e+pfrVe8WRmXPxadiJjY1V+/bt3cbatWund955R5IUExMjScrNzVVsbKxrTl5enqKjo11zSktLlZ+fr2bNmrnN6datW5X7DQkJUUhISKXx4OBgr/7gAgJOn/9dLoecAVW/1KecRsXFxWedUy6HiouLFRAQ4PM31vny9mvakPhr7/7at0Tv/ti7v/Yt1Y/ea7p/n16N1b17d+3atctt7Ouvv1br1q0lSfHx8YqJiVFmZqZre2lpqdauXesKMp07d1ZwcLDbnJycHG3fvr3asAMAAPyHT1d2Hn30UXXr1k1paWkaPHiwPv/8c82bN0/z5s2TdPrwVUpKitLS0pSQkKCEhASlpaUpLCxMQ4YMkSQ1bdpUI0eO1MSJExUZGanmzZtr0qRJ6tixo+vqLAAA4L98Gnauv/56LV++XJMnT9Yzzzyj+Ph4zZw5U/fdd59rzmOPPabi4mKNHTtW+fn56tq1q1atWqWIiAjXnBdffFFBQUEaPHiwiouL1adPHy1cuFCBgYG+aAsAANQjPg07kpScnKzk5ORqtzscDqWmpio1NbXaOY0bN9asWbM0a9asOqgQAAA0ZD7/uggAAIC65FHY2bNnj7frAAAAqBMehZ0rr7xSvXv31uLFi3Xy5Elv1wQAAOA1HoWdrVu36tprr9XEiRMVExOj0aNH6/PPP/d2bQAAALXmUdhJTExURkaGDh48qAULFig3N1c333yzOnTooIyMDP3444/erhMAAMAjtTpBOSgoSAMHDtTf//53Pf/88/r22281adIkXXbZZRo6dKhycnK8VScAAIBHahV2vvjiC40dO1axsbHKyMjQpEmT9O233+qDDz7QwYMHddddd3mrTgAAAI949Dk7GRkZWrBggXbt2qU77rhDb7zxhu644w7Xd0FVfNt427ZtvVosAADA+fIo7MyZM0cjRozQAw884PqyzjO1atVK8+fPr1VxAAAAteVR2Nm9e/c55zRq1EjDhg3z5OkBAAC8xqNzdhYsWKC333670vjbb7+tRYsW1booAAAAb/Eo7EybNk0tWrSoNB4VFaW0tLRaFwUAAOAtHoWdvXv3Kj4+vtJ469attW/fvloXBQAA4C0ehZ2oqCh9+eWXlca3bt2qyMjIWhcFAADgLR6FnXvvvVe/+93vlJWVpfLycpWXl+uDDz7Q+PHjde+993q7RgAAAI95dDXWs88+q71796pPnz4KCjr9FE6nU0OHDuWcHQAAUK94FHYaNWqkt956S3/605+0detWhYaGqmPHjmrdurW36wMAAKgVj8JOhauuukpXXXWVt2oBAADwOo/CTnl5uRYuXKg1a9YoLy9PTqfTbfsHH3zgleIAAABqy6OwM378eC1cuFD9+/dXYmKiHA6Ht+sCAADwCo/CzrJly/T3v/9dd9xxh7frAQAA8CqPLj1v1KiRrrzySm/XAgAA4HUehZ2JEyfqpZdekjHG2/UAAAB4lUeHsdavX6+srCy999576tChg4KDg922v/vuu14pDgAAoLY8CjsXX3yxBg4c6O1aAAAAvM6jsLNgwQJv1wEAAFAnPDpnR5JOnTql1atX69VXX1VhYaEk6dChQzp+/LjXigMAAKgtj1Z29u7dq9tuu0379u1TSUmJ+vXrp4iICE2fPl0nT57U3LlzvV0nAACARzxa2Rk/fry6dOmi/Px8hYaGusYHDhyoNWvWeK04AACA2vL4aqyPP/5YjRo1chtv3bq1Dh486JXCAAAAvMGjlR2n06ny8vJK4wcOHFBEREStiwIAAPAWj8JOv379NHPmTNd9h8Oh48ePa+rUqXyFBAAAqFc8Ooz14osvqnfv3mrfvr1OnjypIUOGaPfu3WrRooWWLl3q7RoBAAA85lHYiYuL05YtW7R06VJt2rRJTqdTI0eO1H333ed2wjIAAICveRR2JCk0NFQjRozQiBEjvFkPAACAV3kUdt54442zbh86dKhHxQAAAHibR2Fn/PjxbvfLyspUVFSkRo0aKSwsjLADAADqDY+uxsrPz3e7HT9+XLt27dLNN9/MCcoAAKBe8fi7sc6UkJCgadOmVVr1AQAA8CWvhR1JCgwM1KFDh7z5lAAAALXi0Tk7K1ascLtvjFFOTo5mz56t7t27e6UwAAAAb/Ao7Nx9991u9x0Ohy655BLdcssteuGFF7xRFwAAgFd4FHacTqe36wAAAKgTXj1nBwAAoL7xaGVnwoQJNZ6bkZHhyS4AAAC8wqOws3nzZm3atEmnTp1SmzZtJElff/21AgMDdd1117nmORwO71QJAADgIY/Czp133qmIiAgtWrRIzZo1k3T6gwYfeOAB/fKXv9TEiRO9WiQAAICnPDpn54UXXlB6eror6EhSs2bN9Oyzz3I1FgAAqFc8CjsFBQX64YcfKo3n5eWpsLCw1kUBAAB4i0dhZ+DAgXrggQf0j3/8QwcOHNCBAwf0j3/8QyNHjtSgQYO8XSMAAIDHPDpnZ+7cuZo0aZLuv/9+lZWVnX6ioCCNHDlSM2bM8GqBAAAAteFR2AkLC9Mrr7yiGTNm6Ntvv5UxRldeeaXCw8O9XR8AAECt1OpDBXNycpSTk6OrrrpK4eHhMsZ4qy4AAACv8Cjs/PTTT+rTp4+uuuoq3XHHHcrJyZEkjRo1isvOAQBAveJR2Hn00UcVHBysffv2KSwszDV+zz336P333/dacQAAALXl0Tk7q1at0sqVK3XZZZe5jSckJGjv3r1eKQwAAMAbPFrZOXHihNuKToXDhw8rJCSk1kUBAAB4i0dhp0ePHnrjjTdc9x0Oh5xOp2bMmKHevXt7rTgAAIDa8ugw1owZM9SrVy998cUXKi0t1WOPPaYdO3boyJEj+vjjj71dIwAAgMc8Wtlp3769vvzyS91www3q16+fTpw4oUGDBmnz5s264oorvF0jAACAx857ZaesrExJSUl69dVX9fTTT9dFTQAAAF5z3is7wcHB2r59uxwOR13UAwAA4FUeHcYaOnSo5s+f7+1aAAAAvM6jE5RLS0v1+uuvKzMzU126dKn0nVgZGRleKQ4AAKC2zmtl57vvvpPT6dT27dt13XXXqUmTJvr666+1efNm123Lli0eFZKeni6Hw6GUlBTXmDFGqampiouLU2hoqHr16qUdO3a4Pa6kpESPPPKIWrRoofDwcA0YMEAHDhzwqAYAAGCf8wo7CQkJOnz4sLKyspSVlaWoqCgtW7bMdT8rK0sffPDBeRexYcMGzZs3T1dffbXb+PTp05WRkaHZs2drw4YNiomJUb9+/VRYWOiak5KSouXLl2vZsmVav369jh8/ruTkZJWXl593HQAAwD7nFXbO/Fbz9957TydOnKhVAcePH9d9992n1157Tc2aNXPb18yZMzVlyhQNGjRIiYmJWrRokYqKirRkyRJJ0rFjxzR//ny98MIL6tu3r6699lotXrxY27Zt0+rVq2tVFwAAsINH5+xUODP8eGLcuHHq37+/+vbtq2effdY1vmfPHuXm5iopKck1FhISop49eyo7O1ujR4/Wxo0bXZfCV4iLi1NiYqKys7N16623VrnPkpISlZSUuO4XFBRIOn1ZfVlZWa17quB0OiVJgTIKcJ6qck5QgEOhoaFnnRMoo9DQUDmdTq/WV5cq6mwo9XqTv/bur31L9P7zX/2Fv/Yt1a/ea1rDeYUdh8NR6ZLz2lyCvmzZMm3atEkbNmyotC03N1eSFB0d7TYeHR3t+rLR3NxcNWrUyG1FqGJOxeOrkp6eXuVnBK1atarK7/yqrR7hRdKBz6rc1qZ9jAYvXSrpRPVzwqXeS5fq4MGDOnjwoNfrq0uZmZm+LsFn/LV3f+1bond/5K99S/Wj96KiohrNO6+wY4zR8OHDXV/2efLkSY0ZM6bS1VjvvvvuOZ9r//79Gj9+vFatWqXGjRtXO+/MMGWMOWfAOtecyZMna8KECa77BQUFatmypZKSktSkSZNz1l5TmzdvVk5OjtadCFN0m45Vztm66l9a/qdH9eDrKxTXJrHKOYd2bde8UQO0bt06derUyWv11aWysjJlZmaqX79+Cg4O9nU5F5S/9u6vfUv07o+9+2vfUv3qveLIzLmcV9gZNmyY2/3777//fB7uZuPGjcrLy1Pnzp1dY+Xl5Vq3bp1mz56tXbt2STq9ehMbG+uak5eX51rtiYmJUWlpqfLz891Wd/Ly8tStW7dq9x0SElLlt7MHBwd79QcXEHD6lKhyOeQMqPqlPuU0Ki4uPuuccjlUXFysgIAAn7+xzpe3X9OGxF9799e+JXr3x979tW+pfvRe0/2fV9hZsGCBR8VUpU+fPtq2bZvb2AMPPKC2bdvq8ccf1y9+8QvFxMQoMzNT1157raTTn++zdu1aPf/885Kkzp07Kzg4WJmZmRo8eLAkKScnR9u3b9f06dO9VisAAGi4anWCcm1EREQoMdH9sE14eLgiIyNd4ykpKUpLS1NCQoISEhKUlpamsLAwDRkyRJLUtGlTjRw5UhMnTlRkZKSaN2+uSZMmqWPHjurbt+8F7wkAANQ/Pgs7NfHYY4+puLhYY8eOVX5+vrp27apVq1YpIiLCNefFF19UUFCQBg8erOLiYvXp00cLFy5UYGCgDysHAAD1Rb0KOx9++KHbfYfDodTUVKWmplb7mMaNG2vWrFmaNWtW3RYHAAAaJI++CBQAAKChIOwAAACrEXYAAIDVCDsAAMBqhB0AAGA1wg4AALAaYQcAAFiNsAMAAKxG2AEAAFYj7AAAAKsRdgAAgNUIOwAAwGqEHQAAYDXCDgAAsBphBwAAWI2wAwAArEbYAQAAViPsAAAAqxF2AACA1Qg7AADAaoQdAABgNcIOAACwGmEHAABYjbADAACsRtgBAABWI+wAAACrEXYAAIDVCDsAAMBqhB0AAGA1wg4AALAaYQcAAFiNsAMAAKxG2AEAAFYj7AAAAKsRdgAAgNUIOwAAwGqEHQAAYDXCDgAAsBphBwAAWI2wAwAArEbYAQAAViPsAAAAqxF2AACA1Qg7AADAaoQdAABgNcIOAACwGmEHAABYjbADAACsRtgBAABWI+wAAACrEXYAAIDVCDsAAMBqhB0AAGA1wg4AALAaYQcAAFiNsAMAAKxG2AEAAFYj7AAAAKsRdgAAgNUIOwAAwGqEHQAAYDXCDgAAsBphBwAAWI2wAwAArObTsJOenq7rr79eERERioqK0t13361du3a5zTHGKDU1VXFxcQoNDVWvXr20Y8cOtzklJSV65JFH1KJFC4WHh2vAgAE6cODAhWwFAADUUz4NO2vXrtW4ceP06aefKjMzU6dOnVJSUpJOnDjhmjN9+nRlZGRo9uzZ2rBhg2JiYtSvXz8VFha65qSkpGj58uVatmyZ1q9fr+PHjys5OVnl5eW+aAsAANQjQb7c+fvvv+92f8GCBYqKitLGjRvVo0cPGWM0c+ZMTZkyRYMGDZIkLVq0SNHR0VqyZIlGjx6tY8eOaf78+XrzzTfVt29fSdLixYvVsmVLrV69WrfeeusF7wsAANQfPg07Zzp27JgkqXnz5pKkPXv2KDc3V0lJSa45ISEh6tmzp7KzszV69Ght3LhRZWVlbnPi4uKUmJio7OzsKsNOSUmJSkpKXPcLCgokSWVlZSorK/NaP06nU5IUKKMA56kq5wQFOBQaGnrWOYEyCg0NldPp9Gp9damizoZSrzf5a+/+2rdE7z//1V/4a99S/eq9pjU4jDGmjmupEWOM7rrrLuXn5+ujjz6SJGVnZ6t79+46ePCg4uLiXHMffPBB7d27VytXrtSSJUv0wAMPuIUXSUpKSlJ8fLxeffXVSvtKTU3V008/XWl8yZIlCgsL83JnAACgLhQVFWnIkCE6duyYmjRpUu28erOy8/DDD+vLL7/U+vXrK21zOBxu940xlcbOdLY5kydP1oQJE1z3CwoK1LJlSyUlJZ31xTpfmzdvVk5OjtadCFN0m45Vztm66l9a/qdH9eDrKxTXJrHKOYd2bde8UQO0bt06derUyWv11aWysjJlZmaqX79+Cg4O9nU5F5S/9u6vfUv07o+9+2vfUv3qveLIzLnUi7DzyCOPaMWKFVq3bp0uu+wy13hMTIwkKTc3V7Gxsa7xvLw8RUdHu+aUlpYqPz9fzZo1c5vTrVu3KvcXEhKikJCQSuPBwcFe/cEFBJw+/7tcDjkDqn6pTzmNiouLzzqnXA4VFxcrICDA52+s8+Xt17Qh8dfe/bVvid79sXd/7VuqH73XdP8+vRrLGKOHH35Y7777rj744APFx8e7bY+Pj1dMTIwyMzNdY6WlpVq7dq0ryHTu3FnBwcFuc3JycrR9+/Zqww4AAPAfPl3ZGTdunJYsWaJ//etfioiIUG5uriSpadOmCg0NlcPhUEpKitLS0pSQkKCEhASlpaUpLCxMQ4YMcc0dOXKkJk6cqMjISDVv3lyTJk1Sx44dXVdnAQAA/+XTsDNnzhxJUq9evdzGFyxYoOHDh0uSHnvsMRUXF2vs2LHKz89X165dtWrVKkVERLjmv/jiiwoKCtLgwYNVXFysPn36aOHChQoMDLxQrQAAgHrKp2GnJheCORwOpaamKjU1tdo5jRs31qxZszRr1iwvVgcAAGzAd2MBAACrEXYAAIDVCDsAAMBqhB0AAGA1wg4AALAaYQcAAFiNsAMAAKxG2AEAAFYj7AAAAKsRdgAAgNUIOwAAwGqEHQAAYDXCDgAAsBphBwAAWI2wAwAArEbYAQAAViPsAAAAqxF2AACA1Qg7AADAaoQdAABgNcIOAACwGmEHAABYjbADAACsRtgBAABWI+wAAACrEXYAAIDVCDsAAMBqhB0AAGA1wg4AALAaYQcAAFiNsAMAAKxG2AEAAFYj7AAAAKsRdgAAgNUIOwAAwGqEHQAAYDXCDgAAsBphBwAAWI2wAwAArEbYAQAAViPsAAAAqxF2AACA1Qg7AADAaoQdAABgNcIOAACwGmEHAABYjbADAACsFuTrAgAAgHft27dPhw8fPuucFi1aqFWrVheoIt8i7AAAYJF9+/apbbt2Ki4qOuu80LAw/WfnTr8IPIQdAAAscvjwYRUXFWnws3MUFZ9Q5Zy8Pbv19z88pMOHDxN20PD489KlP/cOAGeKik/Qpe06+bqMeoGwYxF/Xrr0594BAGdH2LGIN5cuG9oqCcu2AIDqEHYsVNuly4a8SsKyLQDgTIQdVMIqCQDAJoQdVItVEgCADfgEZQAAYDVWduB3du7cedbt9enEawBA7RF24DcKD/8gR0CA7r///rPOq28nXje0K+MAoL4h7KBWqlslcTqdkqQDBw4oPj7+QpZUreLCAhmns0GdeN2Qr4wDgPqCsAOPnGuVJDQ0VEuXLlWX66/X5k2b6tU/wg3pxOv6eGVcdStNFQF369atioqK8kotrGoB8AbCDjxyrlWSQBlJJ1RcVFRvVkkasvoS0M620lQRcHv06CE5HLVeaWJVC4C3EHZQK9X9IxzgPCUd+MwHFV0YZ1txqI+H8LzlbCtNFQF34FMvasmTY2odci/0qpY/ryL5c+/wD4Qd4Dyda8WhPh/C85aqQm5FwL2k9RV1vi9vq4+rSBcqgNTH3i8kgp5/sCbsvPLKK5oxY4ZycnLUoUMHzZw5U7/85S99XRYsdK4VBw7hNTz17dyoCxlA6lvvF5K/Bz1/YkXYeeutt5SSkqJXXnlF3bt316uvvqrbb79dX331FW/OBqCh/s/KXw/hNUTneo9VXFVYX86N8kUAuVC916c/7+fzOn/00Udq166da/znJ+QHBATUqOb61Lu/sSLsZGRkaOTIkRo1apQkaebMmVq5cqXmzJmj9PR0H1eHs+F/VqhrNX2P1Uf1JXx5S339836217m6K09/fkJ+cXHxOWuur717Q0MIcQ0+7JSWlmrjxo164okn3MaTkpKUnZ3to6pQU/68hI4LoybvsV0fr1HmK/zHqK41xD/v1V15WnG4+sHXVyhnzzfnrLkh9l4TDSXENfiwc/jwYZWXlys6OtptPDo6Wrm5uVU+pqSkRCUlJa77x44dkyQdOXJEZWVlXqutoKBARUVF+mH39yopOlHlnPz936lx48b6Ydc2nSo6XuWcn/bvUePGjbVx40YVFBRUu7/du3d75blq8jznqjtQRi3Di2u8L1N6stp9mdKTF6RmyTuvT017l6SAgADXcrinfdX0/XGufdW2noq+f9j9fb3qvSbvMZWfqtW+nE6nioqK9NFHHykoKKhOX+ea1HMh93U+vXvrz3tN+qrJnPP5e+PMmo2MihzFOlVkzuvvqAvRe12/f37+M//2229lnE71GfE7NY2KrfI5juXl6OMl8/Tdd98pPDy82n15orCwUJJkjDn7RNPAHTx40Egy2dnZbuPPPvusadOmTZWPmTp1qpHEjRs3bty4cbPgtn///rNmhQa/stOiRQsFBgZWWsXJy8urtNpTYfLkyZowYYLrvtPp1JEjRxQZGSmHw+G12goKCtSyZUvt379fTZo08drzNgT07n+9+2vfEr37Y+/+2rdUv3o3xqiwsFBxcXFnndfgw06jRo3UuXNnZWZmauDAga7xzMxM3XXXXVU+JiQkRCEhIW5jF198cZ3V2KRJE5+/IXyF3v2vd3/tW6J3f+zdX/uW6k/vTZs2PeecBh92JGnChAn67W9/qy5duuimm27SvHnztG/fPo0ZM8bXpQEAAB+zIuzcc889+umnn/TMM88oJydHiYmJ+ve//63WrVv7ujQAAOBjVoQdSRo7dqzGjh3r6zLchISEaOrUqZUOmfkDeve/3v21b4ne/bF3f+1bapi9O4w51/VaAAAADVeArwsAAACoS4QdAABgNcIOAACwGmEHAABYjbBTh1555RXFx8ercePG6ty5sz766CNfl1Qr69at05133qm4uDg5HA7985//dNtujFFqaqri4uIUGhqqXr16aceOHW5zSkpK9Mgjj6hFixYKDw/XgAEDdODAgQvYxflLT0/X9ddfr4iICEVFRenuu+/Wrl273ObY2vucOXN09dVXuz487KabbtJ7773n2m5r32dKT0+Xw+FQSkqKa8zW3lNTU+VwONxuMTExru229l3h4MGDuv/++xUZGamwsDBdc8012rhxo2u7rf1ffvnllX7uDodD48aNk2RB37X8aipUY9myZSY4ONi89tpr5quvvjLjx4834eHhZu/evb4uzWP//ve/zZQpU8w777xjJJnly5e7bZ82bZqJiIgw77zzjtm2bZu55557TGxsrCkoKHDNGTNmjLn00ktNZmam2bRpk+ndu7fp1KmTOXXq1AXupuZuvfVWs2DBArN9+3azZcsW079/f9OqVStz/Phx1xxbe1+xYoX53//9X7Nr1y6za9cu8+STT5rg4GCzfft2Y4y9ff/c559/bi6//HJz9dVXm/Hjx7vGbe196tSppkOHDiYnJ8d1y8vLc223tW9jjDly5Ihp3bq1GT58uPnss8/Mnj17zOrVq80333zjmmNr/3l5eW4/88zMTCPJZGVlGWMaft+EnTpyww03mDFjxriNtW3b1jzxxBM+qsi7zgw7TqfTxMTEmGnTprnGTp48aZo2bWrmzp1rjDHm6NGjJjg42Cxbtsw15+DBgyYgIMC8//77F6z22srLyzOSzNq1a40x/tW7McY0a9bMvP76637Rd2FhoUlISDCZmZmmZ8+errBjc+9Tp041nTp1qnKbzX0bY8zjjz9ubr755mq3297/z40fP95cccUVxul0WtE3h7HqQGlpqTZu3KikpCS38aSkJGVnZ/uoqrq1Z88e5ebmuvUcEhKinj17unreuHGjysrK3ObExcUpMTGxQb0ux44dkyQ1b95ckv/0Xl5ermXLlunEiRO66aab/KLvcePGqX///urbt6/buO297969W3FxcYqPj9e9996r7777TpL9fa9YsUJdunTRr3/9a0VFRenaa6/Va6+95tpue/8VSktLtXjxYo0YMUIOh8OKvgk7deDw4cMqLy+v9K3r0dHRlb6d3RYVfZ2t59zcXDVq1EjNmjWrdk59Z4zRhAkTdPPNNysxMVGS/b1v27ZNF110kUJCQjRmzBgtX75c7du3t77vZcuWadOmTUpPT6+0zebeu3btqjfeeEMrV67Ua6+9ptzcXHXr1k0//fST1X1L0nfffac5c+YoISFBK1eu1JgxY/S73/1Ob7zxhiS7f+4/989//lNHjx7V8OHDJdnRtzVfF1EfORwOt/vGmEpjtvGk54b0ujz88MP68ssvtX79+krbbO29TZs22rJli44ePap33nlHw4YN09q1a13bbex7//79Gj9+vFatWqXGjRtXO8/G3m+//XbX7zt27KibbrpJV1xxhRYtWqQbb7xRkp19S5LT6VSXLl2UlpYmSbr22mu1Y8cOzZkzR0OHDnXNs7X/CvPnz9ftt9+uuLg4t/GG3DcrO3WgRYsWCgwMrJRm8/LyKiVjW1RcrXG2nmNiYlRaWqr8/Pxq59RnjzzyiFasWKGsrCxddtllrnHbe2/UqJGuvPJKdenSRenp6erUqZNeeuklq/veuHGj8vLy1LlzZwUFBSkoKEhr167VX/7yFwUFBblqt7H3M4WHh6tjx47avXu31T9zSYqNjVX79u3dxtq1a6d9+/ZJsv/PuiTt3btXq1ev1qhRo1xjNvRN2KkDjRo1UufOnZWZmek2npmZqW7duvmoqroVHx+vmJgYt55LS0u1du1aV8+dO3dWcHCw25ycnBxt3769Xr8uxhg9/PDDevfdd/XBBx8oPj7ebbvNvVfFGKOSkhKr++7Tp4+2bdumLVu2uG5dunTRfffdpy1btugXv/iFtb2fqaSkRDt37lRsbKzVP3NJ6t69e6WPlfj666/VunVrSf7xZ33BggWKiopS//79XWNW9H2hz4j2FxWXns+fP9989dVXJiUlxYSHh5vvv//e16V5rLCw0GzevNls3rzZSDIZGRlm8+bNrsvpp02bZpo2bWreffdds23bNvOb3/ymyksTL7vsMrN69WqzadMmc8stt9SbSxOr89BDD5mmTZuaDz/80O3SzKKiItccW3ufPHmyWbdundmzZ4/58ssvzZNPPmkCAgLMqlWrjDH29l2Vn1+NZYy9vU+cONF8+OGH5rvvvjOffvqpSU5ONhEREa6/u2zt25jTHzMQFBRknnvuObN7927zt7/9zYSFhZnFixe75tjcf3l5uWnVqpV5/PHHK21r6H0TdurQyy+/bFq3bm0aNWpkrrvuOtelyg1VVlaWkVTpNmzYMGPM6csyp06damJiYkxISIjp0aOH2bZtm9tzFBcXm4cfftg0b97chIaGmuTkZLNv3z4fdFNzVfUsySxYsMA1x9beR4wY4XoPX3LJJaZPnz6uoGOMvX1X5cywY2vvFZ+fEhwcbOLi4sygQYPMjh07XNtt7bvC//zP/5jExEQTEhJi2rZta+bNm+e23eb+V65caSSZXbt2VdrW0Pt2GGOMT5aUAAAALgDO2QEAAFYj7AAAAKsRdgAAgNUIOwAAwGqEHQAAYDXCDgAAsBphBwAAWI2wA6DeS01N1TXXXOPTGoYPH667777bpzUA8AxhB4BPORyOs96GDx+uSZMmac2aNb4uFUADFeTrAgD4t5ycHNfv33rrLf3xj390+zLG0NBQXXTRRbrooot8UR4AC7CyA8CnYmJiXLemTZvK4XBUGjvzMFbFIaW0tDRFR0fr4osv1tNPP61Tp07p97//vZo3b67LLrtMf/3rX932dfDgQd1zzz1q1qyZIiMjddddd+n7778/r3r//Oc/KzY2VpGRkRo3bpzKysq88CoAqEuEHQAN0gcffKBDhw5p3bp1ysjIUGpqqpKTk9WsWTN99tlnGjNmjMaMGaP9+/dLkoqKitS7d29ddNFFWrdundavX6+LLrpIt912m0pLS2u0z6ysLH377bfKysrSokWLtHDhQi1cuLAOuwTgDYQdAA1S8+bN9Ze//EVt2rTRiBEj1KZNGxUVFenJJ59UQkKCJk+erEaNGunjjz+WJC1btkwBAQF6/fXX1bFjR7Vr104LFizQvn379OGHH9Zon82aNdPs2bPVtm1bJScnq3///pxLBDQAnLMDoEHq0KGDAgL+//9r0dHRSkxMdN0PDAxUZGSk8vLyJEkbN27UN998o4iICLfnOXnypL799tsa7zMwMNB1PzY2Vtu2batNGwAuAMIOgAYpODjY7b7D4ahyzOl0SpKcTqc6d+6sv/3tb5We65JLLvF4nxXPD6D+IuwA8AvXXXed3nrrLUVFRalJkya+LgfABcQ5OwD8wn333acWLVrorrvu0kcffaQ9e/Zo7dq1Gj9+vA4cOODr8gDUIcIOAL8QFhamdevWqVWrVho0aJDatWunESNGqLi4mJUewHIOY4zxdREAAAB1hZUdAABgNcIOAEiur6So6vbRRx/5ujwAtcBhLACQ9M0331S77dJLL1VoaOgFrAaANxF2AACA1TiMBQAArEbYAQAAViPsAAAAqxF2AACA1Qg7AADAaoQdAABgNcIOAACwGmEHAABY7f8AeYJUA3JJLJ8AAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAkUAAAHFCAYAAAD8Jo2EAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAABDLUlEQVR4nO3df3zP9f7/8ft7v942Rpj9CmtpJJOKEs7xIzbJr+ikcipCkR+HcCr6dMw5QpykKNVpDTkzp6TjnArzcySlhZAj1fzeWhjDZr/ez+8fffd+97YfmPf23ux2vVzel3q/Xs/38/V4PfbGfa8f77fFGGMEAABQzXm4uwAAAIDKgFAEAAAgQhEAAIAkQhEAAIAkQhEAAIAkQhEAAIAkQhEAAIAkQhEAAIAkQhEAAIAkQhHgdgsXLpTFYtHXX39d7PpevXrphhtucFp2ww03aPDgwVe0na1btyomJkanT58uW6HV0LJly9SiRQv5+vrKYrFo586dl3zNypUrZbFYVL9+feXk5Fxy/Ouvvy6LxaLIyMhi16empur//u//1K5dOwUEBKh27dpq3bq13nnnHRUUFBQZf+7cOY0bN06hoaGqUaOGbrvtNiUkJDiNKSgo0Jw5c3TvvfeqYcOG8vPzU/PmzfX8889f8v3x3XffyWq1lvqeBaoqQhFQBa1YsUIvvvjiFb1m69atmjp1KqHoMv3yyy967LHH1KRJE61atUpffPGFmjZtesnXxcbGSpJOnTqljz/++JLj33vvPUnS3r179eWXXxZZn5ycrMWLF6tr165avHixli9frk6dOunpp5/Wk08+WWR8//79tWjRIk2ZMkWfffaZ7rzzTj3yyCOKj4+3j8nOzlZMTIzCwsI0d+5cffrpp3ryySf1zjvvqEOHDsrOzi621oKCAg0ZMkQBAQGX3C+gSjIA3CouLs5IMtu3by92fc+ePU1YWNhVb2f27NlGkklJSbnqucoiNzfX5OXluWXbZbFlyxYjySxbtuyyX5Oammq8vLzMPffcY2rUqGGioqJKHb99+3YjyfTs2dNIMk8++WSRMadOnTK5ublFlo8aNcpIMocPH7Yv++STT4wkEx8f7zQ2KirKhIaGmvz8fGOMMfn5+ebEiRNF5vzggw+MJPP+++8XW+/s2bPN9ddfb1577bVS37NAVcWRIqAKuvj0mc1m07Rp09SsWTP5+vrquuuu06233qrXXntNkhQTE6M///nPkqTw8HBZLBZZLBZt3LjR/vpZs2bp5ptvltVqVWBgoB5//HEdPXrUabvGGE2fPl1hYWGqUaOG2rRpo8TERHXu3FmdO3e2j9u4caMsFovef/99TZgwQddff72sVqt++OEH/fLLLxo5cqRuueUW1apVS4GBgbrnnnu0efNmp20dPHhQFotFs2fP1ssvv6wbbrhBvr6+6ty5s77//nvl5eXp+eefV2hoqOrUqaN+/fopPT39svq3cuVKtWvXTn5+fvL391dUVJS++OIL+/rBgwfrd7/7nSTpoYceksVicdq/kixatEj5+fl65pln1L9/f61bt06HDh0qcXzhUaWZM2eqffv2SkhIUFZWltOYunXrytvbu8hr77rrLkly+hmtWLFCtWrV0oMPPug09oknntDx48ftR6I8PT1Vv379Euc8cuRIkXUHDhzQX/7yF7355puqXbt2ifsEVGWEIqCSKCgoUH5+fpGHMeaSr501a5ZiYmL0yCOP6JNPPtGyZcs0dOhQ+6myYcOGacyYMZKkjz76SF988YW++OIL3XHHHZKkp59+Ws8995yioqK0cuVK/e1vf9OqVavUvn17nThxwr6dF154QS+88ILuvfde/fvf/9aIESM0bNgwff/998XWNWnSJB0+fFhvvfWW/vOf/ygwMFCnTp2SJE2ZMkWffPKJ4uLidOONN6pz5872kPZbb7zxhj7//HO98cYbevfdd/W///1PvXv31tChQ/XLL7/ovffe06xZs7R27VoNGzbskr2Kj49X3759Vbt2bS1dulSxsbHKyMhQ586dtWXLFknSiy++qDfeeEOSNH36dH3xxRd68803Lzn3e++9p5CQEPXo0UNDhgyRzWbTwoULix2bnZ2tpUuX6s4771RkZKSGDBmis2fP6oMPPrjkdiRp/fr18vLycjqlt2fPHjVv3lxeXl5OY2+99Vb7+kvNKUktWrRwWm6M0bBhw9SrVy/16dPnsuoDqiQ3H6kCqr3C02elPS4+fRYWFmYGDRpkf96rVy9z2223lbqdkk6f7du3z0gyI0eOdFr+5ZdfGklm8uTJxphfT+NYrVbz0EMPOY374osvjCTTqVMn+7INGzYYSaZjx46X3P/8/HyTl5dnunbtavr162dfnpKSYiSZVq1amYKCAvvyuXPnGkmmT58+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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# you can play around with histograms below to check distribution\n", + "# \n", + "# # Plot histogram\n", + "import matplotlib.pyplot as plt\n", + "\n", + "def plot_hist(df, value, name):\n", + " plt.hist(df[value], bins=50, color='skyblue', edgecolor='black')\n", + " plt.xlabel(f'{value}')\n", + " plt.ylabel('Frequency')\n", + " plt.title(f'Histogram of {name}')\n", + " plt.grid(True)\n", + " plt.show()\n", + "\n", + "hist_value = 'Time_h'\n", + "plot_hist(df_full, value = hist_value, name = 'Full')\n", + "plot_hist(df_Al, value = hist_value, name = 'Al')\n", + "plot_hist(df_AA2024, value = hist_value, name = 'AA2024')" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Number of entries in full dataset: 2011\n", + "Number of entries in full dataset with Time_h >= 1: 1638\n", + "Number of entries in full dataset with Time_h < 1: 373\n" + ] + } + ], + "source": [ + "# check filtering to see the effect of getting rid of some rows, to check whether its feasible to drop some columns\n", + "\n", + "def check_filter(dataset, column_name, filter):\n", + " print(f\"Number of entries in full dataset: {len(dataset)}\")\n", + " print(f\"Number of entries in full dataset with {column_name} >= {filter}: {len(dataset[dataset[column_name] >= filter])}\")\n", + " print(f\"Number of entries in full dataset with {column_name} < {filter}: {len(dataset[dataset[column_name] < filter])}\")\n", + "\n", + "\n", + "check_filter(dataset = df_Al, column_name = 'Time_h', filter = 1)\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 55, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "121" + ] + }, + "execution_count": 55, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# quick check to check the amount of unique compounds\n", + "filtered_df_Al = df_AA2024[df_AA2024['Time_h'] >= 1] # 123 to 121 compounds, maybe not much information loss for the small dataset...\n", + "len(filtered_df_Al['SMILES'].unique())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Now to create a new dataframe cleaned of unnecessary details for analysis. \n", + "Entries with synergy and encapsulation is removed, then unnecessary columns dropped." + ] + }, + { + "cell_type": "code", + "execution_count": 65, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "611" + ] + }, + "execution_count": 65, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def filter_dataframe_AA2024(df):\n", + " no_synergy_df = df[df['Synergistic_inhib'] == 'No']\n", + " no_encapsulation_df = no_synergy_df[no_synergy_df['Encapsulated'] == 'No']\n", + " filtered_df = no_encapsulation_df.drop(columns=['Inhibitor', 'Number', 'Metal', 'Alloy', 'Temperature_K', 'Salt_Concentrat_M', \n", + " 'Synergistic_inhib','Synergistic_inhib_type', 'Synergistic_inhib_Concentrat_M',\n", + " 'Encapsulated', 'Methodology','Reference', 'Link', 'Contributor'])\n", + " return filtered_df\n", + "\n", + "filtered_df_AA2024 = filter_dataframe_AA2024(df_AA2024)\n", + "len(filtered_df_AA2024['SMILES'])\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 611 datapoints for actual Bayesian optimization work. " + ] + }, + { + "cell_type": "code", + "execution_count": 92, + "metadata": {}, + "outputs": [], + "source": [ + "# save\n", + "filtered_df_AA2024.to_excel('filtered_AA2024.xlsx', index=False)" + ] + }, + { + "cell_type": "code", + "execution_count": 93, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "1966" + ] + }, + "execution_count": 93, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def filter_dataframe_Al(df):\n", + " no_synergy_df = df[df['Synergistic_inhib'] == 'No']\n", + " no_encapsulation_df = no_synergy_df[no_synergy_df['Encapsulated'] == 'No']\n", + " filtered_df = no_encapsulation_df.drop(columns=['Inhibitor', 'Number', 'Metal', 'Temperature_K', 'Salt_Concentrat_M', \n", + " 'Synergistic_inhib','Synergistic_inhib_type', 'Synergistic_inhib_Concentrat_M',\n", + " 'Encapsulated', 'Methodology','Reference', 'Link', 'Contributor'])\n", + " return filtered_df\n", + "\n", + "filtered_df_Al = filter_dataframe_Al(df_Al)\n", + "len(filtered_df_Al['SMILES'])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1966 datapoints, almost 3 times. Assuming we can just ignore the effect of alloy type, or find a way to featurize it, would be fun to work with. Maybe composition based?" + ] + }, + { + "cell_type": "code", + "execution_count": 94, + "metadata": {}, + "outputs": [], + "source": [ + "# save\n", + "filtered_df_Al.to_excel('filtered_Al.xlsx', index=False)" + ] + }, + { + "cell_type": "code", + "execution_count": 89, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "4708" + ] + }, + "execution_count": 89, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def filter_dataframe_full(df):\n", + " no_synergy_df = df[df['Synergistic_Inhib_type'].isnull()]\n", + " filtered_df = no_synergy_df.drop(columns=['Inhibitor', 'Index', 'Mol._weight', 'Temperature_K', 'Salt_Concentrat_M',\n", + " 'Synergistic_Inhib_type', 'Synergistic_Inhib_M','Methodology','Reference',\n", + " 'Contributor'])\n", + " return filtered_df\n", + "\n", + "filtered_df_full = filter_dataframe_full(df_full)\n", + "len(filtered_df_full['SMILES'])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 4708 datapoints, we more than double the previous. Again if we can jump to the featurization of alloy or substrate, super cool number to work with." + ] + }, + { + "cell_type": "code", + "execution_count": 91, + "metadata": {}, + "outputs": [], + "source": [ + "# save\n", + "filtered_df_full.to_excel('filtered_full.xlsx', index=False)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.11" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/filtered_AA2024.xlsx b/filtered_AA2024.xlsx new file mode 100644 index 0000000..618858a Binary files /dev/null and b/filtered_AA2024.xlsx differ diff --git a/filtered_Al.xlsx b/filtered_Al.xlsx new file mode 100644 index 0000000..75f1c1a Binary files /dev/null and b/filtered_Al.xlsx differ diff --git a/filtered_full.xlsx b/filtered_full.xlsx new file mode 100644 index 0000000..ecd6388 Binary files /dev/null and b/filtered_full.xlsx differ diff --git a/hello.py b/hello.py deleted file mode 100644 index 5b312bc..0000000 --- a/hello.py +++ /dev/null @@ -1,2 +0,0 @@ -def hello_world(): - return "Hello World!" diff --git a/hello_test.py b/hello_test.py deleted file mode 100644 index 708a061..0000000 --- a/hello_test.py +++ /dev/null @@ -1,5 +0,0 @@ -import hello - - -def test_hello(): - assert hello.hello_world() == "Hello World!"