{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.12.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":118765,"databundleVersionId":15231210,"sourceType":"competition"}],"dockerImageVersionId":31236,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nfrom scipy.spatial.transform import Rotation as R\nimport random\nfrom Bio import pairwise2\nfrom Bio.Seq import Seq\nimport time\nfrom scipy.spatial import distance_matrix\nimport warnings\n\nwarnings.filterwarnings('ignore')\n\n# === 1. ЗАГРУЗКА ===\nDATA_PATH = '/kaggle/input/stanford-rna-3d-folding-2/'\n\n# Загружаем базовые данные\ntrain_seqs = pd.read_csv(DATA_PATH + 'train_sequences.csv')\ntest_seqs = pd.read_csv(DATA_PATH + 'test_sequences.csv')\ntrain_labels = pd.read_csv(DATA_PATH + 'train_labels.csv')\n\n# ===== ЕДИНСТВЕННОЕ ИЗМЕНЕНИЕ: ПРОБУЕМ ЗАГРУЗИТЬ ВАЛИДАЦИЮ =====\ntry:\n    validation_seqs = pd.read_csv(DATA_PATH + 'validation_sequences.csv')\n    validation_labels = pd.read_csv(DATA_PATH + 'validation_labels.csv')\n    print(\"Validation data found and will be combined with train data.\")\n    \n    # Объединяем последовательности\n    combined_seqs = pd.concat([train_seqs, validation_seqs], ignore_index=True)\n    \n    # Объединяем labels\n    combined_labels = pd.concat([train_labels, validation_labels], ignore_index=True)\n    \nexcept FileNotFoundError:\n    print(\"Validation data not found, using only train data.\")\n    combined_seqs = train_seqs\n    combined_labels = train_labels\n# ===== КОНЕЦ ИЗМЕНЕНИЯ =====\n\ndef process_labels(labels_df):\n    coords_dict = {}\n    for id_prefix, group in labels_df.groupby(lambda x: labels_df['ID'][x].rsplit('_', 1)[0]):\n        coords = [group.sort_values('resid')[['x_1', 'y_1', 'z_1']].values]\n        coords_dict[id_prefix] = coords[0]\n    return coords_dict\n\n# Используем ОБЪЕДИНЕННЫЕ данные вместо только train\ncombined_coords_dict = process_labels(combined_labels)\n\n# === 2. ЭВРИСТИКИ (без изменений) ===\n\ndef find_similar_sequences(query_seq, train_seqs_df, train_coords_dict, top_n=5):\n    similar_seqs = []\n    query_seq_obj = Seq(query_seq)\n    \n    for _, row in train_seqs_df.iterrows():\n        target_id, train_seq = row['target_id'], row['sequence']\n        if target_id not in train_coords_dict: continue\n        if abs(len(train_seq) - len(query_seq)) / max(len(train_seq), len(query_seq)) > 0.4: continue\n        \n        # ПРАВКА 1: Немного изменили штрафы за гэпы (-10 -> -8, -0.5 -> -0.3)\n        # Это позволит лучше находить шаблоны с пропусками в петлях\n        alignments = pairwise2.align.globalms(query_seq_obj, train_seq, 2, -1, -8, -0.3, one_alignment_only=True)\n        \n        if alignments:\n            score = alignments[0].score / (2 * min(len(query_seq), len(train_seq)))\n            similar_seqs.append((target_id, train_seq, score, train_coords_dict[target_id]))\n    \n    similar_seqs.sort(key=lambda x: x[2], reverse=True)\n    return similar_seqs[:top_n]\n\ndef adaptive_rna_constraints(coordinates, sequence, confidence=1.0):\n    refined_coords = coordinates.copy()\n    n_residues = len(sequence)\n    \n    # ПРАВКА 2: Оптимизировали силу натяжения. Для хороших шаблонов (conf > 0.8) она почти нулевая.\n    constraint_strength = 0.7 * (1.0 - min(confidence, 0.95))\n    \n    # ПРАВКА 3: Сузили таргет-диапазон расстояния (было 5.5-6.5, стало 5.8-6.1)\n    # Это сделает цепочку более \"упругой\"\n    seq_min_dist, seq_max_dist = 5.8, 6.1\n    \n    for i in range(n_residues - 1):\n        dist = np.linalg.norm(refined_coords[i+1] - refined_coords[i])\n        if dist < seq_min_dist or dist > seq_max_dist:\n            target_dist = 5.95 \n            direction = (refined_coords[i+1] - refined_coords[i]) / (dist + 1e-10)\n            adjustment = (target_dist - dist) * constraint_strength\n            refined_coords[i+1] = refined_coords[i+1] + direction * adjustment\n            \n    return refined_coords\n\ndef adapt_template_to_query(query_seq, template_seq, template_coords):\n    # Код адаптации из оригинала (самый стабильный)\n    alignments = pairwise2.align.globalms(Seq(query_seq), Seq(template_seq), 2, -1, -8, -0.3, one_alignment_only=True)\n    if not alignments: return np.zeros((len(query_seq), 3))\n    \n    a_q, a_t = alignments[0].seqA, alignments[0].seqB\n    new_coords = np.full((len(query_seq), 3), np.nan)\n    q_idx, t_idx = 0, 0\n    for char_q, char_t in zip(a_q, a_t):\n        if char_q != '-' and char_t != '-':\n            if t_idx < len(template_coords): new_coords[q_idx] = template_coords[t_idx]\n            q_idx += 1; t_idx += 1\n        elif char_q != '-': q_idx += 1\n        elif char_t != '-': t_idx += 1\n\n    # Заполнение NaN\n    for i in range(len(new_coords)):\n        if np.isnan(new_coords[i, 0]):\n            prev_v = next((j for j in range(i-1, -1, -1) if not np.isnan(new_coords[j, 0])), -1)\n            next_v = next((j for j in range(i+1, len(new_coords)) if not np.isnan(new_coords[j, 0])), -1)\n            if prev_v >= 0 and next_v >= 0:\n                w = (i - prev_v) / (next_v - prev_v)\n                new_coords[i] = (1-w)*new_coords[prev_v] + w*new_coords[next_v]\n            elif prev_v >= 0: new_coords[i] = new_coords[prev_v] + [3, 0, 0]\n            elif next_v >= 0: new_coords[i] = new_coords[next_v] + [3, 0, 0]\n            else: new_coords[i] = [i*3, 0, 0]\n    return np.nan_to_num(new_coords)\n\ndef generate_rna_structure(sequence, seed=None):\n    if seed: np.random.seed(seed)\n    n = len(sequence)\n    coords = np.zeros((n, 3))\n    for i in range(1, n):\n        coords[i] = coords[i-1] + [random.uniform(3.8, 4.2), 0, 0]\n    return coords\n\n# === 3. PREDICT (без изменений, но используем combined данные) ===\n\ndef predict_rna_structures(sequence, target_id, train_seqs_df, train_coords_dict, n_predictions=5):\n    predictions = []\n    similar_seqs = find_similar_sequences(sequence, train_seqs_df, train_coords_dict, top_n=n_predictions)\n    \n    if similar_seqs:\n        for i, (template_id, template_seq, similarity, template_coords) in enumerate(similar_seqs):\n            adapted = adapt_template_to_query(sequence, template_seq, template_coords)\n            refined = adaptive_rna_constraints(adapted, sequence, confidence=similarity)\n            \n            # ПРАВКА 4: Снизили уровень шума для топовых шаблонов (0.05 -> 0.02)\n            # Это сохранит точность лучшего из 5 предсказаний\n            random_scale = max(0.01, (0.4 - similarity) * 0.1) \n            refined += np.random.normal(0, random_scale, refined.shape)\n            predictions.append(refined)\n                \n    while len(predictions) < n_predictions:\n        predictions.append(generate_rna_structure(sequence, seed=len(predictions)))\n    \n    return predictions[:n_predictions]\n\n# === 4. LOOP & SAVE (без изменений) ===\nall_predictions = []\nfor idx, row in test_seqs.iterrows():\n    target_id, sequence = row['target_id'], row['sequence']\n    if idx % 5 == 0: print(f\"Processing {idx+1}/{len(test_seqs)}\")\n    \n    # ВОТ ЗДЕСЬ ИСПОЛЬЗУЕМ ОБЪЕДИНЕННЫЕ ДАННЫЕ вместо train_seqs и train_coords_dict\n    preds = predict_rna_structures(sequence, target_id, combined_seqs, combined_coords_dict)\n    \n    for j in range(len(sequence)):\n        res = {'ID': f\"{target_id}_{j+1}\", 'resname': sequence[j], 'resid': j+1}\n        for i in range(5):\n            res[f'x_{i+1}'], res[f'y_{i+1}'], res[f'z_{i+1}'] = preds[i][j]\n        all_predictions.append(res)\n\nsubmission_df = pd.DataFrame(all_predictions)\ncols = ['ID', 'resname', 'resid'] + [f'{c}_{i}' for i in range(1,6) for c in ['x','y','z']]\nsubmission_df[cols].to_csv('submission.csv', index=False)\nprint(\"Submission.csv generated!\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#pip install numpy scipy biopython scikit-learn seaborn matplotlib","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-17T12:20:43.850756Z","iopub.execute_input":"2026-01-17T12:20:43.851453Z","iopub.status.idle":"2026-01-17T12:20:50.722796Z","shell.execute_reply.started":"2026-01-17T12:20:43.851421Z","shell.execute_reply":"2026-01-17T12:20:50.721898Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}