{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Conformer Ensembles\n", "\n", "The `ConformerEnsemble` takes everything available in `Molecule` and extends this to many different conformers of a molecule." ] }, { "cell_type": "code", "execution_count": 81, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ConformerEnsemble(name='pentane', formula='C5 H12', n_conformers=7)\n" ] } ], "source": [ "# Imports molli\n", "import molli as ml\n", "\n", "# Imports numpy \n", "import numpy as np\n", "\n", "#Loads Conformer Ensemble\n", "ens = ml.ConformerEnsemble.load_mol2(ml.files.pentane_confs_mol2)\n", "print(ens)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Conformer ensembles are made up of individual molecules referred to as conformers. These can also be iterated and sliced as if it was a list. " ] }, { "cell_type": "code", "execution_count": 82, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Conformer(name='pentane', conf_id=0)\n", "Conformer(name='pentane', conf_id=1)\n", "Conformer(name='pentane', conf_id=2)\n", "Conformer(name='pentane', conf_id=3)\n", "Conformer(name='pentane', conf_id=4)\n", "Conformer(name='pentane', conf_id=5)\n", "Conformer(name='pentane', conf_id=6)\n" ] } ], "source": [ "#Iterates through each conformer\n", "for i, conformer in enumerate(ens):\n", " print(conformer)" ] }, { "cell_type": "code", "execution_count": 83, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Conformer(name='pentane', conf_id=2)\n" ] } ], "source": [ "#Prints the third conformer in the ensemble\n", "print(ens[2])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Key Properties of Conformer Ensemble\n", "\n", "`coords` represent all coordinates of all conformers, and are shaped by (n_conformers, n_atoms, n_dimensions)" ] }, { "cell_type": "code", "execution_count": 84, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[[-2.8045e+00 3.9964e+00 -1.4128e+00]\n", " [-2.7484e+00 3.3174e+00 -5.3600e-02]\n", " [-3.6840e+00 4.6446e+00 -1.4767e+00]\n", " [-2.8678e+00 3.2576e+00 -2.2181e+00]\n", " [-1.9154e+00 4.6126e+00 -1.5806e+00]\n", " [-1.5288e+00 2.4040e+00 6.6300e-02]\n", " [-3.6655e+00 2.7359e+00 9.5900e-02]\n", " [-2.7185e+00 4.0835e+00 7.2990e-01]\n", " [-2.2860e-01 3.1846e+00 -1.2460e-01]\n", " [-1.5920e+00 1.6061e+00 -6.8380e-01]\n", " [-1.5265e+00 1.9213e+00 1.0512e+00]\n", " [-8.9200e-02 4.2949e+00 9.0460e-01]\n", " [-2.0010e-01 3.6206e+00 -1.1300e+00]\n", " [ 6.2870e-01 2.5066e+00 -4.0400e-02]\n", " [-9.1500e-01 5.0091e+00 8.2550e-01]\n", " [ 8.4720e-01 4.8399e+00 7.4960e-01]\n", " [-8.1700e-02 3.8889e+00 1.9212e+00]]\n", "\n", " [[-2.7298e+00 4.4129e+00 1.0005e+00]\n", " [-2.7484e+00 3.3174e+00 -5.3600e-02]\n", " [-3.6107e+00 5.0541e+00 8.9640e-01]\n", " [-1.8387e+00 5.0405e+00 8.9840e-01]\n", " [-2.7368e+00 3.9871e+00 2.0090e+00]\n", " [-1.5288e+00 2.4040e+00 6.6300e-02]\n", " [-2.7735e+00 3.7765e+00 -1.0488e+00]\n", " [-3.6668e+00 2.7289e+00 5.5600e-02]\n", " [-2.2860e-01 3.1846e+00 -1.2460e-01]\n", " [-1.5920e+00 1.6061e+00 -6.8380e-01]\n", " [-1.5265e+00 1.9213e+00 1.0512e+00]\n", " [-1.6270e-01 3.8294e+00 -1.4999e+00]\n", " [ 6.2990e-01 2.5144e+00 -3.0000e-04]\n", " [-1.4590e-01 3.9636e+00 6.4210e-01]\n", " [-2.1040e-01 3.0736e+00 -2.2903e+00]\n", " [ 7.7480e-01 4.3823e+00 -1.6147e+00]\n", " [-9.9070e-01 4.5309e+00 -1.6443e+00]]\n", "\n", " [[-4.0432e+00 2.5483e+00 1.5460e-01]\n", " [-2.7484e+00 3.3174e+00 -5.3600e-02]\n", " [-4.9021e+00 3.2207e+00 6.4500e-02]\n", " [-4.0725e+00 2.0912e+00 1.1488e+00]\n", " [-4.1528e+00 1.7552e+00 -5.9200e-01]\n", " [-1.5288e+00 2.4040e+00 6.6300e-02]\n", " [-2.6852e+00 4.1224e+00 6.8780e-01]\n", " [-2.7652e+00 3.7884e+00 -1.0434e+00]\n", " [-2.2860e-01 3.1846e+00 -1.2460e-01]\n", " [-1.5920e+00 1.6061e+00 -6.8380e-01]\n", " [-1.5265e+00 1.9213e+00 1.0512e+00]\n", " [ 9.8660e-01 2.2767e+00 -2.1500e-02]\n", " [-1.5320e-01 3.9735e+00 6.3270e-01]\n", " [-2.2900e-01 3.6748e+00 -1.1051e+00]\n", " [ 1.0344e+00 1.7952e+00 9.6040e-01]\n", " [ 1.9050e+00 2.8554e+00 -1.6120e-01]\n", " [ 9.5810e-01 1.4947e+00 -7.8710e-01]]\n", "\n", " [[-4.0432e+00 2.5483e+00 1.5460e-01]\n", " [-2.7484e+00 3.3174e+00 -5.3600e-02]\n", " [-4.9021e+00 3.2207e+00 6.4500e-02]\n", " [-4.0725e+00 2.0912e+00 1.1488e+00]\n", " [-4.1528e+00 1.7552e+00 -5.9200e-01]\n", " [-1.5288e+00 2.4040e+00 6.6300e-02]\n", " [-2.6852e+00 4.1224e+00 6.8780e-01]\n", " [-2.7652e+00 3.7884e+00 -1.0434e+00]\n", " [-2.2860e-01 3.1846e+00 -1.2460e-01]\n", " [-1.5920e+00 1.6061e+00 -6.8380e-01]\n", " [-1.5265e+00 1.9213e+00 1.0512e+00]\n", " [-8.9200e-02 4.2949e+00 9.0460e-01]\n", " [-2.0010e-01 3.6206e+00 -1.1300e+00]\n", " [ 6.2870e-01 2.5066e+00 -4.0400e-02]\n", " [-9.1500e-01 5.0091e+00 8.2550e-01]\n", " [ 8.4720e-01 4.8399e+00 7.4960e-01]\n", " [-8.1700e-02 3.8889e+00 1.9212e+00]]\n", "\n", " [[-4.0432e+00 2.5483e+00 1.5460e-01]\n", " [-2.7484e+00 3.3174e+00 -5.3600e-02]\n", " [-4.9021e+00 3.2207e+00 6.4500e-02]\n", " [-4.0725e+00 2.0912e+00 1.1488e+00]\n", " [-4.1528e+00 1.7552e+00 -5.9200e-01]\n", " [-1.5288e+00 2.4040e+00 6.6300e-02]\n", " [-2.6852e+00 4.1224e+00 6.8780e-01]\n", " [-2.7652e+00 3.7884e+00 -1.0434e+00]\n", " [-2.2860e-01 3.1846e+00 -1.2460e-01]\n", " [-1.5920e+00 1.6061e+00 -6.8380e-01]\n", " [-1.5265e+00 1.9213e+00 1.0512e+00]\n", " [-1.6270e-01 3.8294e+00 -1.4999e+00]\n", " [ 6.2990e-01 2.5144e+00 -3.0000e-04]\n", " [-1.4590e-01 3.9636e+00 6.4210e-01]\n", " [-2.1040e-01 3.0736e+00 -2.2903e+00]\n", " [ 7.7480e-01 4.3823e+00 -1.6147e+00]\n", " [-9.9070e-01 4.5309e+00 -1.6443e+00]]\n", "\n", " [[-2.8045e+00 3.9964e+00 -1.4128e+00]\n", " [-2.7484e+00 3.3174e+00 -5.3600e-02]\n", " [-3.6840e+00 4.6446e+00 -1.4767e+00]\n", " [-2.8678e+00 3.2576e+00 -2.2181e+00]\n", " [-1.9154e+00 4.6126e+00 -1.5806e+00]\n", " [-1.5288e+00 2.4040e+00 6.6300e-02]\n", " [-3.6655e+00 2.7359e+00 9.5900e-02]\n", " [-2.7185e+00 4.0835e+00 7.2990e-01]\n", " [-2.2860e-01 3.1846e+00 -1.2460e-01]\n", " [-1.5920e+00 1.6061e+00 -6.8380e-01]\n", " [-1.5265e+00 1.9213e+00 1.0512e+00]\n", " [ 9.8660e-01 2.2767e+00 -2.1500e-02]\n", " [-1.5320e-01 3.9735e+00 6.3270e-01]\n", " [-2.2900e-01 3.6748e+00 -1.1051e+00]\n", " [ 1.0344e+00 1.7952e+00 9.6040e-01]\n", " [ 1.9050e+00 2.8554e+00 -1.6120e-01]\n", " [ 9.5810e-01 1.4947e+00 -7.8710e-01]]\n", "\n", " [[-2.7298e+00 4.4129e+00 1.0005e+00]\n", " [-2.7484e+00 3.3174e+00 -5.3600e-02]\n", " [-3.6107e+00 5.0541e+00 8.9640e-01]\n", " [-1.8387e+00 5.0405e+00 8.9840e-01]\n", " [-2.7368e+00 3.9871e+00 2.0090e+00]\n", " [-1.5288e+00 2.4040e+00 6.6300e-02]\n", " [-2.7735e+00 3.7765e+00 -1.0488e+00]\n", " [-3.6668e+00 2.7289e+00 5.5600e-02]\n", " [-2.2860e-01 3.1846e+00 -1.2460e-01]\n", " [-1.5920e+00 1.6061e+00 -6.8380e-01]\n", " [-1.5265e+00 1.9213e+00 1.0512e+00]\n", " [ 9.8660e-01 2.2767e+00 -2.1500e-02]\n", " [-1.5320e-01 3.9735e+00 6.3270e-01]\n", " [-2.2900e-01 3.6748e+00 -1.1051e+00]\n", " [ 1.0344e+00 1.7952e+00 9.6040e-01]\n", " [ 1.9050e+00 2.8554e+00 -1.6120e-01]\n", " [ 9.5810e-01 1.4947e+00 -7.8710e-01]]]\n" ] } ], "source": [ "#Prints the shape of the ensemble coordinates\n", "np.shape(ens.coords)\n", "\n", "print(ens.coords)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`atomic_charges` represent the atomic charges of individual atoms for all conformers and are shaped (n_conformers, n_atoms)" ] }, { "cell_type": "code", "execution_count": 85, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Shape of Atomic Charge Array\n", "(7, 17)\n", "\n" ] }, { "data": { "text/plain": [ "array([[-0.0653, -0.0559, 0.023 , 0.023 , 0.023 , -0.0536, 0.0263,\n", " 0.0263, -0.0559, 0.0265, 0.0265, -0.0653, 0.0263, 0.0263,\n", " 0.023 , 0.023 , 0.023 ],\n", " [-0.0653, -0.0559, 0.023 , 0.023 , 0.023 , -0.0536, 0.0263,\n", " 0.0263, -0.0559, 0.0265, 0.0265, -0.0653, 0.0263, 0.0263,\n", " 0.023 , 0.023 , 0.023 ],\n", " [-0.0653, -0.0559, 0.023 , 0.023 , 0.023 , -0.0536, 0.0263,\n", " 0.0263, -0.0559, 0.0265, 0.0265, -0.0653, 0.0263, 0.0263,\n", " 0.023 , 0.023 , 0.023 ],\n", " [-0.0653, -0.0559, 0.023 , 0.023 , 0.023 , -0.0536, 0.0263,\n", " 0.0263, -0.0559, 0.0265, 0.0265, -0.0653, 0.0263, 0.0263,\n", " 0.023 , 0.023 , 0.023 ],\n", " [-0.0653, -0.0559, 0.023 , 0.023 , 0.023 , -0.0536, 0.0263,\n", " 0.0263, -0.0559, 0.0265, 0.0265, -0.0653, 0.0263, 0.0263,\n", " 0.023 , 0.023 , 0.023 ],\n", " [-0.0653, -0.0559, 0.023 , 0.023 , 0.023 , -0.0536, 0.0263,\n", " 0.0263, -0.0559, 0.0265, 0.0265, -0.0653, 0.0263, 0.0263,\n", " 0.023 , 0.023 , 0.023 ],\n", " [-0.0653, -0.0559, 0.023 , 0.023 , 0.023 , -0.0536, 0.0263,\n", " 0.0263, -0.0559, 0.0265, 0.0265, -0.0653, 0.0263, 0.0263,\n", " 0.023 , 0.023 , 0.023 ]])" ] }, "execution_count": 85, "metadata": {}, "output_type": "execute_result" } ], "source": [ "#Finds the shape of the ensemble coordinates\n", "charge_shape = np.shape(ens.atomic_charges)\n", "print(f'Shape of Atomic Charge Array\\n{charge_shape}\\n')\n", "\n", "#Finds the Atomic Charges set for each conformer\n", "ens.atomic_charges" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`weights` represent defined weights of individual conformers, which can be useful for boltzmann weighting or other operations, and it is shaped (n_conformers,)" ] }, { "cell_type": "code", "execution_count": 86, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([1., 1., 1., 1., 1., 1., 1.])" ] }, "execution_count": 86, "metadata": {}, "output_type": "execute_result" } ], "source": [ "#Gives the weights of individual conformers\n", "ens.weights" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Key Methods in `ConformerEnsemble`\n", "\n", "Conformer ensembles have a few key methods that allow transformations of all coordinates at once.\n", "\n", "`translate` moves all atoms in all conformers by the vector specified" ] }, { "cell_type": "code", "execution_count": 87, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[[27.1955 3.9964 -1.4128]\n", " [27.2516 3.3174 -0.0536]\n", " [26.316 4.6446 -1.4767]\n", " [27.1322 3.2576 -2.2181]\n", " [28.0846 4.6126 -1.5806]]\n", "\n", " [[27.2702 4.4129 1.0005]\n", " [27.2516 3.3174 -0.0536]\n", " [26.3893 5.0541 0.8964]\n", " [28.1613 5.0405 0.8984]\n", " [27.2632 3.9871 2.009 ]]\n", "\n", " [[25.9568 2.5483 0.1546]\n", " [27.2516 3.3174 -0.0536]\n", " [25.0979 3.2207 0.0645]\n", " [25.9275 2.0912 1.1488]\n", " [25.8472 1.7552 -0.592 ]]\n", "\n", " [[25.9568 2.5483 0.1546]\n", " [27.2516 3.3174 -0.0536]\n", " [25.0979 3.2207 0.0645]\n", " [25.9275 2.0912 1.1488]\n", " [25.8472 1.7552 -0.592 ]]\n", "\n", " [[25.9568 2.5483 0.1546]\n", " [27.2516 3.3174 -0.0536]\n", " [25.0979 3.2207 0.0645]\n", " [25.9275 2.0912 1.1488]\n", " [25.8472 1.7552 -0.592 ]]\n", "\n", " [[27.1955 3.9964 -1.4128]\n", " [27.2516 3.3174 -0.0536]\n", " [26.316 4.6446 -1.4767]\n", " [27.1322 3.2576 -2.2181]\n", " [28.0846 4.6126 -1.5806]]\n", "\n", " [[27.2702 4.4129 1.0005]\n", " [27.2516 3.3174 -0.0536]\n", " [26.3893 5.0541 0.8964]\n", " [28.1613 5.0405 0.8984]\n", " [27.2632 3.9871 2.009 ]]]\n" ] } ], "source": [ "#This translates all coordinates over by 2 units in the x direction\n", "ens.translate([30,0,0])\n", "\n", "#This prints the first 5 coordinates of each conformer\n", "print(ens.coords[:, 0:5, :])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`center_at_atom` translates coordinates of the ensemble placing a specified atom at the origin" ] }, { "cell_type": "code", "execution_count": 88, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[[ 0. 0. 0. ]\n", " [ 0.0561 -0.679 1.3592]\n", " [-0.8795 0.6482 -0.0639]\n", " [-0.0633 -0.7388 -0.8053]\n", " [ 0.8891 0.6162 -0.1678]]\n", "\n", " [[ 0. 0. 0. ]\n", " [-0.0186 -1.0955 -1.0541]\n", " [-0.8809 0.6412 -0.1041]\n", " [ 0.8911 0.6276 -0.1021]\n", " [-0.007 -0.4258 1.0085]]\n", "\n", " [[ 0. 0. 0. ]\n", " [ 1.2948 0.7691 -0.2082]\n", " [-0.8589 0.6724 -0.0901]\n", " [-0.0293 -0.4571 0.9942]\n", " [-0.1096 -0.7931 -0.7466]]\n", "\n", " [[ 0. 0. 0. ]\n", " [ 1.2948 0.7691 -0.2082]\n", " [-0.8589 0.6724 -0.0901]\n", " [-0.0293 -0.4571 0.9942]\n", " [-0.1096 -0.7931 -0.7466]]\n", "\n", " [[ 0. 0. 0. ]\n", " [ 1.2948 0.7691 -0.2082]\n", " [-0.8589 0.6724 -0.0901]\n", " [-0.0293 -0.4571 0.9942]\n", " [-0.1096 -0.7931 -0.7466]]\n", "\n", " [[ 0. 0. 0. ]\n", " [ 0.0561 -0.679 1.3592]\n", " [-0.8795 0.6482 -0.0639]\n", " [-0.0633 -0.7388 -0.8053]\n", " [ 0.8891 0.6162 -0.1678]]\n", "\n", " [[ 0. 0. 0. ]\n", " [-0.0186 -1.0955 -1.0541]\n", " [-0.8809 0.6412 -0.1041]\n", " [ 0.8911 0.6276 -0.1021]\n", " [-0.007 -0.4258 1.0085]]]\n" ] } ], "source": [ "#This gets the first atom of the conformer ensemble shared with all conformers\n", "atom = ens.get_atom(0)\n", "\n", "#This centers the conformer ensemble\n", "ens.center_at_atom(atom)\n", "\n", "#This prints the first 5 coordinates of each conformer\n", "print(ens.coords[:, 0:5, :])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`rotate` rotates coordinates by a set rotation matrix" ] }, { "cell_type": "code", "execution_count": 89, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[[ 0. 0. 0. ]\n", " [ 0.0561 1.3592 0.679 ]\n", " [-0.8795 -0.0639 -0.6482]\n", " [-0.0633 -0.8053 0.7388]\n", " [ 0.8891 -0.1678 -0.6162]]\n", "\n", " [[ 0. 0. 0. ]\n", " [-0.0186 -1.0541 1.0955]\n", " [-0.8809 -0.1041 -0.6412]\n", " [ 0.8911 -0.1021 -0.6276]\n", " [-0.007 1.0085 0.4258]]\n", "\n", " [[ 0. 0. 0. ]\n", " [ 1.2948 -0.2082 -0.7691]\n", " [-0.8589 -0.0901 -0.6724]\n", " [-0.0293 0.9942 0.4571]\n", " [-0.1096 -0.7466 0.7931]]\n", "\n", " [[ 0. 0. 0. ]\n", " [ 1.2948 -0.2082 -0.7691]\n", " [-0.8589 -0.0901 -0.6724]\n", " [-0.0293 0.9942 0.4571]\n", " [-0.1096 -0.7466 0.7931]]\n", "\n", " [[ 0. 0. 0. ]\n", " [ 1.2948 -0.2082 -0.7691]\n", " [-0.8589 -0.0901 -0.6724]\n", " [-0.0293 0.9942 0.4571]\n", " [-0.1096 -0.7466 0.7931]]\n", "\n", " [[ 0. 0. 0. ]\n", " [ 0.0561 1.3592 0.679 ]\n", " [-0.8795 -0.0639 -0.6482]\n", " [-0.0633 -0.8053 0.7388]\n", " [ 0.8891 -0.1678 -0.6162]]\n", "\n", " [[ 0. 0. 0. ]\n", " [-0.0186 -1.0541 1.0955]\n", " [-0.8809 -0.1041 -0.6412]\n", " [ 0.8911 -0.1021 -0.6276]\n", " [-0.007 1.0085 0.4258]]]\n" ] } ], "source": [ "#This rotates the coordinates 90 degrees around the x axis (i.e. X stays the same, Y and Z invert)\n", "rot_matrix = np.array([[1,0,0],[0,0,-1],[0,1,0]])\n", "\n", "#This rotates the coordinates 90 degrees around the x axis\n", "ens.rotate(rot_matrix) \n", "\n", "#This prints the first 5 coordinates of each conformer\n", "print(ens.coords[:, 0:5, :])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Potential Unexpected Behavior\n", "\n", "It's important to note that the structure of the `ConformerEnsemble` class operates with a baseline connectivity, atoms, bonds, and attributes. \n", "\n", "The only thing changing between individual conformers are the coordinates of the atoms, and as such, no attempt should be made to alter these properties unless you would like to affect all conformers within the ensemble.\n", "\n", "This may lead to unexpected behavior if not used correctly when operating with individual conformers. One example of this is attempting to set an attribute on an individual `Conformer`, which inadvertently sets attributes for the full ensemble." ] }, { "cell_type": "code", "execution_count": 90, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Original ensemble attributes: {}\n", "Reprinting the ensemble attributes: {'New': 1}\n" ] } ], "source": [ "#This prints the attributes in the Conformer Ensemble\n", "print(f'Original ensemble attributes: {ens.attrib}')\n", "\n", "#This uses Conformer 3 of the ensemble\n", "conf3 = ens[2]\n", "\n", "#This ATTEMPTS to set a new attribute to only Conformer 3\n", "conf3.attrib[\"New\"] = 1\n", "\n", "#The full ensemble now has this property\n", "print(f'Reprinting the ensemble attributes: {ens.attrib}')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As a result, each conformer now has this property" ] }, { "cell_type": "code", "execution_count": 91, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Conformer = Conformer(name='pentane', conf_id=0), Attributes = {'New': 1}\n", "Conformer = Conformer(name='pentane', conf_id=1), Attributes = {'New': 1}\n", "Conformer = Conformer(name='pentane', conf_id=2), Attributes = {'New': 1}\n", "Conformer = Conformer(name='pentane', conf_id=3), Attributes = {'New': 1}\n", "Conformer = Conformer(name='pentane', conf_id=4), Attributes = {'New': 1}\n", "Conformer = Conformer(name='pentane', conf_id=5), Attributes = {'New': 1}\n", "Conformer = Conformer(name='pentane', conf_id=6), Attributes = {'New': 1}\n" ] } ], "source": [ "#This prints the conformers and their associated attributes\n", "for conf in ens:\n", " print(f'Conformer = {conf}, Attributes = {conf.attrib}')" ] } ], "metadata": { "kernelspec": { "display_name": "dev-blake", "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.11.6" }, "orig_nbformat": 4 }, "nbformat": 4, "nbformat_minor": 2 }