{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Transform module of `mlcolvar`\n", " \n", "[![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/luigibonati/mlcolvar/blob/main/docs/notebooks/tutorials/adv_transforms.ipynb)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this noteboook, we will provide an overview of the `transform` module of the library.\n", "This includes non-trainable modules based on a parent `transform` class and divided into two groups:\n", "- `descriptors`: physical descriptors that can be computed from **atomic positions**, including, for example:\n", " - `PairwiseDistances`\n", " - `TorsionalAngle`\n", " - `CoordinationNumbers`\n", " \n", " Multiple descriptors can also be combined using the `MultipleDescriptors` class.\n", "- `tools`: processing tools and utilities, including, for example:\n", " - `Normalization`\n", " - `SwitchingFunctions`\n", " - `ContinuousHistogram`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Setup" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import torch\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", "\n", "from mlcolvar.utils.io import load_dataframe" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Computing descriptors with `mlcolvar`\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "All the descriptors classes share some general features:\n", "\n", "**Positions as input**\n", "\n", "Descriptors in `mlcolvar` take atomic positions as inputs. These can be also returned by `PLUMED` using the `POSITION` keyword for a simpler loading through colvar files.\n", "The positions can be used both as absolute coordinates (default) or as coordinates scaled on the cell's vectors. In this case, the `scaled_coords` key should be set to `True`. \n", "\n", "**Cell and PBC**\n", "\n", "Currently, PBC are implemented **only for orthorombic simulation cells**. By default, PBC are enabled, and the cell's dimensions have to be provided through the `cell` keyword \n", "\n", "**Combining descriptors**\n", "\n", "Multiple descriptors computed on the same set of positions (eventually of a diffent type) can be combined into a single transform object using `MultipleDescriptors`. For example, we can combine some torsional angles with some distances.\n", "\n", "Here we use alanine dipeptide as an example and we will first show how to compute the single decriptors and then how they can be combined." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "# number of atoms\n", "n_atoms=10\n", "\n", "# simulation cell \n", "cell = torch.Tensor([3.0233, 3.0233, 3.0233])\n", "\n", " \n", "filenames = ['https://raw.githubusercontent.com/EnricoTrizio/committor_2.0/refs/heads/main/alanine/unbiased_sims/COLVAR_A',\n", " 'https://raw.githubusercontent.com/EnricoTrizio/committor_2.0/refs/heads/main/alanine/unbiased_sims/COLVAR_B',\n", " ] \n", "\n", "# load data\n", "dataframe = load_dataframe(file_names = filenames,\n", " create_labels = True,\n", " return_dataframe = True,\n", " start=0,\n", " stop=10000,\n", " stride=10,\n", " verbose = True)\n", "\n", "# we put the positions into a tensor\n", "positions = torch.Tensor(dataframe.filter(regex='p[1-9]\\.[abc]|p[1-2][0-9]\\.[abc]').values) " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### TorsionalAngle\n", "Torsional angles can be computed using the `TorsionalAngle` class, which can return the sin, cos and angle value based on the `mode` key.\n", "\n", "Here we compute the sin and cos of the usual $\\phi$ and $\\psi$ angles of alanine." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "torch.Size([2000, 2])\n", "torch.Size([2000, 2])\n" ] } ], "source": [ "from mlcolvar.core.transform.descriptors import TorsionalAngle\n", "\n", "# initialize objects to compute angles\n", "# this computes the sin and cos of Phi, to return also the angle add 'angle' to the mode list.\n", "ComputePhi = TorsionalAngle(indices=[1,3,4,6],\n", " n_atoms=10,\n", " mode=['sin', 'cos'],\n", " PBC=True, \n", " cell=cell, \n", " scaled_coords=True)\n", "\n", "# this computes the sin and cos of Psi to return also the angle add 'angle' to the mode list.\n", "ComputePsi = TorsionalAngle(indices=[3,4,6,8],\n", " n_atoms=10,\n", " mode=['sin', 'cos'], \n", " PBC=True, \n", " cell=cell, \n", " scaled_coords=True)\n", "\n", "# we apply it on the input positions\n", "out_phi = ComputePhi(positions)\n", "out_psi = ComputePsi(positions)\n", "\n", "print(out_phi.shape)\n", "print(out_psi.shape)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### PairwiseDistances\n", "Pairwise distances can be computed using the `PairwiseDistances` class, which, by default, computes all the non-duplicated distances between the given atoms. Otherwise, if we are interested in some specific distances only we can choose the corresponing atomic paris using the `slicing_pairs` keyword. " ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "torch.Size([2000, 45])\n", "torch.Size([2000, 3])\n" ] } ], "source": [ "from mlcolvar.core.transform.descriptors import PairwiseDistances\n", "\n", "# compute ALL the non duplicated distances within the given set of atoms\n", "# initialize object to compute all distances\n", "ComputeDistances = PairwiseDistances(n_atoms=10, \n", " PBC=True, \n", " cell=cell, \n", " scaled_coords=True)\n", "\n", "# we apply it to the positions\n", "out_dist = ComputeDistances(positions)\n", "\n", "print(out_dist.shape)\n", "\n", "# compute only some specific distances within the given set of atoms\n", "# initialize object to compute distances between atom pairs: 0:1 2:3 4:5\n", "ComputeDistances_red = PairwiseDistances(n_atoms=10, \n", " PBC=True, \n", " cell=cell, \n", " scaled_coords=True,\n", " slicing_pairs=[[0, 1],\n", " [2, 3],\n", " [4, 5],])\n", "\n", "# we apply it to the positions\n", "out_dist_red = ComputeDistances_red(positions)\n", "\n", "print(out_dist_red.shape)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### CoordinationNumbers\n", "The coordination number of a group A of atoms with respect to those from a group B based on a cutoff radius can be computed using the `CoordinationNumbers` class.\n", "the overall behaviour of this class mimics the one of `COORDINATION` in `PLUMED`." ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "torch.Size([2000, 2])\n" ] } ], "source": [ "from mlcolvar.core.transform.descriptors import CoordinationNumbers\n", "from mlcolvar.core.transform.tools import SwitchingFunctions\n", "\n", "# to make the coordiantion numbers derivable we need to apply a switching function for the cutoff\n", "# more details are given below\n", "# here it's important to note that the optional dmax ensures that at cutoff the switch value is zero, similarly to PLUMED\n", "switching_function = SwitchingFunctions(in_features=10*3, # n_atoms*3\n", " name='Rational',\n", " cutoff=0.1,\n", " dmax=0.1,\n", " options={'n': 6, 'm': 12}\n", " )\n", "\n", "# compute the coordination of atoms 0 and 9 with respect to the others\n", "ComputeCoord = CoordinationNumbers(group_A=[0, 9],\n", " group_B=[1,2,3,4,5,6,7,8],\n", " cutoff=0.1, \n", " n_atoms=10, \n", " PBC=True, \n", " cell=cell,\n", " mode='continuous', # there's also a discontinuous mode with a sharp cutoff that is not derivable but can be used for analysis\n", " switching_function=switching_function,\n", " dmax=0.1\n", " )\n", "\n", "# we apply it to the positions\n", "out_coord = ComputeCoord(positions)\n", "\n", "print(out_coord.shape)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Combining descriptors with `mlcolvar`\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Multiple and different descriptors acting on the same positions can be combine using the `MultipleDescriptors` class, which takes a list of descriptor objects and combines them into a single model." ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "torch.Size([2000, 49])\n" ] } ], "source": [ "from mlcolvar.core.transform.descriptors import MultipleDescriptors\n", "\n", "# we combine the descriptors\n", "ComputeDescriptors = MultipleDescriptors(descriptors_list=[ComputePhi, # two outputs \n", " ComputePsi, # two outputs\n", " ComputeDistances # three outputs\n", " ], \n", " n_atoms=n_atoms)\n", "\n", "# we applied the combined model to the input positions\n", "out_combined = ComputeDescriptors(positions)\n", "\n", "print(out_combined.shape)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Processing tools in `mlcolvar`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The transform objects in `tools` are used for general processing of data.\n", "Here we'll see two examples:\n", "- `SwitchingFunctions`, which can be used, for example, to define contacts from distances\n", "- `ContinuousHistograms`, which can be used, for example, to build differentiable CVs related to the distribution of some input. \n", " " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### SwitchingFunctions\n", "Switching functions can be used to *switch* some input above and below a threshold and are avaialble using the `SwitchingFunction` class.\n", "\n", "For example, we can use this to turn our distances into contacts, which may be more suitable to describe the on/off nature of chemical reactions." ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "torch.Size([2000, 45])\n" ] } ], "source": [ "from mlcolvar.core.transform.tools import SwitchingFunctions\n", "\n", "# initialize object to compute switching function\n", "ComputeSwitch = SwitchingFunctions(in_features=45,\n", " name='Rational',\n", " cutoff=0.3,\n", " options={'n': 6, 'm': 12})\n", "\n", "# we apply to the distances\n", "out_contacts = ComputeSwitch(out_dist)\n", "\n", "print(out_contacts.shape)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### ContinuousHistogram\n", "\n", "Continuous histograms can be computed using the `ContinuousHistogram` class, which allows constructing differentiable histograms using Gaussian kernels returning the values of the bins.\n", "\n", "We can test this on the distances and contacts in our system" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "data": { "image/png": "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OPfcc4v250nve/PEE0/gc5/7HIYMGYKqqircc889iEQiNo3WHuvWrcP111+PCRMmwOVyYfny5Tkfs3btWlx88cXweDw4++yz8eKLL5o7KCGhpUuXioqKCvH888+L3bt3i7vuukuMHDlStLS0pL1+w4YNwu12i0cffVTs2bNH/PrXvxaDBg0SO3futHnk1tP73nz7298WTz31lNi2bZvYu3evuP3220VlZaVoaGiweeTW0vu+pNTW1orTTjtNXHnlleKGG26wZ7A20vu+RKNRcemll4prr71WrF+/XtTW1oq1a9eK7du32zxy6+l9b1566SXh8XjESy+9JGpra8WqVavE+PHjxT333GPzyK21YsUKcd9994nXX39dABDLli3Len1NTY0YOnSoWLBggdizZ4948sknhdvtFitXrjRtTFIGqhkzZoj58+f3fK0oipgwYYKorq5Oe/23vvUtcd111/W5b+bMmeL73/++peN0gt73pr9EIiGGDx8uFi9ebNUQHWHkfUkkEuLyyy8Xf/nLX8S8efOKMlDpfV+efvppMWnSJBGLxewaomP0vjfz588XX/7yl/vct2DBAjF79mxLx+kkLYHqX//1X8XUqVP73HfzzTeLa665xrRxSFf6i8Vi2LJlC+bMmdNzX1lZGebMmYOPP/447WM+/vjjPtcDwDXXXJPx+kJl5L3pLxQKIR6PY/To0VYN03ZG35d/+7d/w9ixY/G9733PjmHazsj78sYbb2DWrFmYP38+xo0bh2nTpuGRRx6Boih2DdsWRt6byy+/HFu2bOkpD9bU1GDFihW49tprbRmzrOz4/Wv77um5tLe3Q1EUjBs3rs/948aNw759+9I+prm5Oe31zc3Nlo3TCUbem/5++ctfYsKECQO+sQqZkfdl/fr1eO6557B9+3YbRugMI+9LTU0N3nvvPdx6661YsWIFDh06hB/96EeIx+O4//777Ri2LYy8N9/+9rfR3t6OK664AkIIJBIJ/OAHP8CvfvUrO4YsrUy/f30+H8LhMIYMGZL3a0iXUZF1Fi1ahKVLl2LZsmUYPHiw08NxjN/vx2233YZnn30Wp5xyitPDkYqqqhg7diz+/Oc/45JLLsHNN9+M++67D88884zTQ3Pc2rVr8cgjj+A///M/sXXrVrz++ut466238NBDDzk9tKInXUZ1yimnwO12o6Wlpc/9LS0tOPXUU9M+5tRTT9V1faEy8t6kPPbYY1i0aBFWr16N6dOnWzlM2+l9Xw4fPowjR47g+uuv77lPVVUAQHl5Ofbv34/JkydbO2gbGPl+GT9+PAYNGgS3291z33nnnYfm5mbEYjFUVFRYOma7GHlvfvOb3+C2227DP//zPwMALrjgAgSDQdx999247777ch7+V6wy/f4dMWKEKdkUIGFGVVFRgUsuuQRr1qzpuU9VVaxZswazZs1K+5hZs2b1uR4A3n333YzXFyoj7w0APProo3jooYewcuVKXHrppXYM1VZ635cpU6Zg586d2L59e8/t7/7u73D11Vdj+/btqKqqsnP4ljHy/TJ79mwcOnSoJ3ADwIEDBzB+/PiiCVKAsfcmFAoNCEapgC5KeG9vW37/mtaWYaKlS5cKj8cjXnzxRbFnzx5x9913i5EjR4rm5mYhhBC33XabuPfee3uu37BhgygvLxePPfaY2Lt3r7j//vuLuj1dz3uzaNEiUVFRIf72t7+Jpqamnpvf73fqr2AJve9Lf8Xa9af3fTl69KgYPny4+PGPfyz2798v3nzzTTF27Fjxu9/9zqm/gmX0vjf333+/GD58uHjllVdETU2NeOedd8TkyZPFt771Laf+Cpbw+/1i27ZtYtu2bQKAePzxx8W2bdtEXV2dEEKIe++9V9x2220916fa03/xi1+IvXv3iqeeeqo02tOFEOLJJ58UEydOFBUVFWLGjBli48aNPX921VVXiXnz5vW5/tVXXxXnnnuuqKioEFOnThVvvfWWzSO2j5735owzzhAABtzuv/9++wduMb3fM70Va6ASQv/78tFHH4mZM2cKj8cjJk2aJB5++GGRSCRsHrU99Lw38XhcPPDAA2Ly5Mli8ODBoqqqSvzoRz8SXV1d9g/cQu+//37a3xmp92LevHniqquuGvCYiy66SFRUVIhJkyaJF154wdQx8TwqIiKSmnRzVERERL0xUBERkdQYqIiISGoMVEREJDUGKiIikhoDFRERSY2BioiIpMZARUREUmOgIiIiqTFQERGR1BioiIhIav8flSrG3z6UMFUAAAAASUVORK5CYII=", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from mlcolvar.core.transform.tools import ContinuousHistogram\n", "\n", "# we initialize the object for the histogram computation \n", "ComputeHistogram = ContinuousHistogram(in_features=45,\n", " min=0,\n", " max=1, \n", " bins=100)\n", "\n", "# we apply it to the distances\n", "out_hist_dist = ComputeHistogram(out_dist)\n", "# we apply it to the contacts\n", "out_hist_contacts = ComputeHistogram(out_contacts)\n", "\n", "# we compare the two distributions\n", "plt.figure(figsize=(5,4))\n", "plt.fill_between(np.linspace(0, 1, 100), 0, out_hist_dist.mean(axis=0), alpha=0.8)\n", "plt.fill_between(np.linspace(0, 1, 100), 0, out_hist_contacts.mean(axis=0), alpha=0.8)\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Sequentially apply transforms in `mlcolvar` \n", "To apply sequentially different transforms we can simply use a `torch.nn.Sequential` class." ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [ { "data": { "image/png": "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UkBi98bv9/dIRp0JXQzgvb1N+f2r27IMHS1dulQ4nU6xcOFCsW/fPnH//feLYcOGifr6eiGEEHfeead47LHHutpv3LhRpKWliZdeekns379fzJkzJ6WXp8dzb+bOnSsyMjLE3//+d1FXV9f18Xq9Vv0rGCLe+3KiVF31F+99qaqqEllZWeKBBx4QBw8eFJ9++qkYPXq0eO6556z6VzBMvPdmzpw5IisrS7z//vuirKxMfPHFF+K0004Tt9xyi1X/Cobwer1ix44dYseOHQKAePnll8WOHTtEZWWlEEKIxx57TNx5551d7TuXp//2t78V+/fvF/PmzRsYy9OFEOLVV18VJ510ksjIyBCXXHKJKCws7Pre5ZdfLmbOnNmt/bJly8QZZ5whMjIyxKRJk8Rnn31mcsTmiefenHzyyQJAj8+cOXPMD9xg8f7MfFuqJioh4r8vmzZtElOmTBFOp1Oceuqp4vnnnxfhcNjkqM0Rz70JhULi6aefFqeddprIzMwUeXl54le/+pVobW01P3ADffnllxF/Z3Tei5kzZ4rLL7+8xznf+973REZGhjj11FPFggULdI2J9aiIiEhq0j2jIiIi+jYmKiIikhoTFRERSY2JioiIpMZERUREUmOiIiIiqTFRERGR1JioiIhIakxUREQkNSYqIiKSGhMVERFJ7f8D1poYsCjyssEAAAAASUVORK5CYII=", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "ComputeContactsHist = torch.nn.Sequential(ComputeDistances, ComputeSwitch, ComputeHistogram)\n", "\n", "# we initialize the object for the computation positions -> distances -> contacts -> histogram\n", "out_sequential = ComputeContactsHist(positions)\n", "\n", "# we compare the two distributions\n", "plt.figure(figsize=(5,4))\n", "plt.fill_between(np.linspace(0, 1, 100), 0, out_sequential.mean(axis=0), alpha=0.8)\n", "plt.fill_between(np.linspace(0, 1, 100), 0, out_hist_contacts.mean(axis=0), alpha=0.8)\n", "plt.show()\n" ] } ], "metadata": { "kernelspec": { "display_name": "graph_mlcolvar_test_2.5", "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.9.18" } }, "nbformat": 4, "nbformat_minor": 2 }