{ "cells": [ { "cell_type": "code", "execution_count": 3, "id": "d9c44f69", "metadata": {}, "outputs": [], "source": [ "import requests\n", "import json\n", "import time\n", "import numpy as np\n", "import os\n", "from re import A, L\n", "import numpy as np\n", "import pandas as pd\n", "from tqdm import tqdm\n", "import torch\n", "import tensorflow as tf\n", "import tensorflow.keras.backend as K\n", "from tensorflow.keras import Model\n", "from tensorflow.keras.models import load_model\n", "from util import *\n", "from framepool import *\n", "import sys\n", "from Bio import SeqIO\n", "\n", "tf.compat.v1.enable_eager_execution()\n", "\n", "__file__ = os.getcwd()\n", "\n", "sys.path.append(os.path.dirname(os.path.dirname(__file__)))\n", "\n", "\n", "from models import Modules\n", "import configparser\n", "from sklearn.preprocessing import OneHotEncoder\n", "import logging\n", "import collections\n", "from models.ScheduleOptimizer import ScheduledOptim\n", "\n", "SEQ_LEN=128\n", "TF_ENABLE_ONEDNN_OPTS=0\n", "\n", "DATA = './../../data/utrdb2.csv'\n", "BATCH_SIZE = 500\n", "GENE = 'VEGFA'\n", "GC_LIMIT = -1.00\n", "LR = 0.005\n", "GPU = '0'\n", "STEPS = 2\n", "\n", "if GPU == '-1':\n", " device = 'cpu'\n", "else:\n", " os.environ['CUDA_VISIBLE_DEVICES'] = GPU\n", " device = 'cuda'\n", "\n", "\n", "def reverse_complement(sequence):\n", " \"\"\"Compute the reverse complement of a DNA sequence.\"\"\"\n", " complement = {'A': 'T', 'T': 'A', 'C': 'G', 'G': 'C', \n", " 'a': 't', 't': 'a', 'c': 'g', 'g': 'c', 'N': 'N', 'n': 'N'}\n", " return ''.join(complement.get(base, 'N') for base in reversed(sequence))\n", "\n", "\n", "class GeneInfoRetriever:\n", " def __init__(self):\n", " self.base_url = \"https://rest.ensembl.org\"\n", " self.headers = {\"Content-Type\": \"application/json\"}\n", " self.sleep_time = 0.5 # Respect Ensembl API rate limits\n", "\n", " def _make_request(self, endpoint):\n", " \"\"\"Make a request to the Ensembl REST API.\"\"\"\n", " url = self.base_url + endpoint\n", " try:\n", " response = requests.get(url, headers=self.headers)\n", " time.sleep(self.sleep_time)\n", " if response.status_code == 200:\n", " return response.json()\n", " else:\n", " print(f\"Error: {response.status_code} - {response.text}\")\n", " return None\n", " except Exception as e:\n", " print(f\"Request error: {e}\")\n", " return None\n", "\n", " def get_gene_id(self, gene_symbol, species=\"homo_sapiens\"):\n", " \"\"\"Retrieve the Ensembl gene ID for a gene symbol.\"\"\"\n", " endpoint = f\"/lookup/symbol/{species}/{gene_symbol}\"\n", " response = self._make_request(endpoint)\n", " return response.get(\"id\") if response else None\n", "\n", " def get_gene_coordinates(self, gene_id):\n", " \"\"\"Retrieve genomic coordinates for a gene ID.\"\"\"\n", " endpoint = f\"/lookup/id/{gene_id}?expand=1\"\n", " response = self._make_request(endpoint)\n", " if response:\n", " return {\n", " \"chromosome\": response.get(\"seq_region_name\"),\n", " \"start\": response.get(\"start\"),\n", " \"end\": response.get(\"end\"),\n", " \"strand\": response.get(\"strand\")\n", " }\n", " return None\n", "\n", " def get_tss_and_utr(self, gene_id):\n", " \"\"\"Retrieve TSS and 5' UTR coordinates for the canonical transcript.\"\"\"\n", " endpoint = f\"/lookup/id/{gene_id}?expand=1&utr=1\"\n", " response = self._make_request(endpoint)\n", " if not response or \"Transcript\" not in response:\n", " return None\n", "\n", " # Find canonical transcript\n", " canonical_transcript = None\n", " for transcript in response[\"Transcript\"]:\n", " if transcript.get(\"is_canonical\", 0) == 1:\n", " canonical_transcript = transcript\n", " break\n", " if not canonical_transcript:\n", " for transcript in response[\"Transcript\"]:\n", " if transcript.get(\"biotype\") == \"protein_coding\":\n", " canonical_transcript = transcript\n", " break\n", " if not canonical_transcript:\n", " canonical_transcript = response[\"Transcript\"][0] if response[\"Transcript\"] else None\n", "\n", " if not canonical_transcript:\n", " return None\n", "\n", " # Determine TSS and 5' UTR\n", " strand = canonical_transcript.get(\"strand\")\n", " tss = canonical_transcript[\"start\"] if strand == 1 else canonical_transcript[\"end\"]\n", " five_prime_utr = None\n", "\n", " if \"UTR\" in canonical_transcript:\n", " for utr in canonical_transcript[\"UTR\"]:\n", " if utr.get(\"object_type\") == \"five_prime_UTR\":\n", " five_prime_utr = {\n", " \"start\": utr.get(\"start\"),\n", " \"end\": utr.get(\"end\")\n", " }\n", " break\n", "\n", " # Verify TSS matches 5' UTR start\n", " if five_prime_utr:\n", " expected_tss = five_prime_utr[\"start\"] if strand == 1 else five_prime_utr[\"end\"]\n", " if expected_tss != tss:\n", " print(f\"Warning: Adjusting TSS from {tss} to match 5' UTR {'start' if strand == 1 else 'end'} ({expected_tss})\")\n", " tss = expected_tss\n", "\n", " return {\n", " \"tss\": tss,\n", " \"strand\": strand,\n", " \"chromosome\": canonical_transcript.get(\"seq_region_name\"),\n", " \"five_prime_utr\": five_prime_utr,\n", " \"transcript_id\": canonical_transcript.get(\"id\")\n", " }\n", "\n", " def get_promoter_sequence(self, gene_id, upstream=7000, downstream=4000):\n", " \"\"\"Retrieve sequence around TSS (8kb upstream, 4kb downstream).\"\"\"\n", " tss_info = self.get_tss_and_utr(gene_id)\n", " if not tss_info:\n", " return None, None\n", "\n", " chromosome = tss_info[\"chromosome\"]\n", " strand = tss_info[\"strand\"]\n", " tss_position = tss_info[\"tss\"]\n", "\n", " # Calculate region based on strand\n", " if strand == 1:\n", " seq_start = tss_position - upstream\n", " seq_end = tss_position + downstream - 1\n", " else:\n", " seq_start = tss_position - downstream\n", " seq_end = tss_position + upstream - 1\n", "\n", " seq_start = max(1, seq_start)\n", "\n", " # Store sequence coordinates\n", " sequence_coords = {\n", " \"chromosome\": chromosome,\n", " \"start\": seq_start,\n", " \"end\": seq_end,\n", " \"strand\": 1 if strand == 1 else -1\n", " }\n", "\n", " # Validate 5' UTR inclusion\n", " if tss_info[\"five_prime_utr\"]:\n", " utr_start = tss_info[\"five_prime_utr\"][\"start\"]\n", " utr_end = tss_info[\"five_prime_utr\"][\"end\"]\n", " if not (seq_start <= utr_start <= seq_end and seq_start <= utr_end <= seq_end):\n", " print(f\"Warning: 5' UTR ({utr_start}-{utr_end}) not fully within sequence ({seq_start}-{seq_end})\")\n", "\n", " # Get sequence\n", " strand_str = \"1\" if strand == 1 else \"-1\"\n", " endpoint = f\"/sequence/region/human/{chromosome}:{seq_start}..{seq_end}:{strand_str}\"\n", " response = self._make_request(endpoint)\n", " return response.get(\"seq\") if response else None, sequence_coords\n", "\n", " def get_gene_info(self, gene_symbol, species=\"homo_sapiens\", output_json=\"gene_info.json\"):\n", " \n", " if not os.path.exists(os.path.join('./.cache/',f\"{gene_symbol}_info.json\")):\n", "\n", " \"\"\"Retrieve and save promoter sequence, TSS, 5' UTR, and coordinates.\"\"\"\n", " # Get gene ID\n", " gene_id = self.get_gene_id(gene_symbol, species)\n", " if not gene_id:\n", " return {\"error\": f\"Gene {gene_symbol} not found\"}\n", "\n", " # Get TSS and 5' UTR\n", " tss_info = self.get_tss_and_utr(gene_id)\n", " if not tss_info:\n", " return {\"error\": \"Could not retrieve TSS or transcript information\"}\n", "\n", " # Get promoter sequence and coordinates\n", " promoter_sequence, sequence_coords = self.get_promoter_sequence(gene_id)\n", " if not promoter_sequence:\n", " return {\"error\": \"Could not retrieve promoter sequence\"}\n", "\n", " # Compile gene information\n", " gene_info = {\n", " \"gene_symbol\": gene_symbol,\n", " \"gene_id\": gene_id,\n", " \"promoter_sequence\": promoter_sequence,\n", " \"sequence_length\": len(promoter_sequence),\n", " \"sequence_coordinates\": sequence_coords,\n", " \"tss\": {\n", " \"chromosome\": tss_info[\"chromosome\"],\n", " \"position\": tss_info[\"tss\"],\n", " \"strand\": \"+\" if tss_info[\"strand\"] == 1 else \"-\"\n", " },\n", " \"five_prime_utr\": tss_info[\"five_prime_utr\"],\n", " \"transcript_id\": tss_info[\"transcript_id\"]\n", " }\n", "\n", " # Save to JSON\n", " try:\n", " os.makedirs(os.path.dirname('./.cache/'), exist_ok=True)\n", " with open(os.path.join('./.cache/',f\"{gene_symbol}_info.json\"), \"w\") as f:\n", " json.dump(gene_info, f, indent=2)\n", " print(f\"Saved gene information to {output_json}\")\n", " except Exception as e:\n", " print(f\"Error saving JSON: {e}\")\n", "\n", " else:\n", "\n", " with open(os.path.join('./.cache/',f\"{gene_symbol}_info.json\"), \"r\") as f:\n", " gene_info = json.load(f)\n", "\n", " return gene_info\n", "\n", " def reverse_complement(self, sequence):\n", " \"\"\"Compute the reverse complement of a DNA sequence.\"\"\"\n", " complement = {'A': 'T', 'T': 'A', 'C': 'G', 'G': 'C', \n", " 'a': 't', 't': 'a', 'c': 'g', 'g': 'c', 'N': 'N', 'n': 'N'}\n", " return ''.join(complement.get(base, 'N') for base in reversed(sequence))\n", "\n", " def replace_utr_in_sequence(self, gene_info_file, generated_utrs, target_length=10500, output_prefix=\"modified_sequence\", write_json=False, verbose=False):\n", " \"\"\"\n", " Replace original 5' UTR with generated UTRs, ensuring 10,500nt output.\n", " \n", " Parameters:\n", " gene_info_file (str): Path to JSON file with gene information\n", " generated_utrs (list): List of generated 5' UTR sequences (64-128nt)\n", " target_length (int): Desired output sequence length (default: 10500)\n", " output_prefix (str): Prefix for output JSON files\n", " \n", " Returns:\n", " list: List of modified sequences with metadata\n", " \"\"\"\n", " try:\n", " # Read gene information\n", " with open(gene_info_file, \"r\") as f:\n", " gene_info = json.load(f)\n", "\n", " original_sequence = gene_info[\"promoter_sequence\"]\n", " strand = gene_info[\"tss\"][\"strand\"]\n", " tss_position = gene_info[\"tss\"][\"position\"]\n", " sequence_coords = gene_info[\"sequence_coordinates\"]\n", " seq_start = sequence_coords[\"start\"]\n", " seq_end = sequence_coords[\"end\"]\n", " five_prime_utr = gene_info[\"five_prime_utr\"]\n", " gene_symbol = gene_info[\"gene_symbol\"]\n", " transcript_id = gene_info[\"transcript_id\"]\n", "\n", " if not five_prime_utr:\n", " print(f\"Error: No 5' UTR information available for {gene_symbol}\")\n", " return []\n", "\n", " # Calculate original 5' UTR position in sequence\n", " if strand == \"+\":\n", " utr_start_genomic = five_prime_utr[\"start\"]\n", " utr_end_genomic = five_prime_utr[\"end\"]\n", " utr_start_seq = utr_start_genomic - seq_start\n", " utr_end_seq = utr_end_genomic - seq_start\n", " else:\n", " utr_start_genomic = five_prime_utr[\"end\"] # TSS\n", " utr_end_genomic = five_prime_utr[\"start\"]\n", " utr_start_seq = seq_end - utr_start_genomic\n", " utr_end_seq = seq_end - utr_end_genomic\n", "\n", " # Validate UTR positions\n", " seq_length = len(original_sequence)\n", " if not (0 <= utr_start_seq <= seq_length and 0 <= utr_end_seq <= seq_length):\n", " print(f\"Error: 5' UTR coordinates (seq indices {utr_start_seq}-{utr_end_seq}) out of sequence bounds (0-{seq_length}) for {gene_symbol}\")\n", " return []\n", "\n", " original_utr_length = abs(utr_end_genomic - utr_start_genomic) + 1\n", " if verbose:\n", " print(f\"Original 5' UTR length for {gene_symbol}: {original_utr_length} nt\")\n", "\n", " modified_sequences = []\n", " for i, new_utr in enumerate(generated_utrs):\n", " new_utr_length = len(new_utr)\n", "\n", " # Construct new sequence\n", " if strand == \"+\":\n", " new_sequence = (\n", " original_sequence[:utr_start_seq] +\n", " new_utr +\n", " original_sequence[utr_end_seq + 1:]\n", " )\n", " new_utr_start_genomic = utr_start_genomic\n", " new_utr_end_genomic = utr_start_genomic + new_utr_length - 1\n", " if len(new_sequence) > target_length:\n", " new_sequence = new_sequence[:target_length]\n", " sequence_coords[\"end\"] = seq_start + target_length - 1\n", " elif len(new_sequence) < target_length:\n", " if verbose:\n", " print(f\"Error: Sequence too short ({len(new_sequence)} nt) after UTR replacement for {gene_symbol}\")\n", " continue\n", " else:\n", " new_utr_rc = reverse_complement(new_utr)\n", " new_sequence = (\n", " original_sequence[:min(utr_start_seq, utr_end_seq)] +\n", " new_utr_rc +\n", " original_sequence[max(utr_start_seq, utr_end_seq) + 1:]\n", " )\n", " new_utr_start_genomic = utr_start_genomic\n", " new_utr_end_genomic = utr_start_genomic - new_utr_length + 1\n", " if len(new_sequence) > target_length:\n", " trim_amount = len(new_sequence) - target_length\n", " new_sequence = new_sequence[trim_amount:]\n", " sequence_coords[\"start\"] = seq_start + trim_amount\n", " elif len(new_sequence) < target_length:\n", " if verbose:\n", " print(f\"Error: Sequence too short ({len(new_sequence)} nt) after UTR replacement for {gene_symbol}\")\n", " continue\n", "\n", " # Store modified sequence and metadata\n", " modified_info = {\n", " \"gene_symbol\": gene_symbol,\n", " \"transcript_id\": transcript_id,\n", " \"modified_sequence\": new_sequence,\n", " \"sequence_length\": len(new_sequence),\n", " \"sequence_coordinates\": sequence_coords.copy(),\n", " \"tss\": gene_info[\"tss\"],\n", " \"five_prime_utr\": {\n", " \"start\": new_utr_start_genomic,\n", " \"end\": new_utr_end_genomic,\n", " \"sequence\": new_utr if strand == \"+\" else new_utr_rc\n", " },\n", " \"original_utr_length\": original_utr_length,\n", " \"new_utr_length\": new_utr_length,\n", " \"utr_index\": i + 1\n", " }\n", "\n", " # Save to JSON\n", " if write_json:\n", " output_file = f\"{output_prefix}_{gene_symbol}_utr_{i+1}.json\"\n", " try:\n", " os.makedirs(os.path.dirname(output_file), exist_ok=True)\n", " with open(output_file, \"w\") as f:\n", " json.dump(modified_info, f, indent=2)\n", " print(f\"Saved modified sequence {i+1} for {gene_symbol} to {output_file}\")\n", " except Exception as e:\n", " print(f\"Error saving modified sequence {i+1} for {gene_symbol}: {e}\")\n", "\n", " modified_sequences.append(modified_info[\"modified_sequence\"])\n", "\n", " return modified_sequences\n", "\n", " except Exception as e:\n", " # print(f\"Error processing UTR replacement for {gene_info.get('gene_symbol', 'unknown')}: {e}\")\n", " print(f\"Error processing UTR replacement for gene: {e}\")\n", " return []\n", "\n", "\n", " def replace_utr_in_multiple_sequences(self, gene_symbols, generated_utrs, target_length=10500, cache_dir=\"./.cache\", output_prefix=\"modified_sequence\", verbose=False):\n", " \"\"\"\n", " Replace 5' UTRs for multiple genes with generated UTRs.\n", " \n", " Parameters:\n", " gene_symbols (list): List of gene names\n", " generated_utrs (list): List of generated 5' UTR sequences (64-128nt)\n", " target_length (int): Desired output sequence length (default: 10500)\n", " cache_dir (str): Directory containing cached gene info JSON files\n", " output_prefix (str): Prefix for output JSON files\n", " \n", " Returns:\n", " list: List of n_utrs * n_genes modified sequences with metadata\n", " \"\"\"\n", " all_modified_sequences = []\n", " n_utrs = len(generated_utrs)\n", " n_genes = len(gene_symbols)\n", "\n", " for gene_symbol in gene_symbols:\n", " json_file = os.path.join(cache_dir, f\"{gene_symbol}_info.json\")\n", " if not os.path.exists(json_file):\n", " print(f\"Error: Gene info file {json_file} not found\")\n", " continue\n", " \n", " if verbose:\n", " print(f\"\\nProcessing gene: {gene_symbol}\")\n", " modified_sequences = self.replace_utr_in_sequence(\n", " gene_info_file=json_file,\n", " generated_utrs=generated_utrs,\n", " target_length=target_length,\n", " output_prefix=os.path.join(cache_dir, output_prefix)\n", " )\n", "\n", " if modified_sequences:\n", " all_modified_sequences.extend(modified_sequences)\n", " else:\n", " if verbose:\n", " print(f\"No modified sequences generated for {gene_symbol}\")\n", "\n", " expected_count = n_utrs * n_genes\n", " actual_count = len(all_modified_sequences)\n", " if verbose:\n", " print(f\"\\nGenerated {actual_count} modified sequences (expected: {expected_count})\")\n", "\n", " return all_modified_sequences\n", "\n", "def convert_model(model_:Model):\n", " input_ = tf.keras.layers.Input(shape=( 10500, 4))\n", " input = input_\n", " for i in range(len(model_.layers)-1):\n", "\n", " \n", " if isinstance(model_.layers[i+1],tf.keras.layers.Concatenate):\n", " paddings = tf.constant([[0,0],[0,6]])\n", " output = tf.pad(input, paddings, 'CONSTANT')\n", " input = output\n", " else:\n", " if not isinstance(model_.layers[i+1],tf.keras.layers.InputLayer):\n", " output = model_.layers[i+1](input)\n", " input = output\n", "\n", " if isinstance(model_.layers[i+1],tf.keras.layers.Conv1D):\n", " pass\n", "\n", " model = tf.keras.Model(inputs=input_, outputs=output)\n", " model.compile(loss=\"mse\", optimizer=\"adam\")\n", " return model\n", "\n", "def one_hot(seq):\n", " convert = False\n", " if isinstance(seq, tf.Tensor):\n", " seq = seq.numpy().astype(str)\n", " convert = True\n", "\n", " num_seqs = len(seq)\n", " seq_len = len(seq[0])\n", " seqindex = {'A':0, 'C':1, 'G':2, 'T':3, 'a':0, 'c':1, 'g':2, 't':3}\n", " seq_vec = np.zeros((num_seqs,seq_len,4), dtype='bool')\n", " for i in range(num_seqs):\n", " thisseq = seq[i]\n", " for j in range(seq_len):\n", " try:\n", " seq_vec[i,j,seqindex[thisseq[j]]] = 1\n", " except:\n", " pass\n", " \n", " if convert:\n", " seq_vec = tf.convert_to_tensor(seq_vec,dtype=tf.float32)\n", "\n", "\n", " return seq_vec\n", "\n", "def gen_random_dna(len=10500,size=SEQ_LEN):\n", " list_ = ['A','C','G','T']\n", " dnas = []\n", " for i in range(size):\n", " \n", " list_ = ['A','C','G','T']\n", " mydna = 'AGT'\n", " for i in range(len-3):\n", " char = list_[random.randint(0,3)]\n", " mydna = mydna + char\n", " dnas.append(mydna)\n", "\n", "\n", " return dnas\n", " \n", "def select_dna_single(fname='small_seqs.npy',batch_size=64):\n", " refs = np.load(fname)\n", " indice = random.sample(range(0,refs.shape[0]),1)\n", " refs = refs\n", " return indice[0], refs \n", "\n", "def recover_seq(samples, rev_charmap):\n", " \"\"\"Convert samples to strings and save to log directory.\"\"\"\n", " if isinstance(samples,tf.Tensor):\n", " samples = samples.numpy()\n", "\n", " char_probs = samples\n", " argmax = np.argmax(char_probs, 2)\n", " seqs = []\n", " for line in argmax:\n", " s = \"\".join(rev_charmap[d] for d in line)\n", " s = s.replace('*','')\n", " seqs.append(s)\n", "\n", " seqs = np.array(seqs)\n", " return seqs\n", "\n", "\n", "rna_vocab = {\"A\":0,\n", " \"C\":1,\n", " \"G\":2,\n", " \"U\":3,\n", " \"*\":4}\n", "\n", "rev_rna_vocab = {v:k for k,v in rna_vocab.items()}\n", "\n", "def select_best(scores, seqs, gc_control=False, GC=-1):\n", " t = np.max(scores,axis=1)\n", " # print(scores)\n", " maxinds = np.argmax(scores,axis=0)\n", " selected_scores = []\n", " selected_seqs = []\n", " for i in range(len(maxinds)):\n", " selected_seqs.append(seqs[maxinds[i]][i])\n", " selected_scores.append(scores[maxinds[i]][i])\n", "\n", "\n", " return selected_seqs, selected_scores" ] }, { "cell_type": "code", "execution_count": 4, "id": "1b365284", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "WARNING:tensorflow:Error in loading the saved optimizer state. As a result, your model is starting with a freshly initialized optimizer.\n", "WARNING:tensorflow:No training configuration found in the save file, so the model was *not* compiled. Compile it manually.\n" ] } ], "source": [ "\n", "\n", "\n", "\n", "DIM = 40\n", "SEQ_LEN = 128\n", "gpath = './../../models/checkpoint_3000.h5'\n", "exp_path = './../../models/humanMedian_trainepoch.11-0.426.h5'\n", "tpath = './../exp_optimization/script/checkpoint/RL_hard_share_MTL/3R/schedule_MTL-model_best_cv1.pth'\n", "\n", "CELL_LINE = ''\n", "# CELL_LINE = 'K562_'\n", "# CELL_LINE = 'GM12878_'\n", "\n", "# Set seeds\n", "# seed = 65\n", "# np.random.seed(seed)\n", "# tf.random.set_seed(seed)\n", "# torch.manual_seed(seed)\n", "# torch.cuda.manual_seed(seed) # If using CUDA\n", "# random.seed(seed)\n", "\n", "# # Ensure deterministic behavior in PyTorch\n", "# torch.backends.cudnn.deterministic = True\n", "# torch.backends.cudnn.benchmark = False\n", "\n", "model = load_model(exp_path)\n", "\n", "model = convert_model(model)\n", "\n", "gene_name = GENE\n", "\n", "retriever = GeneInfoRetriever()\n", " \n", "ref = ''\n", "\n", "output_json = f\"{gene_name}_info.json\"\n", "\n", "if not os.path.exists(os.path.join('./.cache/',output_json)):\n", "\n", " # Retrieve gene information\n", " gene_info = retriever.get_gene_info(gene_name, output_json=output_json)\n", "\n", " if \"error\" in gene_info:\n", " print(f\"Error: {gene_info['error']}\")\n", " else:\n", " ref = gene_info[\"promoter_sequence\"] \n", "else:\n", " with open(os.path.join('./.cache/',output_json), \"r\") as f:\n", " gene_info = json.load(f)\n", " ref = gene_info[\"promoter_sequence\"]\n", "\n", "original_gene_sequence = ref\n", "\n", "wgan = tf.keras.models.load_model(gpath)\n", "\n", "\"\"\"\n", "Data:\n", "\"\"\"\n", "\n", "noise = tf.Variable(tf.random.normal(shape=[BATCH_SIZE,DIM]))\n", "\n", "\n", "diffs = []\n", "init_exps = []\n", "\n", "opt_exps = []\n", "\n", "orig_vals = []\n", "\n", "\n", "noise = tf.Variable(tf.random.normal(shape=[BATCH_SIZE,DIM]))\n", "# noise = tf.random.normal(shape=[BATCH_SIZE,40])\n", "noise_small = tf.random.normal(shape=[BATCH_SIZE,DIM],stddev=1e-5)\n", "\n", "optimizer = tf.keras.optimizers.Adam(learning_rate=0.1)\n", "\n", "'''\n", "Original Gene Expression\n", "'''\n", "\n", "seqs_orig = one_hot([original_gene_sequence[:10500]])\n", "pred_orig = model(seqs_orig) \n", "pred_orig = tf.reshape(pred_orig,(-1)).numpy().astype('float')[0]\n", "\n", "'''\n", "Optimization takes place here.\n", "'''\n", "\n", "\n", "\n", "bind_scores_list = []\n", "bind_scores_means = []\n", "sequences_list = []\n", "\n", "\"\"\" LOW Start Mode \"\"\"\n", "\n", "best = 100\n", "\n", "LOW_START = False\n", "\n", "if LOW_START:\n", "\n", " for i in tqdm(range(1000)):\n", " tempnoise = tf.random.normal(shape=[BATCH_SIZE,DIM])\n", " sequences = wgan(tempnoise)\n", "\n", " seqs_gen = recover_seq(sequences, rev_rna_vocab)\n", "\n", " seqs = retriever.replace_utr_in_sequence(f\"./.cache/{gene_name}_info.json\", seqs_gen)\n", "\n", " seqs = one_hot(seqs)\n", " \n", " pred = model(seqs)\n", "\n", " score = np.mean(tf.reshape(pred,(-1)).numpy().astype('float'))\n", "\n", " if score < best:\n", " best = score\n", " selectednoise = tempnoise\n", " noise = tf.Variable(selectednoise)\n", "else:\n", " noise = tf.Variable(tf.random.normal(shape=[BATCH_SIZE,DIM]))\n", "\n", "\n", "#######################\n", "\n", "iters_ = []\n", "\n", "OPTIMIZE = True\n", "\n", "DNA_SEL = False\n", "\n", "sequences_init = wgan(noise)\n", "\n", "gen_seqs_init = sequences_init.numpy().astype('float')\n", "\n", "seqs_gen_init = recover_seq(gen_seqs_init, rev_rna_vocab)\n", "\n", "seqs_init = retriever.replace_utr_in_sequence(f\"./.cache/{gene_name}_info.json\", seqs_gen_init)\n", "\n", "seqs_init = one_hot(seqs_init)\n", "\n", "pred_init = model(seqs_init) \n", "\n", "init_t = tf.reshape(pred_init,(-1)).numpy().astype('float')\n", "\n", "STEPS = STEPS\n", "\n", "seqs_collection = []\n", "scores_collection = []\n", "\n", "GC_CONTROL = False\n", "\n", "if GC_LIMIT > 0.:\n", " GC_CONTROL = True" ] }, { "cell_type": "code", "execution_count": 5, "id": "9dcefb89", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "100%|██████████| 2/2 [00:06<00:00, 3.29s/it]\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Results for VEGFA saved to ./outputs/\n", "Natural 5' UTR Expression: 6.5809\n", "Average Initial Expression: 8.1897\n", "Max Initial Expression: 10.5389\n", "Max Best Expression: 10.5389\n", "Average Improvement: 2.89%\n", "Max Improvement: 24.97%\n", "Average Improvement (wrt to Natural 5'UTR): 28.32%\n", "Max Improvement (wrt to Natural 5'UTR): 60.14%\n" ] } ], "source": [ "\n", "\n", "if OPTIMIZE:\n", " \n", " iter_ = 0\n", " for opt_iter in tqdm(range(STEPS)):\n", " \n", " with tf.GradientTape() as gtape:\n", "\n", " gtape.watch(noise)\n", " \n", " sequences = wgan(noise)\n", "\n", " seqs_gen = recover_seq(sequences, rev_rna_vocab)\n", " seqs_collection.append(seqs_gen)\n", "\n", " seqs2 = retriever.replace_utr_in_sequence(f\"./.cache/{gene_name}_info.json\", seqs_gen)\n", " \n", " seqs = one_hot(seqs2)\n", " seqs = tf.convert_to_tensor(seqs,dtype=tf.float32)\n", "\n", "\n", " with tf.GradientTape() as ptape:\n", "\n", " ptape.watch(seqs)\n", "\n", " pred = model(seqs)\n", " t = tf.reshape(pred,(-1))\n", " scores_collection.append(t.numpy().astype('float'))\n", "\n", " pred = tf.math.scalar_mul(-1.0, pred)\n", "\n", " g1 = ptape.gradient(pred,seqs)\n", "\n", " g1 = tf.slice(g1,[0,7000,0],[-1,SEQ_LEN,-1])\n", "\n", "\n", " tmp_g = g1.numpy().astype('float')\n", " tmp_seqs = seqs_gen\n", "\n", " tmp_lst = np.zeros(shape=(BATCH_SIZE,SEQ_LEN,5))\n", " for i in range(len(tmp_seqs)):\n", " len_ = len(tmp_seqs[i])\n", " \n", " edited_g = tmp_g[i][:len_,:]\n", "\n", " edited_g = np.pad(edited_g,((0,SEQ_LEN-len_),(0,1)),'constant') \n", " \n", " tmp_lst[i] = edited_g\n", " \n", " g1 = tf.convert_to_tensor(tmp_lst,dtype=tf.float32)\n", "\n", " g2 = gtape.gradient(sequences,noise,output_gradients=g1)\n", "\n", " a1 = g2 + noise_small\n", " change = [(a1,noise)]\n", " \n", " optimizer.apply_gradients(change)\n", "\n", " iters_.append(iter_)\n", " iter_ += 1\n", "\n", " sequences_opt = wgan(noise)\n", "\n", " gen_seqs_opt = sequences_opt.numpy().astype('float')\n", "\n", " seqs_gen_opt = recover_seq(gen_seqs_opt, rev_rna_vocab)\n", "\n", " seqs_opt= retriever.replace_utr_in_sequence(f\"./.cache/{gene_name}_info.json\", seqs_gen_opt, target_length=10500, output_prefix=\"modified_sequence\")\n", "\n", " seqs_opt = one_hot(seqs_opt)\n", "\n", " pred_opt = model(seqs_opt)\n", "\n", " t = tf.reshape(pred_opt,(-1))\n", " opt_t = t.numpy().astype('float')\n", "\n", "\n", " if GC_CONTROL:\n", " best_seqs, best_scores = select_best(scores_collection, seqs_collection, True, GC_LIMIT)\n", " else:\n", " best_seqs, best_scores = select_best(scores_collection, seqs_collection)\n", "\n", "\n", " if GC_CONTROL:\n", "\n", " with open(f'./outputs/{CELL_LINE}gc_init_exps_'+gene_name+'.txt', 'w') as f:\n", " for item in init_t:\n", " f.write(f'{item}\\n')\n", "\n", " with open(f'./outputs/{CELL_LINE}gc_opt_exps_'+gene_name+'.txt', 'w') as f:\n", " for item in best_scores:\n", " f.write(f'{item}\\n')\n", "\n", " with open(f'./outputs/{CELL_LINE}gc_best_seqs_'+gene_name+'.txt', 'w') as f:\n", " for item in best_seqs:\n", " f.write(f'{item}\\n')\n", "\n", " with open(f'./outputs/{CELL_LINE}gc_init_seqs_'+gene_name+'.txt', 'w') as f:\n", " for item in seqs_gen_init:\n", " f.write(f'{item}\\n')\n", "\n", " else:\n", " with open(f'./outputs/{CELL_LINE}init_exps_{gene_name}.txt', 'w') as f:\n", " for item in init_t:\n", " f.write(f'{item}\\n')\n", "\n", " with open(f'./outputs/{CELL_LINE}opt_exps_{gene_name}.txt', 'w') as f:\n", " for item in best_scores:\n", " f.write(f'{item}\\n')\n", "\n", " with open(f'./outputs/{CELL_LINE}best_seqs_{gene_name}.txt', 'w') as f:\n", " for item in best_seqs:\n", " f.write(f'{item}\\n')\n", "\n", " with open(f'./outputs/{CELL_LINE}init_seqs_{gene_name}.txt', 'w') as f:\n", " for item in seqs_gen_init:\n", " f.write(f'{item}\\n')\n", "\n", "\n", " print(f\"Results for {gene_name} saved to ./outputs/\")\n", " print(f\"Natural 5' UTR Expression: {np.power(10,pred_orig):.4f}\")\n", " print(f\"Average Initial Expression: {np.power(10,np.average(init_t)):.4f}\")\n", " print(f\"Max Initial Expression: {np.power(10,np.max(init_t)):.4f}\")\n", " print(f\"Max Best Expression: {np.power(10,np.max(best_scores)):.4f}\")\n", " print(f\"Average Improvement: {np.average((np.power(10,best_scores) - np.power(10,init_t))/np.power(10,init_t))*100:.2f}%\")\n", " print(f\"Max Improvement: {np.max((np.power(10,best_scores) - np.power(10,init_t))/np.power(10,init_t))*100:.2f}%\")\n", " print(f\"Average Improvement (wrt to Natural 5'UTR): {np.average((np.power(10,best_scores) - math.pow(10,pred_orig))/math.pow(10,pred_orig))*100:.2f}%\")\n", " print(f\"Max Improvement (wrt to Natural 5'UTR): {np.max((np.power(10,best_scores) - math.pow(10,pred_orig))/math.pow(10,pred_orig))*100:.2f}%\")\n", "\n", "\n" ] } ], "metadata": { "kernelspec": { "display_name": "utrgan", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.8" } }, "nbformat": 4, "nbformat_minor": 5 }