using protein folding rules to drive a 3d ca

Getting your Trinity Audio player ready…

With openaiGPTo1-preview

Explanation:

  • Amino Acid Properties: We define a dictionary amino_acids that maps each amino acid to its type based on hydrophobicity and charge.
  • Initialization: The protein sequence is placed randomly within a 3D grid.
  • Interaction Rules:
    • Hydrophobic Interactions: Hydrophobic amino acids tend to move closer together to avoid contact with the aqueous environment.
    • Electrostatic Interactions: Positively charged amino acids are attracted to negatively charged ones and vice versa.
    • Charge Repulsion: Amino acids with the same charge repel each other.
  • Update Function: update_positions moves amino acids according to the interaction rules, updating their positions on the grid.
  • Simulation Loop: The simulation runs for a specified number of steps, updating positions at each step.
  • Visualization: The final positions of the amino acids are plotted in a 3D scatter plot, color-coded based on their properties.

Customization:

  • Protein Sequence: You can modify the protein_sequence variable to simulate different proteins.
  • Grid Size: Adjust the grid_size variable to change the simulation space.
  • Simulation Steps: Modify the steps variable to run the simulation for more or fewer iterations.

Limitations:

  • This model is highly simplified and does not capture the full complexity of protein folding.
  • The movement rules are basic and do not account for all physical forces involved in actual protein folding.
  • For more accurate simulations, molecular dynamics software or specialized protein folding algorithms should be used.

References to ML Insights:

The rules used in this simulation are inspired by patterns identified through machine learning in protein folding studies:

  • Hydrophobic Collapse: ML models have shown the significance of hydrophobic interactions in the early stages of folding.
  • Electrostatic Interactions: Machine learning has helped in understanding the role of long-range electrostatic interactions.
  • Secondary Structure Formation: While not explicitly modeled here, ML has contributed to predicting alpha-helices and beta-sheets formations.

import numpy as np

import matplotlib.pyplot as plt

from mpl_toolkits.mplot3d import Axes3D

import random

# Define amino acid properties

amino_acids = {

    ‘A’: {‘type’: ‘hydrophobic’},

    ‘C’: {‘type’: ‘hydrophobic’},

    ‘D’: {‘type’: ‘negatively_charged’},

    ‘E’: {‘type’: ‘negatively_charged’},

    ‘F’: {‘type’: ‘hydrophobic’},

    ‘G’: {‘type’: ‘hydrophobic’},

    ‘H’: {‘type’: ‘positively_charged’},

    ‘I’: {‘type’: ‘hydrophobic’},

    ‘K’: {‘type’: ‘positively_charged’},

    ‘L’: {‘type’: ‘hydrophobic’},

    ‘M’: {‘type’: ‘hydrophobic’},

    ‘N’: {‘type’: ‘polar’},

    ‘P’: {‘type’: ‘hydrophobic’},

    ‘Q’: {‘type’: ‘polar’},

    ‘R’: {‘type’: ‘positively_charged’},

    ‘S’: {‘type’: ‘polar’},

    ‘T’: {‘type’: ‘polar’},

    ‘V’: {‘type’: ‘hydrophobic’},

    ‘W’: {‘type’: ‘hydrophobic’},

    ‘Y’: {‘type’: ‘polar’},

}

# Initial protein sequence (You can modify this)

protein_sequence = ‘ACDEFGHIKLMNPQRSTVWY’

# Grid size

grid_size = 20

# Initialize the 3D grid

grid = np.full((grid_size, grid_size, grid_size), None)

# Place amino acids randomly in the grid

positions = []

for aa in protein_sequence:

    while True:

        x, y, z = np.random.randint(0, grid_size, size=3)

        if grid[x, y, z] is None:

            grid[x, y, z] = aa

            positions.append([x, y, z])

            break

positions = np.array(positions)

# Interaction rules

def get_neighbors(pos):

    x, y, z = pos

    neighbors = []

    for dx in [-1, 0, 1]:

        for dy in [-1, 0, 1]:

            for dz in [-1, 0, 1]:

                if (dx == 0 and dy == 0 and dz == 0):

                    continue

                nx, ny, nz = x + dx, y + dy, z + dz

                if 0 <= nx < grid_size and 0 <= ny < grid_size and 0 <= nz < grid_size:

                    neighbors.append((nx, ny, nz))

    return neighbors

def update_positions(positions):

    new_positions = positions.copy()

    for idx, pos in enumerate(positions):

        aa = grid[tuple(pos)]

        aa_type = amino_acids[aa][‘type’]

        neighbors = get_neighbors(pos)

        random.shuffle(neighbors)

        for neighbor in neighbors:

            npos = np.array(neighbor)

            naa = grid[tuple(npos)]

            if naa is None:

                continue

            naa_type = amino_acids[naa][‘type’]

            # Hydrophobic interactions

            if aa_type == ‘hydrophobic’ and naa_type == ‘hydrophobic’:

                # Move closer

                direction = npos – pos

                new_pos = pos + np.sign(direction)

                new_pos = np.clip(new_pos, 0, grid_size – 1)

                if grid[tuple(new_pos)] is None:

                    grid[tuple(pos)] = None

                    grid[tuple(new_pos)] = aa

                    new_positions[idx] = new_pos

                break

            # Electrostatic interactions

            elif (aa_type == ‘positively_charged’ and naa_type == ‘negatively_charged’) or \

                 (aa_type == ‘negatively_charged’ and naa_type == ‘positively_charged’):

                # Move closer

                direction = npos – pos

                new_pos = pos + np.sign(direction)

                new_pos = np.clip(new_pos, 0, grid_size – 1)

                if grid[tuple(new_pos)] is None:

                    grid[tuple(pos)] = None

                    grid[tuple(new_pos)] = aa

                    new_positions[idx] = new_pos

                break

            # Repulsion for same charges

            elif aa_type == naa_type and aa_type in [‘positively_charged’, ‘negatively_charged’]:

                # Move away

                direction = pos – npos

                new_pos = pos + np.sign(direction)

                new_pos = np.clip(new_pos, 0, grid_size – 1)

                if grid[tuple(new_pos)] is None:

                    grid[tuple(pos)] = None

                    grid[tuple(new_pos)] = aa

                    new_positions[idx] = new_pos

                break

    return new_positions

# Run the simulation

steps = 50

for step in range(steps):

    positions = update_positions(positions)

# Visualization

fig = plt.figure()

ax = fig.add_subplot(111, projection=’3d’)

aa_types = {‘hydrophobic’: ‘red’, ‘polar’: ‘blue’, ‘positively_charged’: ‘green’, ‘negatively_charged’: ‘yellow’}

colors = []

for pos in positions:

    aa = grid[tuple(pos)]

    aa_type = amino_acids[aa][‘type’]

    colors.append(aa_types[aa_type])

ax.scatter(positions[:, 0], positions[:, 1], positions[:, 2], c=colors, s=100)

ax.set_xlabel(‘X’)

ax.set_ylabel(‘Y’)

ax.set_zlabel(‘Z’)

plt.title(‘3D Cellular Automaton Protein Folding Simulation’)

plt.show()


Posted

in

by

Tags:

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *