{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":87793,"databundleVersionId":11553390,"sourceType":"competition"}],"dockerImageVersionId":30918,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-03-04T08:25:55.326145Z","iopub.execute_input":"2025-03-04T08:25:55.326507Z","iopub.status.idle":"2025-03-04T08:25:55.336762Z","shell.execute_reply.started":"2025-03-04T08:25:55.326476Z","shell.execute_reply":"2025-03-04T08:25:55.335799Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport math\n\ndef calculate_lref_d0(df):\n  \"\"\"Calculates Lref and d0 for each entry in the DataFrame.\n\n  Args:\n    df: Pandas DataFrame containing the data.\n\n  Returns:\n    Pandas DataFrame with added 'Lref' and 'd0' columns.\n  \"\"\"\n  df['Lref'] = df['sequence'].apply(len)\n  df['d0'] = df['Lref'].apply(lambda lref: 0.6 * math.sqrt(lref - 0.5) - 2.5)\n  return df\n\n# Load the CSV files\ntry:\n    validation_df = pd.read_csv(\"validation_sequences.csv\")\n    test_df = pd.read_csv(\"test_sequences.csv\")\nexcept FileNotFoundError:\n    print(\"Error: validation_sequences.csv or test_sequences.csv not found.  Make sure the files are in the same directory as the script.\")\n    # Create empty DataFrames to prevent NameError, but analysis will be limited.\n    validation_df = pd.DataFrame()\n    test_df = pd.DataFrame()\n    # Exit or continue with empty dataframes.  For Kaggle, it's better to continue\n    # so the notebook still runs, even if it doesn't do much.\n    # exit()  # Uncomment if you want to stop completely on FileNotFoundError\n    print(\"Continuing with empty DataFrames.\")\n\n\n# Calculate Lref and d0 for both DataFrames\nif not validation_df.empty:  # Only process if the DataFrame is not empty\n    validation_df = calculate_lref_d0(validation_df)\n    print(\"Validation Data:\")\n    print(validation_df[['target_id', 'sequence', 'Lref', 'd0']]) # Showing only relevant columns\nelse:\n    print(\"Validation DataFrame is empty, skipping Lref/d0 calculation.\")\n\nif not test_df.empty:  # Only process if the DataFrame is not empty\n    test_df = calculate_lref_d0(test_df)\n    print(\"\\nTest Data:\")\n    print(test_df[['target_id', 'sequence', 'Lref', 'd0']]) # Showing only relevant columns\nelse:\n    print(\"Test DataFrame is empty, skipping Lref/d0 calculation.\")\n\n\n\n# Optionally, save the updated DataFrames to new CSV files:\n# validation_df.to_csv(\"validation_sequences_with_lref_d0.csv\", index=False)\n# test_df.to_csv(\"test_sequences_with_lref_d0.csv\", index=False)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-04T08:25:55.338047Z","iopub.execute_input":"2025-03-04T08:25:55.338340Z","iopub.status.idle":"2025-03-04T08:25:55.357108Z","shell.execute_reply.started":"2025-03-04T08:25:55.338305Z","shell.execute_reply":"2025-03-04T08:25:55.356033Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\n\nbase_path = \"/kaggle/input/stanford-rna-3d-folding/\"\n\nvalidation_csv_path = os.path.join(base_path, \"validation_sequences.csv\")\ntest_csv_path = os.path.join(base_path, \"test_sequences.csv\")\n\nprint(f\"Validation CSV Path: {validation_csv_path}\")\nprint(f\"Test CSV Path: {test_csv_path}\")\n\nprint(f\"Validation CSV Exists: {os.path.exists(validation_csv_path)}\")\nprint(f\"Test CSV Exists: {os.path.exists(test_csv_path)}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-04T08:25:55.358890Z","iopub.execute_input":"2025-03-04T08:25:55.359228Z","iopub.status.idle":"2025-03-04T08:25:55.382031Z","shell.execute_reply.started":"2025-03-04T08:25:55.359204Z","shell.execute_reply":"2025-03-04T08:25:55.380984Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport math\nimport os\n\ndef calculate_lref_d0(df):\n  \"\"\"Calculates Lref and d0 for each entry in the DataFrame.\n\n  Args:\n    df: Pandas DataFrame containing the data.\n\n  Returns:\n    Pandas DataFrame with added 'Lref' and 'd0' columns.\n  \"\"\"\n  df['Lref'] = df['sequence'].apply(len)\n  df['d0'] = df['Lref'].apply(lambda lref: 0.6 * math.sqrt(lref - 0.5) - 2.5)\n  return df\n\n# Define the base path for the input files in Kaggle\ncompetition_name = \"stanford-rna-3d-folding\"  # Replace with the actual competition name\nbase_path = f\"/kaggle/input/{competition_name}/\"\n\n# Load the CSV files\nvalidation_csv_path = os.path.join(base_path, \"validation_sequences.csv\")\ntest_csv_path = os.path.join(base_path, \"test_sequences.csv\")\n\n# The files exist, so we can load them directly\nvalidation_df = pd.read_csv(validation_csv_path)\ntest_df = pd.read_csv(test_csv_path)\n\n\n# Calculate Lref and d0 for both DataFrames\nvalidation_df = calculate_lref_d0(validation_df)\nprint(\"Validation Data:\")\nprint(validation_df[['target_id', 'sequence', 'Lref', 'd0']]) # Showing only relevant columns\n\n\ntest_df = calculate_lref_d0(test_df)\nprint(\"\\nTest Data:\")\nprint(test_df[['target_id', 'sequence', 'Lref', 'd0']]) # Showing only relevant columns\n\n\n\n# Optionally, save the updated DataFrames to new CSV files:\n# validation_df.to_csv(\"validation_sequences_with_lref_d0.csv\", index=False)\n# test_df.to_csv(\"test_sequences_with_lref_d0.csv\", index=False)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-04T08:25:55.383506Z","iopub.execute_input":"2025-03-04T08:25:55.383859Z","iopub.status.idle":"2025-03-04T08:25:55.417035Z","shell.execute_reply.started":"2025-03-04T08:25:55.383826Z","shell.execute_reply":"2025-03-04T08:25:55.416113Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport math\nimport os\nfrom IPython.display import display, HTML\nimport numpy as np  # Import numpy for creating sample predictions\n\ndef calculate_lref_d0(df):\n    \"\"\"Calculates Lref and d0 for each entry in the DataFrame.\"\"\"\n    df['Lref'] = df['sequence'].apply(len)\n    df['d0'] = df['Lref'].apply(lambda lref: 0.6 * math.sqrt(lref - 0.5) - 2.5)\n    return df\n\n# Define the base path for the input files in Kaggle\ncompetition_name = \"stanford-rna-3d-folding\"\nbase_path = f\"/kaggle/input/{competition_name}/\"\n\n# Load the CSV files\nvalidation_csv_path = os.path.join(base_path, \"validation_sequences.csv\")\ntest_csv_path = os.path.join(base_path, \"test_sequences.csv\")\n\n# The files exist, so we can load them directly\nvalidation_df = pd.read_csv(validation_csv_path)\ntest_df = pd.read_csv(test_csv_path)\n\n# Calculate Lref and d0 for both DataFrames\nvalidation_df = calculate_lref_d0(validation_df)\nprint(\"<h2>Validation Data:</h2>\")\ndisplay(HTML(validation_df[['target_id', 'sequence', 'Lref', 'd0']].to_html(index=False)))\n\ntest_df = calculate_lref_d0(test_df)\nprint(\"<h2>Test Data:</h2>\")\ndisplay(HTML(test_df[['target_id', 'sequence', 'Lref', 'd0']].to_html(index=False)))\n\n\n# --- PREDICTION CODE STARTS HERE ---\n# REPLACE THIS SECTION WITH YOUR ACTUAL MODEL AND PREDICTION LOGIC\n# This is placeholder code to generate sample predictions.  You must adapt this\n# to use your trained model to generate predictions based on the sequences in test_df.\n# Make sure that 'predictions' is a Pandas Series or NumPy array with one prediction\n# for each row in 'test_df'.\nnp.random.seed(42)  # for reproducibility\npredictions = np.random.rand(len(test_df))\n# --- PREDICTION CODE ENDS HERE ---\n\n\n# --- CREATE SUBMISSION FILE ---\nsubmission = pd.DataFrame({'target_id': test_df['target_id'], 'predicted_value': predictions})\nsubmission['predicted_value'] = submission['predicted_value'].astype(float) #Ensure its numeric\n\nsubmission_filename = 'submission.csv'\nsubmission.to_csv(submission_filename, index=False)\n\n\n# --- VERIFY SUBMISSION FILE CREATION ---\nif os.path.exists(submission_filename):\n    print(f\"Submission file '{submission_filename}' created successfully!\")\n    print(\"\\nFirst 5 rows of submission.csv:\")\n    display(HTML(submission.head().to_html(index=False))) # Show the first few rows\nelse:\n    print(f\"ERROR: Submission file '{submission_filename}' was NOT created!\")\n\nprint(\"Make sure to submit file named submission.csv\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-04T08:25:55.417891Z","iopub.execute_input":"2025-03-04T08:25:55.418155Z","iopub.status.idle":"2025-03-04T08:25:55.451828Z","shell.execute_reply.started":"2025-03-04T08:25:55.418132Z","shell.execute_reply":"2025-03-04T08:25:55.450858Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport math\nimport os\nfrom IPython.display import display, HTML\nimport numpy as np\nimport matplotlib.pyplot as plt  # Import for plotting\nfrom mpl_toolkits.mplot3d import Axes3D  # Import for 3D plotting\n\n# Assume the existence of the following file on the host:\n#   - test_sequences.csv: test sequences\n\ndef calculate_lref_d0(df):\n    \"\"\"Calculates Lref and d0 for each entry in the DataFrame.\"\"\"\n    df['Lref'] = df['sequence'].apply(len)\n    df['d0'] = df['Lref'].apply(lambda lref: 0.6 * math.sqrt(lref - 0.5) - 2.5)\n    return df\n\n# Define the base path for the input files in Kaggle\ncompetition_name = \"stanford-rna-3d-folding\"\nbase_path = f\"/kaggle/input/{competition_name}/\"\n\n# Load the CSV files\ntry:\n    validation_csv_path = os.path.join(base_path, \"validation_sequences.csv\")\n    test_csv_path = os.path.join(base_path, \"test_sequences.csv\")\n\n    # Load the dataframes, raising FileNotFoundError exception if the files can't be found.\n    validation_df = pd.read_csv(validation_csv_path)\n    test_df = pd.read_csv(test_csv_path)\nexcept FileNotFoundError as e:\n    print(f\"Error: {e}\")\n    #If either of the dataframes can't be found, stop execution.\n    raise\n\n# Calculate Lref and d0 for both DataFrames\nvalidation_df = calculate_lref_d0(validation_df)\nprint(\"<h2>Validation Data:</h2>\")\ndisplay(HTML(validation_df[['target_id', 'sequence', 'Lref', 'd0']].to_html(index=False)))\n\ntest_df = calculate_lref_d0(test_df)\nprint(\"<h2>Test Data:</h2>\")\ndisplay(HTML(test_df[['target_id', 'sequence', 'Lref', 'd0']].to_html(index=False)))\n\n# --- PREDICTION CODE STARTS HERE ---\n# REPLACE THIS ENTIRE SECTION WITH YOUR ACTUAL MODEL AND 3D STRUCTURE PREDICTION LOGIC!\n# This is placeholder code to generate random coordinates, attempting to simulate\n# a helical structure. You MUST adapt this to use your trained model to predict\n# the 3D structure of each RNA sequence in 'test_df'.\n\n# Parameters to control the helix generation (adjust these!)\nnum_structures = 1 # Reduced to 1 to make visualization clearer\nnp.random.seed(42)  # For reproducibility\nhelix_radius = 5.0  # Radius of the helix\nhelix_pitch = 3.0  # Vertical distance between turns\nz_scaling_factor = 1.0\n\n#Define base_points - Use the first entry as the start to the transformation\nbase_point_x = np.array(test_df['Lref'])[0]\nbase_point_y = np.array(test_df['d0'])[0]\nbase_points = np.array([base_point_x, base_point_y])\n\ndef k_vector_field(x, structure_number):\n    \"\"\"Defines a simple k-vector field\"\"\"\n    # This is a very simple example: a constant vector field\n    # Scale based on how far the structure is from the origin\n    scaling = 0.1 * structure_number\n    return np.array([scaling, scaling])\n\ndef integral_section(base_point, k_vector_field, sequence_length, structure_number):\n    \"\"\"Applies the integral section to create the 3d points, transforming the points\"\"\"\n    angles = np.linspace(0, 4 * np.pi, sequence_length)  # Angles for points along the helix (4 pi = two full rotations)\n    random_offsets = np.random.rand(sequence_length) * 1.0  # Add some random noise\n\n    #Apply transformation based on vector field\n    vector_field = k_vector_field(base_point, structure_number) # Scale the transformation based on the vectorfield\n    x = helix_radius * np.cos(angles) + random_offsets + vector_field[0]\n    y = helix_radius * np.sin(angles) + random_offsets + vector_field[1]\n    z = helix_pitch * angles  + z_scaling_factor * structure_number #Linear increase + scalingFactor\n    return x,y,z\n\ndef generate_helical_structure(sequence_length, structure_number):\n    \"\"\"Generates a single helical 3D structure (coordinates for each residue).\"\"\"\n    angles = np.linspace(0, 4 * np.pi, sequence_length)  # Angles for points along the helix (4 pi = two full rotations)\n    random_offsets = np.random.rand(sequence_length) * 1.0  # Add some random noise\n    x_coords = helix_radius * np.cos(angles) + random_offsets\n    y_coords = helix_radius * np.sin(angles) + random_offsets\n    z_coords = helix_pitch * angles  + z_scaling_factor * structure_number\n    return x_coords, y_coords, z_coords\n\nall_structure_data = []\nfor index, row in test_df.iterrows():\n    target_id = row['target_id']\n    sequence = row['sequence']\n    sequence_length = len(sequence)\n\n    # Generate a color for the sequence (for plotting)\n    color = np.random.rand(3,)  # Generate a random RGB color\n    # plot with color of choice\n    fig = plt.figure(figsize=(8, 8))  # Create a figure\n    ax = fig.add_subplot(111, projection='3d')  # Add a 3D subplot\n\n    for structure_num in range(1, num_structures + 1):\n        x_coords, y_coords, z_coords = integral_section(base_points, k_vector_field, sequence_length, structure_num)\n\n        # Plot the helical structure with a custom color\n        ax.plot(x_coords, y_coords, z_coords, c=color, label=f\"{target_id}\")  # Change from scatter to plot, for line\n\n        for residue_index in range(sequence_length):\n            resname = sequence[residue_index]  # Get the residue name from the sequence\n            resid = residue_index + 1  # Residue ID (1-based)\n            structure_id = f\"{target_id}_{structure_num}\"\n\n            # Create structure for the current structure\n            all_structure_data.append([structure_id, resname, resid,\n                                        x_coords[residue_index],\n                                        y_coords[residue_index],\n                                        z_coords[residue_index]])\n\n    ax.set_xlabel(\"X\")\n    ax.set_ylabel(\"Y\")\n    ax.set_zlabel(\"Z\")\n    ax.set_title(f\"3D Structure of {target_id}\") # Title with id\n    ax.legend()  # Show legend to identify the structures\n\n    #Adjust axes ranges\n    max_range = np.array([x_coords.max()-x_coords.min(), y_coords.max()-y_coords.min(), z_coords.max()-z_coords.min()]).max() / 2.0\n    mid_x = (x_coords.max()+x_coords.min()) * 0.5\n    mid_y = (y_coords.max()+y_coords.min()) * 0.5\n    mid_z = (z_coords.max()+z_coords.min()) * 0.5\n    ax.set_xlim(mid_x - max_range, mid_x + max_range)\n    ax.set_ylim(mid_y - max_range, mid_y + max_range)\n    ax.set_zlim(mid_z - max_range, mid_z + max_range)\n\n    plt.show()  # Display the plot\n\n#Create the columns based on the structure of all_structure_data\ncol_names = ['ID', 'resname', 'resid', 'x_1', 'y_1', 'z_1']\n\n# --- PREDICTION CODE ENDS HERE ---\n\n# --- CREATE SUBMISSION FILE ---\nsubmission_df = pd.DataFrame(all_structure_data, columns=col_names)\n\nsubmission_filename = 'submission.csv'\nsubmission_df.to_csv(submission_filename, index=False)\n\n# --- VERIFY SUBMISSION FILE CREATION ---\nif os.path.exists(submission_filename):\n    print(f\"Submission file '{submission_filename}' created successfully!\")\n    print(\"\\nFirst 5 rows of submission.csv:\")\n    display(HTML(submission_df.head().to_html(index=False)))  # Show the first few rows\n    print(f\"\\nSubmission contains: {len(submission_df)} rows\")  # Shows the number of rows\nelse:\n    print(f\"ERROR: Submission file '{submission_filename}' was NOT created!\")\n\nprint(\"Make sure to submit file named submission.csv\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-04T08:25:55.452812Z","iopub.execute_input":"2025-03-04T08:25:55.453084Z","iopub.status.idle":"2025-03-04T08:25:57.964539Z","shell.execute_reply.started":"2025-03-04T08:25:55.453060Z","shell.execute_reply":"2025-03-04T08:25:57.963496Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport math\nimport os\nfrom IPython.display import display, HTML\nimport numpy as np\nimport matplotlib.pyplot as plt  # Import for plotting\nfrom mpl_toolkits.mplot3d import Axes3D  # Import for 3D plotting\n\n# Assume the existence of the following file on the host:\n#   - test_sequences.csv: test sequences\n\ndef calculate_lref_d0(df):\n    \"\"\"Calculates Lref and d0 for each entry in the DataFrame.\"\"\"\n    df['Lref'] = df['sequence'].apply(len)\n    df['d0'] = df['Lref'].apply(lambda lref: 0.6 * math.sqrt(lref - 0.5) - 2.5)\n    return df\n\n# Define the base path for the input files in Kaggle\ncompetition_name = \"stanford-rna-3d-folding\"\nbase_path = f\"/kaggle/input/{competition_name}/\"\n\n# Load the CSV files\ntry:\n    validation_csv_path = os.path.join(base_path, \"validation_sequences.csv\")\n    test_csv_path = os.path.join(base_path, \"test_sequences.csv\")\n\n    # Load the dataframes, raising FileNotFoundError exception if the files can't be found.\n    validation_df = pd.read_csv(validation_csv_path)\n    test_df = pd.read_csv(test_csv_path)\nexcept FileNotFoundError as e:\n    print(f\"Error: {e}\")\n    #If either of the dataframes can't be found, stop execution.\n    raise\n\n# Calculate Lref and d0 for both DataFrames\nvalidation_df = calculate_lref_d0(validation_df)\nprint(\"<h2>Validation Data:</h2>\")\ndisplay(HTML(validation_df[['target_id', 'sequence', 'Lref', 'd0']].to_html(index=False)))\n\ntest_df = calculate_lref_d0(test_df)\nprint(\"<h2>Test Data:</h2>\")\ndisplay(HTML(test_df[['target_id', 'sequence', 'Lref', 'd0']].to_html(index=False)))\n\n# --- PREDICTION CODE STARTS HERE ---\n# REPLACE THIS ENTIRE SECTION WITH YOUR ACTUAL MODEL AND 3D STRUCTURE PREDICTION LOGIC!\n# This is placeholder code to generate random coordinates, attempting to simulate\n# a helical structure. You MUST adapt this to use your trained model to predict\n# the 3D structure of each RNA sequence in 'test_df'.\n\n# Parameters to control the helix generation (adjust these!)\nnum_structures = 1\nnp.random.seed(42)  # For reproducibility\nhelix_radius = 5.0  # Radius of the helix\nhelix_pitch = 3.0  # Vertical distance between turns\nz_scaling_factor = 1.0\n\ndef generate_helical_structure(sequence_length, structure_number):\n    \"\"\"Generates a single helical 3D structure (coordinates for each residue).\"\"\"\n    angles = np.linspace(0, 4 * np.pi, sequence_length)  # Angles for points along the helix (4 pi = two full rotations)\n    random_offsets = np.random.rand(sequence_length) * 1.0  # Add some random noise\n    x_coords = helix_radius * np.cos(angles) + random_offsets\n    y_coords = helix_radius * np.sin(angles) + random_offsets\n    z_coords = helix_pitch * angles  + z_scaling_factor * structure_number\n    return x_coords, y_coords, z_coords\n\nall_structure_data = []\n\n# Create a single figure and axes for all plots\nfig = plt.figure(figsize=(12, 8))\nax = fig.add_subplot(111, projection='3d')\nax.set_xlabel(\"X\")\nax.set_ylabel(\"Y\")\nax.set_zlabel(\"Z\")\nax.set_title(\"3D Structures of RNA Sequences\")  # General plot title\n\n# Store the initial point\ninitial_point = np.array([0,0,0]) #Origin (Will shift to be sequence base)\n\n# Generate the plots together\nfor index, row in test_df.iterrows():\n    target_id = row['target_id']\n    sequence = row['sequence']\n    sequence_length = len(sequence)\n\n    # Generate a color for the sequence (for plotting)\n    color = np.random.rand(3,)  # Generate a random RGB color\n\n    for structure_num in range(1, num_structures + 1):\n        x_coords, y_coords, z_coords = generate_helical_structure(sequence_length, structure_num)\n\n        # Applying φ(0) = x for point\n        starting_point = np.array([x_coords[0], y_coords[0], z_coords[0]]) # The point the function has been derived to get to\n        x_coords = x_coords - starting_point[0]\n        y_coords = y_coords - starting_point[1]\n        z_coords = z_coords - starting_point[2] # Apply to the coordinate system\n\n        # Applying φ∗(t) to generate lines through those point\n        #Since all values have been offset, now connect to origin (base points)\n        ax.plot([initial_point[0]],[initial_point[1]],[initial_point[2]], 'o', c=color, markersize=4) #Point\n        ax.plot(x_coords, y_coords, z_coords, c=color, label=f\"{target_id}\") #\n\n        for residue_index in range(sequence_length):\n            resname = sequence[residue_index]  # Get the residue name from the sequence\n            resid = residue_index + 1  # Residue ID (1-based)\n            structure_id = f\"{target_id}_{structure_num}\"\n\n            # Create structure for the current structure\n            all_structure_data.append([structure_id, resname, resid,\n                                        x_coords[residue_index],\n                                        y_coords[residue_index],\n                                        z_coords[residue_index]])\n\nax.legend() # Add a legend\nplt.show() # Show plots\n\n#Create the columns based on the structure of all_structure_data\ncol_names = ['ID', 'resname', 'resid', 'x_1', 'y_1', 'z_1']\n\n# --- PREDICTION CODE ENDS HERE ---\n\n# --- CREATE SUBMISSION FILE ---\nsubmission_df = pd.DataFrame(all_structure_data, columns=col_names)\n\nsubmission_filename = 'submission.csv'\nsubmission_df.to_csv(submission_filename, index=False)\n\n# --- VERIFY SUBMISSION FILE CREATION ---\nif os.path.exists(submission_filename):\n    print(f\"Submission file '{submission_filename}' created successfully!\")\n    print(\"\\nFirst 5 rows of submission.csv:\")\n    display(HTML(submission_df.head().to_html(index=False)))  # Show the first few rows\n    print(f\"\\nSubmission contains: {len(submission_df)} rows\")  # Shows the number of rows\nelse:\n    print(f\"ERROR: Submission file '{submission_filename}' was NOT created!\")\n\nprint(\"Make sure to submit file named submission.csv\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-04T08:25:57.965731Z","iopub.execute_input":"2025-03-04T08:25:57.966109Z","iopub.status.idle":"2025-03-04T08:25:58.372735Z","shell.execute_reply.started":"2025-03-04T08:25:57.966074Z","shell.execute_reply":"2025-03-04T08:25:58.371839Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport math\nimport os\nfrom IPython.display import display, HTML\nimport numpy as np\nimport matplotlib.pyplot as plt  # Import for plotting\nfrom mpl_toolkits.mplot3d import Axes3D  # Import for 3D plotting\n\n# Assume the existence of the following file on the host:\n#   - test_sequences.csv: test sequences\n\ndef calculate_lref_d0(df):\n    \"\"\"Calculates Lref and d0 for each entry in the DataFrame.\"\"\"\n    df['Lref'] = df['sequence'].apply(len)\n    df['d0'] = df['Lref'].apply(lambda lref: 0.6 * math.sqrt(lref - 0.5) - 2.5)\n    return df\n\n# Define the base path for the input files in Kaggle\ncompetition_name = \"stanford-rna-3d-folding\"\nbase_path = f\"/kaggle/input/{competition_name}/\"\n\n# Load the CSV files\ntry:\n    validation_csv_path = os.path.join(base_path, \"validation_sequences.csv\")\n    test_csv_path = os.path.join(base_path, \"test_sequences.csv\")\n\n    # Load the dataframes, raising FileNotFoundError exception if the files can't be found.\n    validation_df = pd.read_csv(validation_csv_path)\n    test_df = pd.read_csv(test_csv_path)\nexcept FileNotFoundError as e:\n    print(f\"Error: {e}\")\n    #If either of the dataframes can't be found, stop execution.\n    raise\n\n# Calculate Lref and d0 for both DataFrames\nvalidation_df = calculate_lref_d0(validation_df)\nprint(\"<h2>Validation Data:</h2>\")\ndisplay(HTML(validation_df[['target_id', 'sequence', 'Lref', 'd0']].to_html(index=False)))\n\ntest_df = calculate_lref_d0(test_df)\nprint(\"<h2>Test Data:</h2>\")\ndisplay(HTML(test_df[['target_id', 'sequence', 'Lref', 'd0']].to_html(index=False)))\n\n# --- PREDICTION CODE STARTS HERE ---\n# REPLACE THIS ENTIRE SECTION WITH YOUR ACTUAL MODEL AND 3D STRUCTURE PREDICTION LOGIC!\n# This is placeholder code to generate random coordinates, attempting to simulate\n# a helical structure. You MUST adapt this to use your trained model to predict\n# the 3D structure of each RNA sequence in 'test_df'.\n\n# Parameters to control the helix generation (adjust these!)\nnum_structures = 2 # Generate two structures (double helix)\nnp.random.seed(42)  # For reproducibility\nhelix_radius = 5.0  # Radius of the helix\nhelix_pitch = 3.0  # Vertical distance between turns\nz_scaling_factor = 1.0\n\n#Define base_points - Use the first entry as the start to the transformation\nbase_point_x = np.array(test_df['Lref'])[0]\nbase_point_y = np.array(test_df['d0'])[0]\nbase_points = np.array([base_point_x, base_point_y])\n\ndef k_vector_field(x, structure_number):\n    \"\"\"Defines a simple k-vector field\"\"\"\n    # This is a very simple example: a constant vector field\n    # Scale based on how far the structure is from the origin\n    scaling = 0.1 * structure_number\n    return np.array([scaling, scaling])\n\ndef integral_section(base_point, k_vector_field, sequence_length, structure_number):\n    \"\"\"Applies the integral section to create the 3d points, transforming the points\"\"\"\n    angles = np.linspace(0, 4 * np.pi, sequence_length)  # Angles for points along the helix (4 pi = two full rotations)\n    random_offsets = np.random.rand(sequence_length) * 1.0  # Add some random noise\n\n    # Introduce a phase shift for the second helix\n    phase_shift = np.pi if structure_number == 2 else 0  # 180-degree phase shift\n\n    #Apply transformation based on vector field\n    vector_field = k_vector_field(base_point, structure_number) # Scale the transformation based on the vectorfield\n    x = helix_radius * np.cos(angles + phase_shift) + random_offsets + vector_field[0]\n    y = helix_radius * np.sin(angles + phase_shift) + random_offsets + vector_field[1]\n    z = helix_pitch * angles  + z_scaling_factor * structure_number #Linear increase + scalingFactor\n    return x,y,z\n\ndef generate_helical_structure(sequence_length, structure_number):\n    \"\"\"Generates a single helical 3D structure (coordinates for each residue).\"\"\"\n    angles = np.linspace(0, 4 * np.pi, sequence_length)  # Angles for points along the helix (4 pi = two full rotations)\n    random_offsets = np.random.rand(sequence_length) * 1.0  # Add some random noise\n    x_coords = helix_radius * np.cos(angles) + random_offsets\n    y_coords = helix_radius * np.sin(angles) + random_offsets\n    z_coords = helix_pitch * angles  + z_scaling_factor * structure_number\n    return x_coords, y_coords, z_coords\n\nall_structure_data = []\nfor index, row in test_df.iterrows():\n    target_id = row['target_id']\n    sequence = row['sequence']\n    sequence_length = len(sequence)\n\n    # Generate a color for the sequence (for plotting)\n    # color = np.random.rand(3,)  # Generate a random RGB color #Removed random color, assigning one to the structure instead.\n\n    # plot with color of choice\n    fig = plt.figure(figsize=(8, 8))  # Create a figure\n    ax = fig.add_subplot(111, projection='3d')  # Add a 3D subplot\n\n    for structure_num in range(1, num_structures + 1):\n\n        # Assign different color per structure to differentiate double helix\n        color = 'red' if structure_num == 1 else 'blue'\n\n        x_coords, y_coords, z_coords = integral_section(base_points, k_vector_field, sequence_length, structure_num)\n\n        # Plot the helical structure with a custom color\n        ax.plot(x_coords, y_coords, z_coords, c=color, label=f\"{target_id} Helix {structure_num}\")  # Change from scatter to plot, for line\n\n        for residue_index in range(sequence_length):\n            resname = sequence[residue_index]  # Get the residue name from the sequence\n            resid = residue_index + 1  # Residue ID (1-based)\n            structure_id = f\"{target_id}_{structure_num}\"\n\n            # Create structure for the current structure\n            all_structure_data.append([structure_id, resname, resid,\n                                        x_coords[residue_index],\n                                        y_coords[residue_index],\n                                        z_coords[residue_index]])\n\n    ax.set_xlabel(\"X\")\n    ax.set_ylabel(\"Y\")\n    ax.set_zlabel(\"Z\")\n    ax.set_title(f\"3D Structure of {target_id}\") # Title with id\n    ax.legend()  # Show legend to identify the structures\n\n    #Adjust axes ranges\n    max_range = np.array([x_coords.max()-x_coords.min(), y_coords.max()-y_coords.min(), z_coords.max()-z_coords.min()]).max() / 2.0\n    mid_x = (x_coords.max()+x_coords.min()) * 0.5\n    mid_y = (y_coords.max()+y_coords.min()) * 0.5\n    mid_z = (z_coords.max()+z_coords.min()) * 0.5\n    ax.set_xlim(mid_x - max_range, mid_x + max_range)\n    ax.set_ylim(mid_y - max_range, mid_y + max_range)\n    ax.set_zlim(mid_z - max_range, mid_z + max_range)\n\n    plt.show()  # Display the plot\n\n#Create the columns based on the structure of all_structure_data\ncol_names = ['ID', 'resname', 'resid', 'x_1', 'y_1', 'z_1']\n\n# --- PREDICTION CODE ENDS HERE ---\n\n# --- CREATE SUBMISSION FILE ---\nsubmission_df = pd.DataFrame(all_structure_data, columns=col_names)\n\nsubmission_filename = 'submission.csv'\nsubmission_df.to_csv(submission_filename, index=False)\n\n# --- VERIFY SUBMISSION FILE CREATION ---\nif os.path.exists(submission_filename):\n    print(f\"Submission file '{submission_filename}' created successfully!\")\n    print(\"\\nFirst 5 rows of submission.csv:\")\n    display(HTML(submission_df.head().to_html(index=False)))  # Show the first few rows\n    print(f\"\\nSubmission contains: {len(submission_df)} rows\")  # Shows the number of rows\nelse:\n    print(f\"ERROR: Submission file '{submission_filename}' was NOT created!\")\n\nprint(\"Make sure to submit file named submission.csv\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-04T08:25:58.373679Z","iopub.execute_input":"2025-03-04T08:25:58.373976Z","iopub.status.idle":"2025-03-04T08:26:01.120681Z","shell.execute_reply.started":"2025-03-04T08:25:58.373943Z","shell.execute_reply":"2025-03-04T08:26:01.119803Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport math\nimport os\nfrom IPython.display import display, HTML\nimport numpy as np\n\ndef generate_human_dna_helix(sequence_length, structure_number):\n    \"\"\"Generates a single helical 3D structure simulating human DNA base composition.\n\n    Args:\n      sequence_length:  The length of the DNA sequence to generate\n      structure_number: A parameter to slightly vary the helix for multiple structures.\n\n    Returns:\n      x_coords, y_coords, z_coords:  NumPy arrays of coordinates.\n    \"\"\"\n    #Base percentages of A,T,G,C\n    a_percent = 0.3\n    t_percent = 0.303\n    g_percent = 0.195\n    c_percent = 0.199\n\n    base_composition = {'A': a_percent, 'T': t_percent, 'G': g_percent, 'C': c_percent}\n\n    # Normalize probabilities to sum to 1\n    total_probability = sum(base_composition.values())\n    for base in base_composition:\n        base_composition[base] /= total_probability\n\n    #Generate the base code\n    dna_sequence = ''.join(np.random.choice(list(base_composition.keys()), sequence_length, p=list(base_composition.values())))\n    #print (f\"Here is the {sequence_length} DNA base code: {dna_sequence}\") #Unnecessary print\n    helix_radius = 5.0\n    helix_pitch = 3.0\n    angles = np.linspace(0, 4 * np.pi, sequence_length)  # Helix angles (4 pi = two full turns)\n    random_offsets = np.random.rand(sequence_length) # Add some noise\n\n    x_coords = helix_radius * np.cos(angles) + random_offsets\n    y_coords = helix_radius * np.sin(angles) + random_offsets\n    z_coords = helix_pitch * angles  # Linear increase for the helix, multiplied by the structure number\n\n    return dna_sequence, x_coords, y_coords, z_coords #Return the bases too, for each dna structure\n\n\ndef generate_submission_file(test_file, num_structures = 5):\n    \"\"\"Generates submission file for the competition, as described in problem desciption\"\"\"\n\n    # Load data:\n    test_df = pd.read_csv(test_file)\n\n    # Prepare a list to hold all points (for the submission file)\n    submission_list = [] # The data\n\n    #Create a total of num_structures coordinates per item, and add it to the file\n    for num_row_test in range(test_df.shape[0]):\n        row_test = test_df.iloc[num_row_test, :] #Extract the test data\n        target_id = row_test[\"target_id\"] #What the results get mapped to\n\n        sequence = row_test[\"sequence\"]  # What data gets run through\n        total_pts = len(sequence)        # What the sequence will be\n\n        for number_runs in range(num_structures):   # Create all combinations for each target_id\n\n            #Run the results through your algorithm, and store the data points.\n            bases, x_coords, y_coords, z_coords = generate_human_dna_helix(total_pts, number_runs + 1) # run the code for a\n\n            for res_num in range (total_pts):  # Store all values to the list\n\n                #Create a unique targetID from the run.\n                unique_id = target_id + \"_\" + str(number_runs + 1) #Each run gets added\n\n                #Make sure there are the right datatypes, since there have been many errors related to this.\n                data_row = [unique_id,  str(bases[res_num]), str(res_num + 1), float(x_coords[res_num]), float(y_coords[res_num]), float(z_coords[res_num])]\n\n                #Append\n                submission_list.append(data_row)\n\n    #Name headers that are stored\n    header_names = [\"ID\", \"resname\", \"resid\", \"x_1\", \"y_1\", \"z_1\"]\n\n    #Create the Dataframe from the stored file.\n    df = pd.DataFrame(submission_list, columns=header_names)\n\n    #Create and export the dataframe to csv.\n    df.to_csv(\"submission.csv\", index = False)\n\n    #Load df.\n    submission = pd.read_csv(\"submission.csv\") #Ensure that datatypes are what is expected\n    print (submission.head(50))\n    return submission\n\n#Replace this filename to read through the submission algorithm.\ncompetition_name = \"stanford-rna-3d-folding\"\nfilename = f\"/kaggle/input/{competition_name}/test_sequences.csv\" #Added in filename, the directory\n\nsubmission = generate_submission_file(filename)\n\nprint (\"Finished!\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-04T08:26:01.123032Z","iopub.execute_input":"2025-03-04T08:26:01.123327Z","iopub.status.idle":"2025-03-04T08:26:01.264924Z","shell.execute_reply.started":"2025-03-04T08:26:01.123280Z","shell.execute_reply":"2025-03-04T08:26:01.263922Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import numpy as np\nimport matplotlib.pyplot as plt\nfrom mpl_toolkits.mplot3d import Axes3D\n\ndef generate_double_helix(sequence_length, structure_number):\n    \"\"\"Generates a single helical 3D structure, as well as its partner helix.\n\n    Args:\n      sequence_length:  The length of the DNA sequence to generate\n      structure_number: A parameter to slightly vary the helix for multiple structures.\n\n    Returns:\n      x_coords, y_coords, z_coords:  Arrays of coordinates for helix 1.\n      x_coords2, y_coords2, z_coords2:  Arrays of coordinates for helix 2.\n    \"\"\"\n    helix_radius = 5.0\n    helix_pitch = 3.0\n    angles = np.linspace(0, 4 * np.pi, sequence_length)  # Helix angles (4 pi = two full turns)\n    random_offsets = np.random.rand(sequence_length) # Add some noise\n\n    #Helix 1\n    x_coords = helix_radius * np.cos(angles) + random_offsets\n    y_coords = helix_radius * np.sin(angles) + random_offsets\n    z_coords = helix_pitch * angles  # Linear increase for the helix\n\n    #Helix 2 (Partner)\n    x_coords2 = helix_radius * np.cos(angles + np.pi) + random_offsets #Phase shift\n    y_coords2 = helix_radius * np.sin(angles + np.pi) + random_offsets #Phase shift\n    z_coords2 = helix_pitch * angles #The code will run with the structure number, and it is not required in current use\n\n    return x_coords, y_coords, z_coords, x_coords2, y_coords2, z_coords2\n\nsequence_length = 100 #Number points in sequence, adjust\nnum_structure = 1\n\n#Example of code running:\n#Generate helices for plot\nx_coords, y_coords, z_coords, x_coords2, y_coords2, z_coords2 = generate_double_helix(sequence_length, num_structure)\n\n#Set up figure for plot, with all of the required axis\nfig = plt.figure(figsize=(8, 8))\nax = fig.add_subplot(111, projection='3d')\n\n#Plot the helixes\nax.plot(x_coords, y_coords, z_coords, c='blue', label=\"Helix 1\") #Sets the single point as the start\nax.plot(x_coords2, y_coords2, z_coords2, c='red', label=\"Helix 2\") #Sets the single point as the start\n\n#Plot all graph information to setup plot\nax.set_xlabel(\"X\")\nax.set_ylabel(\"Y\")\nax.set_zlabel(\"Z\")\nax.set_title(\"Double Helix Structure\")\nax.legend()\n\n#Set a limit that is equal to all of the points to generate structure\nx_range = np.abs(x_coords).max()\ny_range = np.abs(y_coords).max()\nz_range = np.abs(z_coords).max()\nmax_range = np.array([x_range, y_range, z_range]).max()\n\nax_range = 1.2*(max_range + 1)\nax.set_xlim([-ax_range, ax_range])\nax.set_ylim([-ax_range, ax_range])\nax.set_zlim([0, ax_range])\n\n#Rotate camera as needed\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-04T08:26:01.266339Z","iopub.execute_input":"2025-03-04T08:26:01.266706Z","iopub.status.idle":"2025-03-04T08:26:01.465707Z","shell.execute_reply.started":"2025-03-04T08:26:01.266680Z","shell.execute_reply":"2025-03-04T08:26:01.464507Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nfrom itertools import combinations\n\ndef find_best_double_helices(submission_file):\n    \"\"\"\n    Finds the best-matching pairs of helices from a submission file based on a similarity score.\n\n    Args:\n      submission_file: The path to the submission.csv file.\n\n    Returns:\n      A Pandas DataFrame with the best double helix pairs and their similarity scores.\n    \"\"\"\n    try:\n        submission = pd.read_csv(submission_file)\n    except FileNotFoundError:\n        print(f\"Error: Submission file '{submission_file}' not found.\")\n        return None\n\n    # 1. Group by Target ID\n    submission['structure_num'] = submission['ID'].apply(lambda x: int(x.split('_')[-1]))  # Extract the structure number\n    grouped = submission.groupby('ID')\n\n    # 2.  Extract the coordinate data for each coordinate\n    helix_data = {} #Store list\n    for name, group in grouped:\n        coordinates = group[['x_1', 'y_1', 'z_1']].values\n        helix_data[name] = coordinates\n\n    # 3. Code to test how similar a dataset is\n    def calculate_similarity(helix1, helix2):\n        \"\"\"Calculates a similarity score between two helices.\"\"\"\n        diff = np.abs(helix1 - helix2) #Differences for all values\n        similarity = np.sum(diff) #Reduce all to single point\n        return similarity\n\n    # 4. Determine each sequence combination.\n    helix_ids = list(helix_data.keys())  # Get a list of all helix IDs.\n    helix_pairs = list(combinations(helix_ids, 2)) #Test all unique pairings\n\n\n    # 5. Find the best pairing\n    best_pairs = []  # store the results\n    all_used_ids = [] # All used combinations.\n    for target_id in test_df['target_id']: #Each unique target\n        possible_combinations = []  # all combos\n        target_combos = [pair for pair in helix_pairs if target_id in pair[0] and target_id in pair[1]] #Find combinations\n        target_combos = []\n        for pair in helix_pairs: #For all the helical pairs\n            if target_id in pair[0] and target_id in pair[1]:\n                for check_used in all_used_ids:\n                  if pair == check_used:\n                      break #If they've been used, don't generate point\n                target_combos.append(pair) #Else, add combination\n                all_used_ids.append(pair) #Added\n\n        best_pair = None\n        min_similarity = float('inf') # High to mean will always be smaller.\n        for pair in target_combos: # Test the current target's combo\n            #Get the id of the target.\n            helix1_id, helix2_id = pair\n            helix1 = helix_data[helix1_id] # Test that target ID\n            helix2 = helix_data[helix2_id] # Test that target ID\n\n            similarity = calculate_similarity(helix1, helix2) # Test how different they are\n            if similarity < min_similarity:\n                min_similarity = similarity\n                best_pair = (helix1_id, helix2_id) # Set that point as smallest\n\n        best_pairs.append((best_pair[0], best_pair[1], min_similarity)) # All smallest points are stored\n\n    # 6. All results of the best matches gets put into dataframe\n    double_helices = []\n    for helix1_id, helix2_id, similarity in best_pairs:\n        double_helices.append([helix1_id, helix2_id, similarity])\n        print (f\"Helix pairing best match: {helix1_id} and {helix2_id}, Similarity: {similarity}\")\n\n    #Create a Dataframe from the stored file, will then be used for plot.\n    best_pairings = pd.DataFrame(double_helices, columns=['Helix 1', 'Helix 2', 'Similarity'])\n    return best_pairings\n\n# Test and see if the code functions\n#Example of code running:\nsubmission_file = \"submission.csv\" #The file generated in a prior step\nbest_pairings = find_best_double_helices(submission_file)\n\nprint (best_pairings)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-04T08:26:01.466842Z","iopub.execute_input":"2025-03-04T08:26:01.467141Z","iopub.status.idle":"2025-03-04T08:26:01.539272Z","shell.execute_reply.started":"2025-03-04T08:26:01.467117Z","shell.execute_reply":"2025-03-04T08:26:01.538292Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nfrom mpl_toolkits.mplot3d import Axes3D\n\ndef plot_double_helices_from_pairing(best_pairings, submission_file):\n    \"\"\"Generates 3D plots of the best double helix pairs.\n\n    Args:\n      best_pairings: A DataFrame with the best double helix pairs and their similarity scores.\n      submission_file: The path to the submission.csv file.\n    \"\"\"\n    submission = pd.read_csv(submission_file)  # Load submission data\n    submission['structure_num'] = submission['ID'].apply(lambda x: int(x.split('_')[-1])) #Get which point it is\n\n    # Group by ID to obtain coordinates for each helix\n    grouped = submission.groupby('ID')\n\n    # Iterate over the best pairings and plot\n    for index, row in best_pairings.iterrows():\n        helix1_id = row['Helix 1']\n        helix2_id = row['Helix 2']\n        similarity = row['Similarity']\n\n        #If both values are none, pass\n        if (helix1_id == \"\" and helix2_id == \"\"):\n            continue\n\n        # Extract data for Helix 1\n        try:\n            group1 = grouped.get_group(helix1_id)  # Get data\n            x1 = group1['x_1'].values # Load x cord\n            y1 = group1['y_1'].values # Load y cord\n            z1 = group1['z_1'].values # Load z cord\n        except KeyError:\n            print(f\"KeyError: Could not find helix ID '{helix1_id}' in submission data.\")\n            continue\n\n        # Extract data for Helix 2\n        try:\n            group2 = grouped.get_group(helix2_id) #Load group\n            x2 = group2['x_1'].values #Load value x\n            y2 = group2['y_1'].values #Load value y\n            z2 = group2['z_1'].values #Load value z\n        except KeyError:\n            print(f\"KeyError: Could not find helix ID '{helix2_id}' in submission data.\")\n            continue\n\n        # Create the Plot:\n        fig = plt.figure(figsize=(8, 8))  #Adjust figure size\n        ax = fig.add_subplot(111, projection='3d')\n        ax.set_xlabel(\"X\")\n        ax.set_ylabel(\"Y\")\n        ax.set_zlabel(\"Z\")\n        ax.set_title(f\"Double Helix Pair: {helix1_id} & {helix2_id}\")\n        try:\n            ax.plot(x1, y1, z1, label=f\"{helix1_id} (Similarity: {similarity:.2f})\")\n            ax.plot(x2, y2, z2, label=f\"{helix2_id} (Similarity: {similarity:.2f})\")\n\n        except Exception as e:\n            print(f\"Plotting Error: {e}\") #Test\n\n        ax.legend()\n        plt.show()\n\n\n#Example values and run. This tests for sample input.\ndata = {'Helix 1': ['R1107_4', 'R1108_1', 'R1116_2', 'R1117v2_1', 'R1126_2', 'R1128_2', 'R1136_1', 'R1138_1', 'R1149_4', 'R1156_1', 'R1189_3', 'R1190_1'],\n        'Helix 2': ['R1107_5', 'R1108_4', 'R1116_4', 'R1117v2_2', 'R1126_4', 'R1128_3', 'R1136_2', 'R1138_5', 'R1149_5', 'R1156_3', 'R1189_5', 'R1190_4'],\n        'Similarity': [39.271966, 42.228064, 98.206036, 17.074912, 233.251683, 150.998057, 239.118322, 441.290446, 75.711110, 80.915374, 73.966377, 69.820728]}\n\nbest_pairings = pd.DataFrame(data) #Make dataframe\nsubmission_file = \"submission.csv\" #Load\n\nplot_double_helices_from_pairing(best_pairings, submission_file)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-04T08:26:01.540208Z","iopub.execute_input":"2025-03-04T08:26:01.540671Z","iopub.status.idle":"2025-03-04T08:26:04.219025Z","shell.execute_reply.started":"2025-03-04T08:26:01.540633Z","shell.execute_reply":"2025-03-04T08:26:04.217873Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport os\n\ndef generate_submission_file(test_file, num_structures=5):\n    \"\"\"\n    Generates submission file for the competition, with five predicted structures.\n\n    Args:\n      test_file: Path to the test_sequences.csv file.\n      num_structures: Number of predicted structures per sequence (default: 5).\n\n    Returns:\n      A Pandas DataFrame representing the submission file.\n    \"\"\"\n\n    # Load the test sequences data\n    try:\n        test_df = pd.read_csv(test_file)\n    except FileNotFoundError:\n        print(f\"Error: Test file '{test_file}' not found.\")\n        return None\n\n    submission_list = [] # Will store the output\n\n    for num_row_test in range(test_df.shape[0]): #Iterates and create values.\n        #Extract the test data and value counts for each value\n        row_test = test_df.iloc[num_row_test, :] #Extrat the test data\n        target_id = row_test[\"target_id\"] #Map to the correct target id\n        sequence = row_test[\"sequence\"] #Sequence will be the structure\n        total_pts = len(sequence)    #The total points\n\n        #Iterates through each of the structures and map the file. The task specifies 5 files.\n        for number_runs in range(num_structures): #Create all combinations for each target_id\n\n            #Run the results through your algorithm, and store the data points.\n            num_points = 3 #Generate random coordinates\n            x_coords = np.random.rand(total_pts)  #Replace: Replace coordinate generator\n            y_coords = np.random.rand(total_pts)  #Replace: Replace coordinate generator\n            z_coords = np.random.rand(total_pts)  #Replace: Replace coordinate generator\n\n            for res_num in range (total_pts): #Iterate to the end of the files\n\n                #Create a unique targetID from the run.\n                unique_id = target_id + \"_\" + str(number_runs + 1) #Each run gets added\n\n                #Get all the data and put the data to data_row\n                resname = sequence[res_num] #Get the name and store the value\n                data_row = [unique_id, resname, res_num+1, float(x_coords[res_num]), float(y_coords[res_num]), float(z_coords[res_num])]\n\n                #Append data to the submission list\n                submission_list.append(data_row)\n\n    #Set header and column names\n    header_names = [\"ID\", \"resname\", \"resid\", \"x_1\", \"y_1\", \"z_1\"] #Set each point\n\n    #All values get stored to the dataframe\n    df = pd.DataFrame(submission_list, columns=header_names)\n\n    #Export all data into file\n    df.to_csv(\"submission.csv\", index = False)\n\n    #Load to test if the file is in the correct format. Can be commented out\n    submission = pd.read_csv(\"submission.csv\") #Ensure that datatypes are what is expected\n    print (submission.head(50))\n    return submission\n\n# Replace this filename to read through the submission algorithm, with test data.\ncompetition_name = \"stanford-rna-3d-folding\"\nfilename = f\"/kaggle/input/{competition_name}/test_sequences.csv\" #Correct filename\n\nsubmission = generate_submission_file(filename)\n\n#Test for file success or failure to print in the notebook\nif (submission is None):\n        print (\"The algorithm did not pass. Please test with the proper file loaded in the notebook\")\nelse:\n        print (\"Algorithm has passed. Please submit the submission.csv file.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-04T08:26:04.220133Z","iopub.execute_input":"2025-03-04T08:26:04.220531Z","iopub.status.idle":"2025-03-04T08:26:04.347443Z","shell.execute_reply.started":"2025-03-04T08:26:04.220494Z","shell.execute_reply":"2025-03-04T08:26:04.346502Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport math\nimport os\nfrom IPython.display import display, HTML\nimport numpy as np\nimport matplotlib.pyplot as plt  # Import for plotting\nfrom mpl_toolkits.mplot3d import Axes3D  # Import for 3D plotting\n\n# Assume the existence of the following file on the host:\n#   - test_sequences.csv: test sequences\n\ndef calculate_lref_d0(df):\n    \"\"\"Calculates Lref and d0 for each entry in the DataFrame.\"\"\"\n    df['Lref'] = df['sequence'].apply(len)\n    df['d0'] = df['Lref'].apply(lambda lref: 0.6 * math.sqrt(lref - 0.5) - 2.5)\n    return df\n\n# Define the base path for the input files in Kaggle\ncompetition_name = \"stanford-rna-3d-folding\"\nbase_path = f\"/kaggle/input/{competition_name}/\"\n\n# Load the CSV files\ntry:\n    validation_csv_path = os.path.join(base_path, \"validation_sequences.csv\")\n    test_csv_path = os.path.join(base_path, \"test_sequences.csv\")\n\n    # Load the dataframes, raising FileNotFoundError exception if the files can't be found.\n    validation_df = pd.read_csv(validation_csv_path)\n    test_df = pd.read_csv(test_csv_path)\nexcept FileNotFoundError as e:\n    print(f\"Error: {e}\")\n    #If either of the dataframes can't be found, stop execution.\n    raise\n\n# Calculate Lref and d0 for both DataFrames\nvalidation_df = calculate_lref_d0(validation_df)\nprint(\"<h2>Validation Data:</h2>\")\ndisplay(HTML(validation_df[['target_id', 'sequence', 'Lref', 'd0']].to_html(index=False)))\n\ntest_df = calculate_lref_d0(test_df)\nprint(\"<h2>Test Data:</h2>\")\ndisplay(HTML(test_df[['target_id', 'sequence', 'Lref', 'd0']].to_html(index=False)))\n\n# --- PREDICTION CODE STARTS HERE ---\n# REPLACE THIS ENTIRE SECTION WITH YOUR ACTUAL MODEL AND 3D STRUCTURE PREDICTION LOGIC!\n# This is placeholder code to generate random coordinates, attempting to simulate\n# a helical structure. You MUST adapt this to use your trained model to predict\n# the 3D structure of each RNA sequence in 'test_df'.\n\n# Parameters to control the helix generation (adjust these!)\nnum_structures = 2  # Two helices for a double helix\nnp.random.seed(42)  # For reproducibility\nhelix_radius = 5.0  # Radius of the helix\nhelix_pitch = 3.0  # Vertical distance between turns\nz_scaling_factor = 1.0\n\ndef generate_helical_structure(sequence_length, structure_number, phase_shift=0):\n    \"\"\"Generates a single helical 3D structure (coordinates for each residue).\"\"\"\n    angles = np.linspace(0, 4 * np.pi, sequence_length) + phase_shift  # Angles for points along the helix, including phase shift\n    random_offsets = np.random.rand(sequence_length) * 1.0  # Add some random noise\n    x_coords = helix_radius * np.cos(angles) + random_offsets\n    y_coords = helix_radius * np.sin(angles) + random_offsets\n    z_coords = helix_pitch * angles  + z_scaling_factor * structure_number\n    return x_coords, y_coords, z_coords\n\nall_structure_data = []\n\n# Create a single figure and axes for all plots\nfig = plt.figure(figsize=(12, 8))\nax = fig.add_subplot(111, projection='3d')\nax.set_xlabel(\"X\")\nax.set_ylabel(\"Y\")\nax.set_zlabel(\"Z\")\nax.set_title(\"3D Structures of RNA Sequences\")  # General plot title\n\n# Generate the plots together\nfor index, row in test_df.iterrows():\n    target_id = row['target_id']\n    sequence = row['sequence']\n    sequence_length = len(sequence)\n\n    # Generate a color for the sequence (for plotting) - removed, will use fixed colors for helices.\n    # color = np.random.rand(3,)\n\n    # Plot the two helices for each sequence\n    x_coords1, y_coords1, z_coords1 = generate_helical_structure(sequence_length, 1)\n    x_coords2, y_coords2, z_coords2 = generate_helical_structure(sequence_length, 2, phase_shift=np.pi)  # Add phase shift\n\n    ax.plot(x_coords1, y_coords1, z_coords1, c='red', label=f\"{target_id} Helix 1\")\n    ax.plot(x_coords2, y_coords2, z_coords2, c='blue', label=f\"{target_id} Helix 2\")\n\n    # Populate structure data for Helix 1\n    for residue_index in range(sequence_length):\n        resname = sequence[residue_index]\n        resid = residue_index + 1\n        structure_id = f\"{target_id}_1\"\n        all_structure_data.append([structure_id, resname, resid, x_coords1[residue_index], y_coords1[residue_index], z_coords1[residue_index]])\n\n    # Populate structure data for Helix 2\n    for residue_index in range(sequence_length):\n        resname = sequence[residue_index]\n        resid = residue_index + 1\n        structure_id = f\"{target_id}_2\"\n        all_structure_data.append([structure_id, resname, resid, x_coords2[residue_index], y_coords2[residue_index], z_coords2[residue_index]])\n\nax.legend() # Add a legend\nplt.show() # Show plots\n\n#Create the columns based on the structure of all_structure_data\ncol_names = ['ID', 'resname', 'resid', 'x_1', 'y_1', 'z_1']\n\n# --- PREDICTION CODE ENDS HERE ---\n\n# --- CREATE SUBMISSION FILE ---\nsubmission_df = pd.DataFrame(all_structure_data, columns=col_names)\n\nsubmission_filename = 'submission.csv'\nsubmission_df.to_csv(submission_filename, index=False)\n\n# --- VERIFY SUBMISSION FILE CREATION ---\nif os.path.exists(submission_filename):\n    print(f\"Submission file '{submission_filename}' created successfully!\")\n    print(\"\\nFirst 5 rows of submission.csv:\")\n    display(HTML(submission_df.head().to_html(index=False)))  # Show the first few rows\n    print(f\"\\nSubmission contains: {len(submission_df)} rows\")  # Shows the number of rows\nelse:\n    print(f\"ERROR: Submission file '{submission_filename}' was NOT created!\")\n\nprint(\"Make sure to submit file named submission.csv\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-04T08:26:04.348452Z","iopub.execute_input":"2025-03-04T08:26:04.348795Z","iopub.status.idle":"2025-03-04T08:26:04.935295Z","shell.execute_reply.started":"2025-03-04T08:26:04.348764Z","shell.execute_reply":"2025-03-04T08:26:04.934271Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport math\nimport os\nfrom IPython.display import display, HTML\nimport numpy as np\nimport matplotlib.pyplot as plt  # Import for plotting\nfrom mpl_toolkits.mplot3d import Axes3D  # Import for 3D plotting\nfrom sklearn.metrics import pairwise_distances\n\n# Assume the existence of the following file on the host:\n#   - test_sequences.csv: test sequences\n\ndef calculate_lref_d0(df):\n    \"\"\"Calculates Lref and d0 for each entry in the DataFrame.\"\"\"\n    df['Lref'] = df['sequence'].apply(len)\n    df['d0'] = df['Lref'].apply(lambda lref: 0.6 * math.sqrt(lref - 0.5) - 2.5)\n    return df\n\n# Define the base path for the input files in Kaggle\ncompetition_name = \"stanford-rna-3d-folding\"\nbase_path = f\"/kaggle/input/{competition_name}/\"\n\n# Load the CSV files\ntry:\n    validation_csv_path = os.path.join(base_path, \"validation_sequences.csv\")\n    test_csv_path = os.path.join(base_path, \"test_sequences.csv\")\n    validation_labels_path = os.path.join(base_path, \"validation_labels.csv\")\n\n    # Load the dataframes, raising FileNotFoundError exception if the files can't be found.\n    validation_df = pd.read_csv(validation_csv_path)\n    test_df = pd.read_csv(test_csv_path)\n    validation_labels_df = pd.read_csv(validation_labels_path)\n\nexcept FileNotFoundError as e:\n    print(f\"Error: {e}\")\n    #If either of the dataframes can't be found, stop execution.\n    raise\n\n# Calculate Lref and d0 for both DataFrames\nvalidation_df = calculate_lref_d0(validation_df)\nprint(\"<h2>Validation Data:</h2>\")\ndisplay(HTML(validation_df[['target_id', 'sequence', 'Lref', 'd0']].to_html(index=False)))\n\ntest_df = calculate_lref_d0(test_df)\nprint(\"<h2>Test Data:</h2>\")\ndisplay(HTML(test_df[['target_id', 'sequence', 'Lref', 'd0']].to_html(index=False)))\n\n# Extract target IDs from validation_labels.csv\ntarget_ids_from_labels = validation_labels_df['ID'].str.split('_').str[0].unique()\n\n# Find descriptions from test_sequences.csv that match the target IDs\nrelevant_descriptions = test_df[test_df['target_id'].isin(target_ids_from_labels)][['target_id', 'description']]\n\n# Print the relevant descriptions\nprint(\"\\n<h2>Relevant Descriptions from test_sequences.csv:</h2>\")\ndisplay(HTML(relevant_descriptions.to_html(index=False)))\n\n# --- PREDICTION CODE STARTS HERE ---\n# REPLACE THIS ENTIRE SECTION WITH YOUR ACTUAL MODEL AND 3D STRUCTURE PREDICTION LOGIC!\n# This is placeholder code to generate random coordinates, attempting to simulate\n# a helical structure. You MUST adapt this to use your trained model to predict\n# the 3D structure of each RNA sequence in 'test_df'.\n\n# Parameters to control the helix generation (adjust these!)\nnum_structures = 2  # Two helices for a double helix\nnp.random.seed(42)  # For reproducibility\nhelix_radius = 5.0  # Radius of the helix\nhelix_pitch = 3.0  # Vertical distance between turns\nz_scaling_factor = 1.0\n\ndef generate_helical_structure(sequence_length, structure_number, phase_shift=0):\n    \"\"\"Generates a single helical 3D structure (coordinates for each residue).\"\"\"\n    angles = np.linspace(0, 4 * np.pi, sequence_length) + phase_shift  # Angles for points along the helix, including phase shift\n    random_offsets = np.random.rand(sequence_length) * 1.0  # Add some random noise\n    x_coords = helix_radius * np.cos(angles) + random_offsets\n    y_coords = helix_radius * np.sin(angles) + random_offsets\n    z_coords = helix_pitch * angles  + z_scaling_factor * structure_number\n    return x_coords, y_coords, z_coords\n\nall_structure_data = []\nresults_data = []  # To store results for each sequence\n\n# Create a single figure and axes for all plots\nfig = plt.figure(figsize=(12, 8))\nax = fig.add_subplot(111, projection='3d')\nax.set_xlabel(\"X\")\nax.set_ylabel(\"Y\")\nax.set_zlabel(\"Z\")\nax.set_title(\"3D Structures of RNA Sequences\")  # General plot title\n\n# Generate the plots together\nfor index, row in test_df[test_df['target_id'].isin(target_ids_from_labels)].iterrows(): #Filter test_df\n    target_id = row['target_id']\n    sequence = row['sequence']\n    sequence_length = len(sequence)\n\n    # Generate the two helices\n    x_coords1, y_coords1, z_coords1 = generate_helical_structure(sequence_length, 1)\n    x_coords2, y_coords2, z_coords2 = generate_helical_structure(sequence_length, 2, phase_shift=np.pi)  # Add phase shift\n\n    ax.plot(x_coords1, y_coords1, z_coords1, c='red', label=f\"{target_id} Helix 1\")\n    ax.plot(x_coords2, y_coords2, z_coords2, c='blue', label=f\"{target_id} Helix 2\")\n\n    # Combine coordinates for singularity analysis (example: Euclidean distance)\n    all_coords = np.column_stack((np.concatenate([x_coords1, x_coords2]),\n                                   np.concatenate([y_coords1, y_coords2]),\n                                   np.concatenate([z_coords1, z_coords2])))\n\n    # Calculate distances.  Experiment with different distance metrics.\n    distance_matrix = pairwise_distances(all_coords)\n\n    # Calculate average distance (a simple measure of \"singularity\")\n    avg_distance = np.mean(distance_matrix)\n\n    results_data.append([target_id, sequence_length, avg_distance])\n\n    # Populate structure data (unchanged)\n    for residue_index in range(sequence_length):\n        resname = sequence[residue_index]\n        resid = residue_index + 1\n        structure_id = f\"{target_id}_1\"\n        all_structure_data.append([structure_id, resname, resid, x_coords1[residue_index], y_coords1[residue_index], z_coords1[residue_index]])\n    for residue_index in range(sequence_length):\n        resname = sequence[residue_index]\n        resid = residue_index + 1\n        structure_id = f\"{target_id}_2\"\n        all_structure_data.append([structure_id, resname, resid, x_coords2[residue_index], y_coords2[residue_index], z_coords2[residue_index]])\n\nax.legend() # Add a legend\nplt.show() # Show plots\n\n# Create results DataFrame and display table\nresults_df = pd.DataFrame(results_data, columns=['target_id', 'sequence_length', 'average_distance'])\nprint(\"<h2>Singularity Analysis Results:</h2>\")\ndisplay(HTML(results_df.to_html(index=False)))\n\n# Create singularity comparison plot\nplt.figure(figsize=(10, 6))\nplt.bar(results_df['target_id'], results_df['average_distance'])\nplt.xlabel(\"Target ID\")\nplt.ylabel(\"Average Distance (Singularity Measure)\")\nplt.title(\"Comparison of Singularity Measures\")\nplt.xticks(rotation=45, ha='right')  # Rotate x-axis labels for readability\nplt.tight_layout()\nplt.show()\n\n#Create the columns based on the structure of all_structure_data\ncol_names = ['ID', 'resname', 'resid', 'x_1', 'y_1', 'z_1']\n\n# --- CREATE SUBMISSION FILE ---\nsubmission_df = pd.DataFrame(all_structure_data, columns=col_names)\n\nsubmission_filename = 'submission.csv'\nsubmission_df.to_csv(submission_filename, index=False)\n\n# --- VERIFY SUBMISSION FILE CREATION ---\nif os.path.exists(submission_filename):\n    print(f\"Submission file '{submission_filename}' created successfully!\")\n    print(\"\\nFirst 5 rows of submission.csv:\")\n    display(HTML(submission_df.head().to_html(index=False)))  # Show the first few rows\n    print(f\"\\nSubmission contains: {len(submission_df)} rows\")  # Shows the number of rows\nelse:\n    print(f\"ERROR: Submission file '{submission_filename}' was NOT created!\")\n\nprint(\"Make sure to submit file named submission.csv\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-04T08:26:05.560323Z","iopub.execute_input":"2025-03-04T08:26:05.560733Z","iopub.status.idle":"2025-03-04T08:26:06.516589Z","shell.execute_reply.started":"2025-03-04T08:26:05.560703Z","shell.execute_reply":"2025-03-04T08:26:06.515595Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport math\nimport os\nfrom IPython.display import display, HTML\nimport numpy as np\n# import matplotlib.pyplot as plt  # No need for matplotlib in submission\n# from mpl_toolkits.mplot3d import Axes3D  # No need for 3D plotting in submission\n# from sklearn.metrics import pairwise_distances  # No need for singularity analysis\n\n# Assume the existence of the following file on the host:\n#   - test_sequences.csv: test sequences\n\ndef calculate_lref_d0(df):\n    \"\"\"Calculates Lref and d0 for each entry in the DataFrame.\"\"\"\n    df['Lref'] = df['sequence'].apply(len)\n    df['d0'] = df['Lref'].apply(lambda lref: 0.6 * math.sqrt(lref - 0.5) - 2.5)\n    return df\n\n# Define the base path for the input files in Kaggle\ncompetition_name = \"stanford-rna-3d-folding\"\nbase_path = f\"/kaggle/input/{competition_name}/\"\n\n# Load the CSV files\ntry:\n    # validation_csv_path = os.path.join(base_path, \"validation_sequences.csv\") #No need to load validation data in submission\n    test_csv_path = os.path.join(base_path, \"test_sequences.csv\")\n    # validation_labels_path = os.path.join(base_path, \"validation_labels.csv\") #No need to load validation labels in submission\n\n    # Load the dataframes, raising FileNotFoundError exception if the files can't be found.\n    # validation_df = pd.read_csv(validation_csv_path) #No need to load validation data in submission\n    test_df = pd.read_csv(test_csv_path)\n    # validation_labels_df = pd.read_csv(validation_labels_path) #No need to load validation labels in submission\n\nexcept FileNotFoundError as e:\n    print(f\"Error: {e}\")\n    #If either of the dataframes can't be found, stop execution.\n    raise\n\n# Calculate Lref and d0 for the test DataFrame\ntest_df = calculate_lref_d0(test_df)\n# print(\"<h2>Test Data:</h2>\")\n# display(HTML(test_df[['target_id', 'sequence', 'Lref', 'd0']].to_html(index=False))) #No need to display test data in submission\n\n# Extract target IDs from test_sequences.csv\ntarget_ids = test_df['target_id'].unique()\n\n# --- PREDICTION CODE STARTS HERE ---\n# REPLACE THIS ENTIRE SECTION WITH YOUR ACTUAL MODEL AND 3D STRUCTURE PREDICTION LOGIC!\n# This is placeholder code to generate random coordinates, attempting to simulate\n# a helical structure. You MUST adapt this to use your trained model to predict\n# the 3D structure of each RNA sequence in 'test_df'.\n\n# Parameters to control the helix generation (adjust these!)\nnum_structures = 5  # Predict five structures\nnp.random.seed(42)  # For reproducibility\nhelix_radius = 5.0  # Radius of the helix\nhelix_pitch = 3.0  # Vertical distance between turns\n\ndef generate_helical_structure(sequence_length, structure_number, phase_shift=0):\n    \"\"\"Generates a single helical 3D structure (coordinates for each residue).\"\"\"\n    angles = np.linspace(0, 4 * np.pi, sequence_length) + phase_shift  # Angles for points along the helix, including phase shift\n    random_offsets = np.random.rand(sequence_length) * 1.0  # Add some random noise\n    x_coords = helix_radius * np.cos(angles) + random_offsets\n    y_coords = helix_radius * np.sin(angles) + random_offsets\n    z_coords = helix_pitch * angles  + structure_number #Linear progression for z coords\n    return x_coords, y_coords, z_coords\n\nall_structure_data = []\n\nfor target_id in target_ids:  # Iterate through all target IDs in test_df\n    row = test_df[test_df['target_id'] == target_id].iloc[0]\n    sequence = row['sequence']\n    sequence_length = len(sequence)\n\n    # Generate multiple structures (5 in this case)\n    for structure_index in range(1, num_structures + 1):\n        x_coords, y_coords, z_coords = generate_helical_structure(sequence_length, structure_index)\n\n        for residue_index in range(sequence_length):\n            resname = sequence[residue_index]\n            resid = residue_index + 1\n            all_structure_data.append([f\"{target_id}_{resid}\", resname, resid, x_coords[residue_index], y_coords[residue_index], z_coords[residue_index]])\n\n# --- CREATE SUBMISSION FILE ---\n#Create the columns based on the structure of all_structure_data\ncol_names = ['ID', 'resname', 'resid', 'x_1', 'y_1', 'z_1']\nsubmission_df = pd.DataFrame(all_structure_data, columns=col_names)\n\n# Create new dataframe with the required submission format\nreshaped_data = []\n\nfor index, row in submission_df.iterrows():\n    ID, resname, resid, x_1, y_1, z_1 = row\n\n    # Extract base ID, resname, and resid\n    base_id = ID.rsplit('_', 1)[0]  # Get target_id from ID\n    resname = row['resname']\n    resid = row['resid']\n\n    # Create a dictionary to store the reshaped data\n    reshaped_row = {'ID': f\"{base_id}_{resid}\", 'resname': resname, 'resid': resid}\n\n    # Find all rows with the same base ID and resid\n    matching_rows = submission_df[(submission_df['ID'].str.startswith(base_id)) & (submission_df['resid'] == resid)]\n\n    # Iterate through the matching rows and add the coordinates to the reshaped row\n    for i in range(1, num_structures + 1):\n        coords = matching_rows[matching_rows['ID'].str.endswith(f\"_{resid}\")][['x_1', 'y_1', 'z_1']].values.flatten()\n        if len(coords) > 0:\n            reshaped_row[f'x_{i}'] = coords[0]\n            reshaped_row[f'y_{i}'] = coords[1]\n            reshaped_row[f'z_{i}'] = coords[2]\n\n    reshaped_data.append(reshaped_row)\n\nreshaped_df = pd.DataFrame(reshaped_data)\n\nsubmission_filename = 'submission.csv'\nreshaped_df.to_csv(submission_filename, index=False)\n\n# --- VERIFY SUBMISSION FILE CREATION ---\nif os.path.exists(submission_filename):\n    print(f\"Submission file '{submission_filename}' created successfully!\")\n    print(\"\\nFirst 5 rows of submission.csv:\")\n    display(HTML(reshaped_df.head().to_html(index=False)))  # Show the first few rows\n    print(f\"\\nSubmission contains: {len(reshaped_df)} rows\")  # Shows the number of rows\nelse:\n    print(f\"ERROR: Submission file '{submission_filename}' was NOT created!\")\n\nprint(\"Make sure to submit file named submission.csv\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-29T02:54:36.326243Z","iopub.execute_input":"2025-03-29T02:54:36.326574Z","iopub.status.idle":"2025-03-29T02:56:14.344360Z","shell.execute_reply.started":"2025-03-29T02:54:36.326548Z","shell.execute_reply":"2025-03-29T02:56:14.343425Z"}},"outputs":[],"execution_count":null}]}