{
  "id": 452056,
  "title": "Representing SMILES Notation as 2D array",
  "url": "/competitions/open-problems-single-cell-perturbations/discussion/452056",
  "author_name": "Arpit",
  "post_date": "2023-10-31T17:37:54.716000",
  "votes": 4,
  "comment_count": 0,
  "views": 0,
  "content": "<p>I'm sharing a method which allows you to convert SMILES Notation to a 2D numpy array, The numpy array contains atomic numbers of the elements mentioned in the SMILES Notation as well as bond values.</p>\n<p>Link to the notebook: <a href=\"https://www.kaggle.com/code/arpitytlinux/smilesto2darray\" target=\"_blank\">https://www.kaggle.com/code/arpitytlinux/smilesto2darray</a></p>\n<p>Here's how it works in a nutshell:</p>\n<h2>Part 1: Adding Atomic numbers as values</h2>\n<p>We first make a 2D array of size 256, 256. This size was chosen because during testing I concluded that the max coordinates can do upto 200 for both axes</p>\n<p><code>map_array = np.zeros((256,256))</code></p>\n<p>Then we use pysmiles to convert SMILES string to a NetworkX graph of nodes and edges</p>\n<pre><code>smiles_string = \nmol = read_smiles(smiles_string) \n</code></pre>\n<p>A NetworkX graph looks like this (Blue circles are called Nodes and the lines connecting the Nodes are called Edges)</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F13007289%2F22ccb62fb6ebcd414d45d56d4b2ef927%2FScreenshot%202023-11-01%20134605.png?generation=1698826665378200&amp;alt=media\" alt=\"\"></p>\n<p>Then we use <code>spring_layout</code> provided by NetworkX to calculate the x, y coordinates of nodes in a given graph, This returns a dictionary which we can use to find out the x, y coordinates of a given node</p>\n<p><code>pos = nx.spring_layout(mol)</code></p>\n<p>Then we adjust the x,y coordinates and store it in a new dictionary because we need to make it compatible with our array (Some coordinates can be in negative and there is no -2 element in our array!), We do this by multiplying it by 100 to make some space between the elements and easier to round it off to integers then adding the lowest value which spring_layout can have which I concluded was -100, So we add +100 to make it minimum of 0</p>\n<pre><code>node_location = {}\n\n\n node  mol.nodes():\n    x,y = pos[node]\n    x,y = (x*) + , (y*) + \n    x,y = (x), (y)\n\n    node_location[node] = [[x,y], mol.nodes[node][]]\n</code></pre>\n<p>Then we need a method to convert the element name or <code>mol.nodes[node][\"element\"]</code> into atomic number, For that we can use PyAstronomy</p>\n<pre><code> PyAstronomy  pyasl\n\nan = pyasl.AtomicNo()\n</code></pre>\n<p>Using <code>an</code> we can now convert element name to atomic number to put in the array, Now we can just loop through the dictionary and add values to our array</p>\n<p>Before looping we store all the points that the atoms use to help with the bond mapping algorithm in the future</p>\n<pre><code>taken_points = []\n\n\n i  node_location.keys():\n    x = node_location[i][][]\n    y = node_location[i][][]\n\n\n    atomic_number = an.getAtomicNo(node_location[i][])\n\n    map_array[x][y] = atomic_number\n\n    taken_points.append([x,y])\n</code></pre>\n<p>Now <code>map_array</code> looks like this</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F13007289%2Fe50aea858a8c8e2a8e7fdc84a9fd383b%2FScreenshot%202023-11-01%20135616.png?generation=1698827204871062&amp;alt=media\" alt=\"\"></p>\n<h2>Part 2: Mapping bonds using an algorithm</h2>\n<p>Since the edges connecting the nodes are ideal lines, they don't use x, y coordinates. So we have to use an algorithm to map out bonds ourselves</p>\n<p>The algorithm I wrote notes down x, y coordinates of the atom which the bond goes to, It starts with the atom which bonds comes from and considers all nearby points which are directly connected to it (This can only be 8 points in a 2D plane) and then selects the one with the least distance from the points of the target x, y coordinates and puts the value of the bond at the point and continues from that point and repeat until there's no nearby points left or the target x, y coordinates are part of the nearby points</p>\n<p>Here's the code for it:</p>\n<pre><code> edge  mol.edges():\n    current_atom = edge[]\n    target_atom = edge[]\n\n    target_x,target_y = node_location[target_atom][]\n\n    current_atom_x, current_atom_y = node_location[current_atom][]\n\n    available_nearby_points = get_available_nearby_points(current_atom_x, current_atom_y, )\n    nearby_points = get_nearby_points(current_atom_x, current_atom_y, )\n\n\n     [target_x,target_y]   nearby_points:\n        least_distance = \n        selected_point = \n\n         (available_nearby_points) == :\n            \n\n         i  available_nearby_points:\n            distance = math.sqrt( ((target_x - i[]) ** ) + ((target_y - i[]) ** ) )\n             least_distance == :\n                least_distance = distance\n                selected_point = i\n\n             least_distance &gt; distance:\n                least_distance = distance\n                selected_point = i\n\n\n\n        taken_points.append(selected_point)\n        map_array[selected_point[]][selected_point[]] = (mol.edges[edge][]) / \n\n\n        available_nearby_points = get_available_nearby_points(selected_point[], selected_point[], )\n        nearby_points = get_nearby_points(selected_point[], selected_point[], )\n</code></pre>\n<p>Here's a GIF to visualize the algorithm</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F13007289%2F9238d3133b8050744d6d61272dff6c41%2Falgorithm.gif?generation=1698830719615758&amp;alt=media\" alt=\"\"></p>\n<p>Now <code>map_array</code> looks like this</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F13007289%2F2956eb6af621cec205b0381adc9ed798%2Fbondmap.png?generation=1698828157183311&amp;alt=media\" alt=\"\"></p>\n<p>Now we apply max pooling of size 4 to turn the size of the array from 256, 256, to 64, 64 without loosing any meaningful information<br>\nAfter applying max pooling <code>map_array</code> will look like this</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F13007289%2Fd98049fd8f27f981523b801cbf44bfc6%2Ffinalmap.png?generation=1698828271218825&amp;alt=media\" alt=\"\"></p>\n<p>The full code is in the linked notebook.</p>\n<p>Thanks for reading!</p>",
  "messages": [
    {
      "id": 2507016,
      "postDate": "2023-10-31T17:37:54.717Z",
      "content": "<p>I'm sharing a method which allows you to convert SMILES Notation to a 2D numpy array, The numpy array contains atomic numbers of the elements mentioned in the SMILES Notation as well as bond values.</p>\n<p>Link to the notebook: <a href=\"https://www.kaggle.com/code/arpitytlinux/smilesto2darray\" target=\"_blank\">https://www.kaggle.com/code/arpitytlinux/smilesto2darray</a></p>\n<p>Here's how it works in a nutshell:</p>\n<h2>Part 1: Adding Atomic numbers as values</h2>\n<p>We first make a 2D array of size 256, 256. This size was chosen because during testing I concluded that the max coordinates can do upto 200 for both axes</p>\n<p><code>map_array = np.zeros((256,256))</code></p>\n<p>Then we use pysmiles to convert SMILES string to a NetworkX graph of nodes and edges</p>\n<pre><code>smiles_string = \nmol = read_smiles(smiles_string) \n</code></pre>\n<p>A NetworkX graph looks like this (Blue circles are called Nodes and the lines connecting the Nodes are called Edges)</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F13007289%2F22ccb62fb6ebcd414d45d56d4b2ef927%2FScreenshot%202023-11-01%20134605.png?generation=1698826665378200&amp;alt=media\" alt=\"\"></p>\n<p>Then we use <code>spring_layout</code> provided by NetworkX to calculate the x, y coordinates of nodes in a given graph, This returns a dictionary which we can use to find out the x, y coordinates of a given node</p>\n<p><code>pos = nx.spring_layout(mol)</code></p>\n<p>Then we adjust the x,y coordinates and store it in a new dictionary because we need to make it compatible with our array (Some coordinates can be in negative and there is no -2 element in our array!), We do this by multiplying it by 100 to make some space between the elements and easier to round it off to integers then adding the lowest value which spring_layout can have which I concluded was -100, So we add +100 to make it minimum of 0</p>\n<pre><code>node_location = {}\n\n\n node  mol.nodes():\n    x,y = pos[node]\n    x,y = (x*) + , (y*) + \n    x,y = (x), (y)\n\n    node_location[node] = [[x,y], mol.nodes[node][]]\n</code></pre>\n<p>Then we need a method to convert the element name or <code>mol.nodes[node][\"element\"]</code> into atomic number, For that we can use PyAstronomy</p>\n<pre><code> PyAstronomy  pyasl\n\nan = pyasl.AtomicNo()\n</code></pre>\n<p>Using <code>an</code> we can now convert element name to atomic number to put in the array, Now we can just loop through the dictionary and add values to our array</p>\n<p>Before looping we store all the points that the atoms use to help with the bond mapping algorithm in the future</p>\n<pre><code>taken_points = []\n\n\n i  node_location.keys():\n    x = node_location[i][][]\n    y = node_location[i][][]\n\n\n    atomic_number = an.getAtomicNo(node_location[i][])\n\n    map_array[x][y] = atomic_number\n\n    taken_points.append([x,y])\n</code></pre>\n<p>Now <code>map_array</code> looks like this</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F13007289%2Fe50aea858a8c8e2a8e7fdc84a9fd383b%2FScreenshot%202023-11-01%20135616.png?generation=1698827204871062&amp;alt=media\" alt=\"\"></p>\n<h2>Part 2: Mapping bonds using an algorithm</h2>\n<p>Since the edges connecting the nodes are ideal lines, they don't use x, y coordinates. So we have to use an algorithm to map out bonds ourselves</p>\n<p>The algorithm I wrote notes down x, y coordinates of the atom which the bond goes to, It starts with the atom which bonds comes from and considers all nearby points which are directly connected to it (This can only be 8 points in a 2D plane) and then selects the one with the least distance from the points of the target x, y coordinates and puts the value of the bond at the point and continues from that point and repeat until there's no nearby points left or the target x, y coordinates are part of the nearby points</p>\n<p>Here's the code for it:</p>\n<pre><code> edge  mol.edges():\n    current_atom = edge[]\n    target_atom = edge[]\n\n    target_x,target_y = node_location[target_atom][]\n\n    current_atom_x, current_atom_y = node_location[current_atom][]\n\n    available_nearby_points = get_available_nearby_points(current_atom_x, current_atom_y, )\n    nearby_points = get_nearby_points(current_atom_x, current_atom_y, )\n\n\n     [target_x,target_y]   nearby_points:\n        least_distance = \n        selected_point = \n\n         (available_nearby_points) == :\n            \n\n         i  available_nearby_points:\n            distance = math.sqrt( ((target_x - i[]) ** ) + ((target_y - i[]) ** ) )\n             least_distance == :\n                least_distance = distance\n                selected_point = i\n\n             least_distance &gt; distance:\n                least_distance = distance\n                selected_point = i\n\n\n\n        taken_points.append(selected_point)\n        map_array[selected_point[]][selected_point[]] = (mol.edges[edge][]) / \n\n\n        available_nearby_points = get_available_nearby_points(selected_point[], selected_point[], )\n        nearby_points = get_nearby_points(selected_point[], selected_point[], )\n</code></pre>\n<p>Here's a GIF to visualize the algorithm</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F13007289%2F9238d3133b8050744d6d61272dff6c41%2Falgorithm.gif?generation=1698830719615758&amp;alt=media\" alt=\"\"></p>\n<p>Now <code>map_array</code> looks like this</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F13007289%2F2956eb6af621cec205b0381adc9ed798%2Fbondmap.png?generation=1698828157183311&amp;alt=media\" alt=\"\"></p>\n<p>Now we apply max pooling of size 4 to turn the size of the array from 256, 256, to 64, 64 without loosing any meaningful information<br>\nAfter applying max pooling <code>map_array</code> will look like this</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F13007289%2Fd98049fd8f27f981523b801cbf44bfc6%2Ffinalmap.png?generation=1698828271218825&amp;alt=media\" alt=\"\"></p>\n<p>The full code is in the linked notebook.</p>\n<p>Thanks for reading!</p>",
      "rawMarkdown": "I'm sharing a method which allows you to convert SMILES Notation to a 2D numpy array, The numpy array contains atomic numbers of the elements mentioned in the SMILES Notation as well as bond values.\n\nLink to the notebook: [https://www.kaggle.com/code/arpitytlinux/smilesto2darray](https://www.kaggle.com/code/arpitytlinux/smilesto2darray)\n\nHere's how it works in a nutshell:\n\n## Part 1: Adding Atomic numbers as values\n\nWe first make a 2D array of size 256, 256. This size was chosen because during testing I concluded that the max coordinates can do upto 200 for both axes\n\n`map_array = np.zeros((256,256))`\n\nThen we use pysmiles to convert SMILES string to a NetworkX graph of nodes and edges\n\n```python\nsmiles_string = \"COC(=O)N(C)c1c(N)nc(-c2nn(Cc3ccccc3F)c3ncccc23)nc1N\"\nmol = read_smiles(smiles_string) \n```\n\nA NetworkX graph looks like this (Blue circles are called Nodes and the lines connecting the Nodes are called Edges)\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F13007289%2F22ccb62fb6ebcd414d45d56d4b2ef927%2FScreenshot%202023-11-01%20134605.png?generation=1698826665378200&alt=media)\n\nThen we use `spring_layout` provided by NetworkX to calculate the x, y coordinates of nodes in a given graph, This returns a dictionary which we can use to find out the x, y coordinates of a given node\n\n`pos = nx.spring_layout(mol)`\n\nThen we adjust the x,y coordinates and store it in a new dictionary because we need to make it compatible with our array (Some coordinates can be in negative and there is no -2 element in our array!), We do this by multiplying it by 100 to make some space between the elements and easier to round it off to integers then adding the lowest value which spring_layout can have which I concluded was -100, So we add +100 to make it minimum of 0\n\n```python\nnode_location = {}\n\n\nfor node in mol.nodes():\n    x,y = pos[node]\n    x,y = (x*100) + 100, (y*100) + 100\n    x,y = int(x), int(y)\n    \n    node_location[node] = [[x,y], mol.nodes[node][\"element\"]]\n```\n\nThen we need a method to convert the element name or `mol.nodes[node][\"element\"]` into atomic number, For that we can use PyAstronomy\n\n```python\nfrom PyAstronomy import pyasl\n\nan = pyasl.AtomicNo()\n```\n\nUsing `an` we can now convert element name to atomic number to put in the array, Now we can just loop through the dictionary and add values to our array\n\nBefore looping we store all the points that the atoms use to help with the bond mapping algorithm in the future\n\n\n```python\ntaken_points = []\n\n\nfor i in node_location.keys():\n    x = node_location[i][0][0]\n    y = node_location[i][0][1]\n    \n    \n    atomic_number = an.getAtomicNo(node_location[i][1])\n    \n    map_array[x][y] = atomic_number\n    \n    taken_points.append([x,y])\n```\n\nNow `map_array` looks like this\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F13007289%2Fe50aea858a8c8e2a8e7fdc84a9fd383b%2FScreenshot%202023-11-01%20135616.png?generation=1698827204871062&alt=media)\n\n\n## Part 2: Mapping bonds using an algorithm\n\nSince the edges connecting the nodes are ideal lines, they don't use x, y coordinates. So we have to use an algorithm to map out bonds ourselves\n\nThe algorithm I wrote notes down x, y coordinates of the atom which the bond goes to, It starts with the atom which bonds comes from and considers all nearby points which are directly connected to it (This can only be 8 points in a 2D plane) and then selects the one with the least distance from the points of the target x, y coordinates and puts the value of the bond at the point and continues from that point and repeat until there's no nearby points left or the target x, y coordinates are part of the nearby points\n\nHere's the code for it:\n\n```python\nfor edge in mol.edges():\n    current_atom = edge[0]\n    target_atom = edge[1]\n    \n    target_x,target_y = node_location[target_atom][0]\n    \n    current_atom_x, current_atom_y = node_location[current_atom][0]\n    \n    available_nearby_points = get_available_nearby_points(current_atom_x, current_atom_y, 256)\n    nearby_points = get_nearby_points(current_atom_x, current_atom_y, 256)\n    \n    \n    while [target_x,target_y] not in nearby_points:\n        least_distance = None\n        selected_point = None\n        \n        if len(available_nearby_points) == 0:\n            break\n        \n        for i in available_nearby_points:\n            distance = math.sqrt( ((target_x - i[0]) ** 2) + ((target_y - i[1]) ** 2) )\n            if least_distance == None:\n                least_distance = distance\n                selected_point = i\n            \n            if least_distance > distance:\n                least_distance = distance\n                selected_point = i\n        \n        \n        \n        taken_points.append(selected_point)\n        map_array[selected_point[0]][selected_point[1]] = int(mol.edges[edge][\"order\"]) / 3\n  \n        \n        available_nearby_points = get_available_nearby_points(selected_point[0], selected_point[1], 256)\n        nearby_points = get_nearby_points(selected_point[0], selected_point[1], 256)\n```\n\nHere's a GIF to visualize the algorithm\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F13007289%2F9238d3133b8050744d6d61272dff6c41%2Falgorithm.gif?generation=1698830719615758&alt=media)\n\n\nNow `map_array` looks like this\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F13007289%2F2956eb6af621cec205b0381adc9ed798%2Fbondmap.png?generation=1698828157183311&alt=media)\n\n\nNow we apply max pooling of size 4 to turn the size of the array from 256, 256, to 64, 64 without loosing any meaningful information\nAfter applying max pooling `map_array` will look like this\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F13007289%2Fd98049fd8f27f981523b801cbf44bfc6%2Ffinalmap.png?generation=1698828271218825&alt=media)\n\n\nThe full code is in the linked notebook.\n\nThanks for reading!",
      "votes": 4
    }
  ],
  "comments": [],
  "raw_markdown_by_id": {
    "2507016": "I'm sharing a method which allows you to convert SMILES Notation to a 2D numpy array, The numpy array contains atomic numbers of the elements mentioned in the SMILES Notation as well as bond values.\n\nLink to the notebook: [https://www.kaggle.com/code/arpitytlinux/smilesto2darray](https://www.kaggle.com/code/arpitytlinux/smilesto2darray)\n\nHere's how it works in a nutshell:\n\n## Part 1: Adding Atomic numbers as values\n\nWe first make a 2D array of size 256, 256. This size was chosen because during testing I concluded that the max coordinates can do upto 200 for both axes\n\n`map_array = np.zeros((256,256))`\n\nThen we use pysmiles to convert SMILES string to a NetworkX graph of nodes and edges\n\n```python\nsmiles_string = \"COC(=O)N(C)c1c(N)nc(-c2nn(Cc3ccccc3F)c3ncccc23)nc1N\"\nmol = read_smiles(smiles_string) \n```\n\nA NetworkX graph looks like this (Blue circles are called Nodes and the lines connecting the Nodes are called Edges)\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F13007289%2F22ccb62fb6ebcd414d45d56d4b2ef927%2FScreenshot%202023-11-01%20134605.png?generation=1698826665378200&alt=media)\n\nThen we use `spring_layout` provided by NetworkX to calculate the x, y coordinates of nodes in a given graph, This returns a dictionary which we can use to find out the x, y coordinates of a given node\n\n`pos = nx.spring_layout(mol)`\n\nThen we adjust the x,y coordinates and store it in a new dictionary because we need to make it compatible with our array (Some coordinates can be in negative and there is no -2 element in our array!), We do this by multiplying it by 100 to make some space between the elements and easier to round it off to integers then adding the lowest value which spring_layout can have which I concluded was -100, So we add +100 to make it minimum of 0\n\n```python\nnode_location = {}\n\n\nfor node in mol.nodes():\n    x,y = pos[node]\n    x,y = (x*100) + 100, (y*100) + 100\n    x,y = int(x), int(y)\n    \n    node_location[node] = [[x,y], mol.nodes[node][\"element\"]]\n```\n\nThen we need a method to convert the element name or `mol.nodes[node][\"element\"]` into atomic number, For that we can use PyAstronomy\n\n```python\nfrom PyAstronomy import pyasl\n\nan = pyasl.AtomicNo()\n```\n\nUsing `an` we can now convert element name to atomic number to put in the array, Now we can just loop through the dictionary and add values to our array\n\nBefore looping we store all the points that the atoms use to help with the bond mapping algorithm in the future\n\n\n```python\ntaken_points = []\n\n\nfor i in node_location.keys():\n    x = node_location[i][0][0]\n    y = node_location[i][0][1]\n    \n    \n    atomic_number = an.getAtomicNo(node_location[i][1])\n    \n    map_array[x][y] = atomic_number\n    \n    taken_points.append([x,y])\n```\n\nNow `map_array` looks like this\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F13007289%2Fe50aea858a8c8e2a8e7fdc84a9fd383b%2FScreenshot%202023-11-01%20135616.png?generation=1698827204871062&alt=media)\n\n\n## Part 2: Mapping bonds using an algorithm\n\nSince the edges connecting the nodes are ideal lines, they don't use x, y coordinates. So we have to use an algorithm to map out bonds ourselves\n\nThe algorithm I wrote notes down x, y coordinates of the atom which the bond goes to, It starts with the atom which bonds comes from and considers all nearby points which are directly connected to it (This can only be 8 points in a 2D plane) and then selects the one with the least distance from the points of the target x, y coordinates and puts the value of the bond at the point and continues from that point and repeat until there's no nearby points left or the target x, y coordinates are part of the nearby points\n\nHere's the code for it:\n\n```python\nfor edge in mol.edges():\n    current_atom = edge[0]\n    target_atom = edge[1]\n    \n    target_x,target_y = node_location[target_atom][0]\n    \n    current_atom_x, current_atom_y = node_location[current_atom][0]\n    \n    available_nearby_points = get_available_nearby_points(current_atom_x, current_atom_y, 256)\n    nearby_points = get_nearby_points(current_atom_x, current_atom_y, 256)\n    \n    \n    while [target_x,target_y] not in nearby_points:\n        least_distance = None\n        selected_point = None\n        \n        if len(available_nearby_points) == 0:\n            break\n        \n        for i in available_nearby_points:\n            distance = math.sqrt( ((target_x - i[0]) ** 2) + ((target_y - i[1]) ** 2) )\n            if least_distance == None:\n                least_distance = distance\n                selected_point = i\n            \n            if least_distance > distance:\n                least_distance = distance\n                selected_point = i\n        \n        \n        \n        taken_points.append(selected_point)\n        map_array[selected_point[0]][selected_point[1]] = int(mol.edges[edge][\"order\"]) / 3\n  \n        \n        available_nearby_points = get_available_nearby_points(selected_point[0], selected_point[1], 256)\n        nearby_points = get_nearby_points(selected_point[0], selected_point[1], 256)\n```\n\nHere's a GIF to visualize the algorithm\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F13007289%2F9238d3133b8050744d6d61272dff6c41%2Falgorithm.gif?generation=1698830719615758&alt=media)\n\n\nNow `map_array` looks like this\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F13007289%2F2956eb6af621cec205b0381adc9ed798%2Fbondmap.png?generation=1698828157183311&alt=media)\n\n\nNow we apply max pooling of size 4 to turn the size of the array from 256, 256, to 64, 64 without loosing any meaningful information\nAfter applying max pooling `map_array` will look like this\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F13007289%2Fd98049fd8f27f981523b801cbf44bfc6%2Ffinalmap.png?generation=1698828271218825&alt=media)\n\n\nThe full code is in the linked notebook.\n\nThanks for reading!"
  }
}