Download model/src/exp_optimization/joint_opt.py from OneScience-Group/UTRGAN: direct link, hf CLI and curl.
- Browser
- Download file 32.4 kB
-
https://huggingface.co/OneScience-Group/UTRGAN/resolve/main/model/src/exp_optimization/joint_opt.py
- Command line
-
hf download hf://OneScience-Group/UTRGAN/model/src/exp_optimization/joint_opt.py
-
curl -L -o joint_opt.py https://huggingface.co/OneScience-Group/UTRGAN/resolve/main/model/src/exp_optimization/joint_opt.py
32.4 kB
| from re import A, L | |
| import numpy as np | |
| import pandas as pd | |
| import argparse | |
| from tqdm import tqdm | |
| import torch | |
| import tensorflow as tf | |
| import tensorflow.keras.backend as K | |
| from tensorflow.keras import Model | |
| from tensorflow.keras.models import load_model | |
| import sys | |
| import socket | |
| import datetime | |
| import random | |
| import os | |
| import matplotlib.pyplot as plt | |
| from Bio import SeqIO | |
| import pandas as pd | |
| import numpy as np | |
| import requests, sys | |
| import json | |
| from util import * | |
| from framepool import * | |
| from popen import Auto_popen | |
| import scipy.stats as stats | |
| abs_path = './../mrl_te_optimization/log/Backbone/RL_hard_share/3M/small_repective_filed_strides1113.ini' | |
| Configuration = Auto_popen(abs_path) | |
| import utils as util_motif | |
| tf.compat.v1.enable_eager_execution() | |
| parser = argparse.ArgumentParser() | |
| parser.add_argument('-bs', type=int, required=False ,default=64) | |
| parser.add_argument('-g', type=str, required=False ,default='IFNG') | |
| parser.add_argument('-lr', type=int, required=False ,default=1) | |
| parser.add_argument('-gpu', type=str, required=False ,default='-1') | |
| parser.add_argument('-s', type=int, required=False ,default=10) | |
| args = parser.parse_args() | |
| if args.gpu == '-1': | |
| device = 'cpu' | |
| else: | |
| os.environ['CUDA_VISIBLE_DEVICES'] = args.gpu | |
| device = 'cuda' | |
| BATCH_SIZE = args.bs | |
| DIM = 40 | |
| SEQ_LEN = 128 | |
| MAX_LEN = SEQ_LEN | |
| gpath = './../../models/checkpoint_3000.h5' | |
| tpath = './script/checkpoint/RL_hard_share_MTL/3R/schedule_MTL-model_best_cv1.pth' | |
| def reverse_complement(sequence): | |
| """Compute the reverse complement of a DNA sequence.""" | |
| complement = {'A': 'T', 'T': 'A', 'C': 'G', 'G': 'C', | |
| 'a': 't', 't': 'a', 'c': 'g', 'g': 'c', 'N': 'N', 'n': 'N'} | |
| return ''.join(complement.get(base, 'N') for base in reversed(sequence)) | |
| class GeneInfoRetriever: | |
| def __init__(self): | |
| self.base_url = "https://rest.ensembl.org" | |
| self.headers = {"Content-Type": "application/json"} | |
| self.sleep_time = 0.5 # Respect Ensembl API rate limits | |
| def _make_request(self, endpoint): | |
| """Make a request to the Ensembl REST API.""" | |
| url = self.base_url + endpoint | |
| try: | |
| response = requests.get(url, headers=self.headers) | |
| time.sleep(self.sleep_time) | |
| if response.status_code == 200: | |
| return response.json() | |
| else: | |
| print(f"Error: {response.status_code} - {response.text}") | |
| return None | |
| except Exception as e: | |
| print(f"Request error: {e}") | |
| return None | |
| def get_gene_id(self, gene_symbol, species="homo_sapiens"): | |
| """Retrieve the Ensembl gene ID for a gene symbol.""" | |
| endpoint = f"/lookup/symbol/{species}/{gene_symbol}" | |
| response = self._make_request(endpoint) | |
| return response.get("id") if response else None | |
| def get_gene_coordinates(self, gene_id): | |
| """Retrieve genomic coordinates for a gene ID.""" | |
| endpoint = f"/lookup/id/{gene_id}?expand=1" | |
| response = self._make_request(endpoint) | |
| if response: | |
| return { | |
| "chromosome": response.get("seq_region_name"), | |
| "start": response.get("start"), | |
| "end": response.get("end"), | |
| "strand": response.get("strand") | |
| } | |
| return None | |
| def get_tss_and_utr(self, gene_id): | |
| """Retrieve TSS and 5' UTR coordinates for the canonical transcript.""" | |
| endpoint = f"/lookup/id/{gene_id}?expand=1&utr=1" | |
| response = self._make_request(endpoint) | |
| if not response or "Transcript" not in response: | |
| return None | |
| # Find canonical transcript | |
| canonical_transcript = None | |
| for transcript in response["Transcript"]: | |
| if transcript.get("is_canonical", 0) == 1: | |
| canonical_transcript = transcript | |
| break | |
| if not canonical_transcript: | |
| for transcript in response["Transcript"]: | |
| if transcript.get("biotype") == "protein_coding": | |
| canonical_transcript = transcript | |
| break | |
| if not canonical_transcript: | |
| canonical_transcript = response["Transcript"][0] if response["Transcript"] else None | |
| if not canonical_transcript: | |
| return None | |
| # Determine TSS and 5' UTR | |
| strand = canonical_transcript.get("strand") | |
| tss = canonical_transcript["start"] if strand == 1 else canonical_transcript["end"] | |
| five_prime_utr = None | |
| if "UTR" in canonical_transcript: | |
| for utr in canonical_transcript["UTR"]: | |
| if utr.get("object_type") == "five_prime_UTR": | |
| five_prime_utr = { | |
| "start": utr.get("start"), | |
| "end": utr.get("end") | |
| } | |
| break | |
| # Verify TSS matches 5' UTR start | |
| if five_prime_utr: | |
| expected_tss = five_prime_utr["start"] if strand == 1 else five_prime_utr["end"] | |
| if expected_tss != tss: | |
| print(f"Warning: Adjusting TSS from {tss} to match 5' UTR {'start' if strand == 1 else 'end'} ({expected_tss})") | |
| tss = expected_tss | |
| return { | |
| "tss": tss, | |
| "strand": strand, | |
| "chromosome": canonical_transcript.get("seq_region_name"), | |
| "five_prime_utr": five_prime_utr, | |
| "transcript_id": canonical_transcript.get("id") | |
| } | |
| def get_promoter_sequence(self, gene_id, upstream=7000, downstream=4000): | |
| """Retrieve sequence around TSS (8kb upstream, 4kb downstream).""" | |
| tss_info = self.get_tss_and_utr(gene_id) | |
| if not tss_info: | |
| return None, None | |
| chromosome = tss_info["chromosome"] | |
| strand = tss_info["strand"] | |
| tss_position = tss_info["tss"] | |
| # Calculate region based on strand | |
| if strand == 1: | |
| seq_start = tss_position - upstream | |
| seq_end = tss_position + downstream - 1 | |
| else: | |
| seq_start = tss_position - downstream | |
| seq_end = tss_position + upstream - 1 | |
| seq_start = max(1, seq_start) | |
| # Store sequence coordinates | |
| sequence_coords = { | |
| "chromosome": chromosome, | |
| "start": seq_start, | |
| "end": seq_end, | |
| "strand": 1 if strand == 1 else -1 | |
| } | |
| # Validate 5' UTR inclusion | |
| if tss_info["five_prime_utr"]: | |
| utr_start = tss_info["five_prime_utr"]["start"] | |
| utr_end = tss_info["five_prime_utr"]["end"] | |
| if not (seq_start <= utr_start <= seq_end and seq_start <= utr_end <= seq_end): | |
| print(f"Warning: 5' UTR ({utr_start}-{utr_end}) not fully within sequence ({seq_start}-{seq_end})") | |
| # Get sequence | |
| strand_str = "1" if strand == 1 else "-1" | |
| endpoint = f"/sequence/region/human/{chromosome}:{seq_start}..{seq_end}:{strand_str}" | |
| response = self._make_request(endpoint) | |
| return response.get("seq") if response else None, sequence_coords | |
| def get_gene_info(self, gene_symbol, species="homo_sapiens", output_json="gene_info.json"): | |
| if not os.path.exists(os.path.join('./.cache/',f"{gene_symbol}_info.json")): | |
| """Retrieve and save promoter sequence, TSS, 5' UTR, and coordinates.""" | |
| # Get gene ID | |
| gene_id = self.get_gene_id(gene_symbol, species) | |
| if not gene_id: | |
| return {"error": f"Gene {gene_symbol} not found"} | |
| # Get TSS and 5' UTR | |
| tss_info = self.get_tss_and_utr(gene_id) | |
| if not tss_info: | |
| return {"error": "Could not retrieve TSS or transcript information"} | |
| # Get promoter sequence and coordinates | |
| promoter_sequence, sequence_coords = self.get_promoter_sequence(gene_id) | |
| if not promoter_sequence: | |
| return {"error": "Could not retrieve promoter sequence"} | |
| # Compile gene information | |
| gene_info = { | |
| "gene_symbol": gene_symbol, | |
| "gene_id": gene_id, | |
| "promoter_sequence": promoter_sequence, | |
| "sequence_length": len(promoter_sequence), | |
| "sequence_coordinates": sequence_coords, | |
| "tss": { | |
| "chromosome": tss_info["chromosome"], | |
| "position": tss_info["tss"], | |
| "strand": "+" if tss_info["strand"] == 1 else "-" | |
| }, | |
| "five_prime_utr": tss_info["five_prime_utr"], | |
| "transcript_id": tss_info["transcript_id"] | |
| } | |
| # Save to JSON | |
| try: | |
| os.makedirs(os.path.dirname('./.cache/'), exist_ok=True) | |
| with open(os.path.join('./.cache/',f"{gene_symbol}_info.json"), "w") as f: | |
| json.dump(gene_info, f, indent=2) | |
| print(f"Saved gene information to {output_json}") | |
| except Exception as e: | |
| print(f"Error saving JSON: {e}") | |
| else: | |
| with open(os.path.join('./.cache/',f"{gene_symbol}_info.json"), "r") as f: | |
| gene_info = json.load(f) | |
| return gene_info | |
| def reverse_complement(self, sequence): | |
| """Compute the reverse complement of a DNA sequence.""" | |
| complement = {'A': 'T', 'T': 'A', 'C': 'G', 'G': 'C', | |
| 'a': 't', 't': 'a', 'c': 'g', 'g': 'c', 'N': 'N', 'n': 'N'} | |
| return ''.join(complement.get(base, 'N') for base in reversed(sequence)) | |
| def replace_utr_in_sequence(self, gene_info_file, generated_utrs, target_length=10500, output_prefix="modified_sequence", write_json=False, verbose=False): | |
| """ | |
| Replace original 5' UTR with generated UTRs, ensuring 10,500nt output. | |
| Parameters: | |
| gene_info_file (str): Path to JSON file with gene information | |
| generated_utrs (list): List of generated 5' UTR sequences (64-128nt) | |
| target_length (int): Desired output sequence length (default: 10500) | |
| output_prefix (str): Prefix for output JSON files | |
| Returns: | |
| list: List of modified sequences with metadata | |
| """ | |
| try: | |
| # Read gene information | |
| with open(gene_info_file, "r") as f: | |
| gene_info = json.load(f) | |
| original_sequence = gene_info["promoter_sequence"] | |
| strand = gene_info["tss"]["strand"] | |
| tss_position = gene_info["tss"]["position"] | |
| sequence_coords = gene_info["sequence_coordinates"] | |
| seq_start = sequence_coords["start"] | |
| seq_end = sequence_coords["end"] | |
| five_prime_utr = gene_info["five_prime_utr"] | |
| gene_symbol = gene_info["gene_symbol"] | |
| transcript_id = gene_info["transcript_id"] | |
| if not five_prime_utr: | |
| print(f"Error: No 5' UTR information available for {gene_symbol}") | |
| return [] | |
| # Calculate original 5' UTR position in sequence | |
| if strand == "+": | |
| utr_start_genomic = five_prime_utr["start"] | |
| utr_end_genomic = five_prime_utr["end"] | |
| utr_start_seq = utr_start_genomic - seq_start | |
| utr_end_seq = utr_end_genomic - seq_start | |
| else: | |
| utr_start_genomic = five_prime_utr["end"] # TSS | |
| utr_end_genomic = five_prime_utr["start"] | |
| utr_start_seq = seq_end - utr_start_genomic | |
| utr_end_seq = seq_end - utr_end_genomic | |
| # Validate UTR positions | |
| seq_length = len(original_sequence) | |
| if not (0 <= utr_start_seq <= seq_length and 0 <= utr_end_seq <= seq_length): | |
| print(f"Error: 5' UTR coordinates (seq indices {utr_start_seq}-{utr_end_seq}) out of sequence bounds (0-{seq_length}) for {gene_symbol}") | |
| return [] | |
| original_utr_length = abs(utr_end_genomic - utr_start_genomic) + 1 | |
| if verbose: | |
| print(f"Original 5' UTR length for {gene_symbol}: {original_utr_length} nt") | |
| modified_sequences = [] | |
| for i, new_utr in enumerate(generated_utrs): | |
| new_utr_length = len(new_utr) | |
| # Construct new sequence | |
| if strand == "+": | |
| new_sequence = ( | |
| original_sequence[:utr_start_seq] + | |
| new_utr + | |
| original_sequence[utr_end_seq + 1:] | |
| ) | |
| new_utr_start_genomic = utr_start_genomic | |
| new_utr_end_genomic = utr_start_genomic + new_utr_length - 1 | |
| if len(new_sequence) > target_length: | |
| new_sequence = new_sequence[:target_length] | |
| sequence_coords["end"] = seq_start + target_length - 1 | |
| elif len(new_sequence) < target_length: | |
| if verbose: | |
| print(f"Error: Sequence too short ({len(new_sequence)} nt) after UTR replacement for {gene_symbol}") | |
| continue | |
| else: | |
| new_utr_rc = reverse_complement(new_utr) | |
| new_sequence = ( | |
| original_sequence[:min(utr_start_seq, utr_end_seq)] + | |
| new_utr_rc + | |
| original_sequence[max(utr_start_seq, utr_end_seq) + 1:] | |
| ) | |
| new_utr_start_genomic = utr_start_genomic | |
| new_utr_end_genomic = utr_start_genomic - new_utr_length + 1 | |
| if len(new_sequence) > target_length: | |
| trim_amount = len(new_sequence) - target_length | |
| new_sequence = new_sequence[trim_amount:] | |
| sequence_coords["start"] = seq_start + trim_amount | |
| elif len(new_sequence) < target_length: | |
| if verbose: | |
| print(f"Error: Sequence too short ({len(new_sequence)} nt) after UTR replacement for {gene_symbol}") | |
| continue | |
| # Store modified sequence and metadata | |
| modified_info = { | |
| "gene_symbol": gene_symbol, | |
| "transcript_id": transcript_id, | |
| "modified_sequence": new_sequence, | |
| "sequence_length": len(new_sequence), | |
| "sequence_coordinates": sequence_coords.copy(), | |
| "tss": gene_info["tss"], | |
| "five_prime_utr": { | |
| "start": new_utr_start_genomic, | |
| "end": new_utr_end_genomic, | |
| "sequence": new_utr if strand == "+" else new_utr_rc | |
| }, | |
| "original_utr_length": original_utr_length, | |
| "new_utr_length": new_utr_length, | |
| "utr_index": i + 1 | |
| } | |
| # Save to JSON | |
| if write_json: | |
| output_file = f"{output_prefix}_{gene_symbol}_utr_{i+1}.json" | |
| try: | |
| os.makedirs(os.path.dirname(output_file), exist_ok=True) | |
| with open(output_file, "w") as f: | |
| json.dump(modified_info, f, indent=2) | |
| print(f"Saved modified sequence {i+1} for {gene_symbol} to {output_file}") | |
| except Exception as e: | |
| print(f"Error saving modified sequence {i+1} for {gene_symbol}: {e}") | |
| modified_sequences.append(modified_info["modified_sequence"]) | |
| return modified_sequences | |
| except Exception as e: | |
| # print(f"Error processing UTR replacement for {gene_info.get('gene_symbol', 'unknown')}: {e}") | |
| print(f"Error processing UTR replacement for gene: {e}") | |
| return [] | |
| def replace_utr_in_multiple_sequences(self, gene_symbols, generated_utrs, target_length=10500, cache_dir="./.cache", output_prefix="modified_sequence", verbose=False): | |
| """ | |
| Replace 5' UTRs for multiple genes with generated UTRs. | |
| Parameters: | |
| gene_symbols (list): List of gene names | |
| generated_utrs (list): List of generated 5' UTR sequences (64-128nt) | |
| target_length (int): Desired output sequence length (default: 10500) | |
| cache_dir (str): Directory containing cached gene info JSON files | |
| output_prefix (str): Prefix for output JSON files | |
| Returns: | |
| list: List of n_utrs * n_genes modified sequences with metadata | |
| """ | |
| all_modified_sequences = [] | |
| n_utrs = len(generated_utrs) | |
| n_genes = len(gene_symbols) | |
| for gene_symbol in gene_symbols: | |
| json_file = os.path.join(cache_dir, f"{gene_symbol}_info.json") | |
| if not os.path.exists(json_file): | |
| print(f"Error: Gene info file {json_file} not found") | |
| continue | |
| if verbose: | |
| print(f"\nProcessing gene: {gene_symbol}") | |
| modified_sequences = self.replace_utr_in_sequence( | |
| gene_info_file=json_file, | |
| generated_utrs=generated_utrs, | |
| target_length=target_length, | |
| output_prefix=os.path.join(cache_dir, output_prefix) | |
| ) | |
| if modified_sequences: | |
| all_modified_sequences.extend(modified_sequences) | |
| else: | |
| if verbose: | |
| print(f"No modified sequences generated for {gene_symbol}") | |
| expected_count = n_utrs * n_genes | |
| actual_count = len(all_modified_sequences) | |
| if verbose: | |
| print(f"\nGenerated {actual_count} modified sequences (expected: {expected_count})") | |
| return all_modified_sequences | |
| def fetch_seq(start, end, chr, strand): | |
| server = "https://rest.ensembl.org" | |
| ext = "/sequence/region/human/" + str(chr) + ":" + str(start) + ".." + str(end) + ":" + str(strand) + "?" | |
| r = requests.get(server+ext, headers={ "Content-Type" : "text/plain"}) | |
| if not r.ok: | |
| r.raise_for_status() | |
| sys.exit() | |
| return r.text | |
| def convert_model(model_:Model): | |
| print(model_.summary()) | |
| input_ = tf.keras.layers.Input(shape=( 10500, 4)) | |
| input = input_ | |
| for i in range(len(model_.layers)-1): | |
| # print(type(model_.layers[i+1])) | |
| if isinstance(model_.layers[i+1],tf.keras.layers.Concatenate): | |
| paddings = tf.constant([[0,0],[0,6]]) | |
| output = tf.pad(input, paddings, 'CONSTANT') | |
| input = output | |
| else: | |
| if not isinstance(model_.layers[i+1],tf.keras.layers.InputLayer): | |
| output = model_.layers[i+1](input) | |
| input = output | |
| if isinstance(model_.layers[i+1],tf.keras.layers.Conv1D): | |
| pass | |
| model = tf.keras.Model(inputs=input_, outputs=output) | |
| model.compile(loss="mse", optimizer="adam") | |
| return model | |
| def one_hot(seq): | |
| convert = False | |
| if isinstance(seq, tf.Tensor): | |
| seq = seq.numpy().astype(str) | |
| convert = True | |
| num_seqs = len(seq) | |
| seq_len = len(seq[0]) | |
| seqindex = {'A':0, 'C':1, 'G':2, 'T':3, 'a':0, 'c':1, 'g':2, 't':3} | |
| seq_vec = np.zeros((num_seqs,seq_len,4), dtype='bool') | |
| for i in range(num_seqs): | |
| thisseq = seq[i] | |
| for j in range(seq_len): | |
| try: | |
| seq_vec[i,j,seqindex[thisseq[j]]] = 1 | |
| except: | |
| pass | |
| if convert: | |
| seq_vec = tf.convert_to_tensor(seq_vec,dtype=tf.float32) | |
| return seq_vec | |
| def gen_random_dna(len=10500,size=SEQ_LEN): | |
| list_ = ['A','C','G','T'] | |
| dnas = [] | |
| for i in range(size): | |
| list_ = ['A','C','G','T'] | |
| mydna = 'AGT' | |
| for i in range(len-3): | |
| char = list_[random.randint(0,3)] | |
| mydna = mydna + char | |
| dnas.append(mydna) | |
| return dnas | |
| def select_dna_single(fname='small_seqs.npy',batch_size=64): | |
| refs = np.load(fname) | |
| indice = random.sample(range(0,refs.shape[0]),1) | |
| refs = refs | |
| return indice[0], refs | |
| def recover_seq(samples, rev_charmap): | |
| """Convert samples to strings and save to log directory.""" | |
| if isinstance(samples,tf.Tensor): | |
| samples = samples.numpy() | |
| char_probs = samples | |
| argmax = np.argmax(char_probs, 2) | |
| seqs = [] | |
| for line in argmax: | |
| s = "".join(rev_charmap[d] for d in line) | |
| s = s.replace('*','') | |
| seqs.append(s) | |
| seqs = np.array(seqs) | |
| return seqs | |
| rna_vocab = {"A":0, | |
| "C":1, | |
| "G":2, | |
| "U":3, | |
| "*":4} | |
| rev_rna_vocab = {v:k for k,v in rna_vocab.items()} | |
| def select_best(scores, seqs, gc_control=False, GC=-1): | |
| selected_scores = [] | |
| selected_seqs = [] | |
| for i in range(len(scores[0])): | |
| best = scores[0][i] | |
| best_seq = seqs[0][i] | |
| for j in range(len(scores)): | |
| if scores[j][i] > best: | |
| if gc_control: | |
| if get_gc_content(seqs[j][i]) < GC: | |
| best = scores[j][i] | |
| best_seq = seqs[j][i] | |
| else: | |
| best = scores[j][i] | |
| best_seq = seqs[j][i] | |
| selected_scores.append(best) | |
| selected_seqs.append(best_seq) | |
| return selected_seqs, selected_scores | |
| def log(samples_dir=False): | |
| stamp = datetime.date.strftime(datetime.datetime.now(), "%Y.%m.%d-%Hh%Mm%Ss") + "_{}".format(socket.gethostname()) | |
| full_logdir = os.path.join("./logs/", "gan_test_opt", stamp) | |
| os.makedirs(full_logdir, exist_ok=True) | |
| if samples_dir: os.makedirs(os.path.join(full_logdir, "samples"), exist_ok=True) | |
| log_dir = "{}:{}".format(socket.gethostname(), full_logdir) | |
| return full_logdir, 0 | |
| if __name__ == "__main__": | |
| model = tf.keras.models.load_model('./../../models/humanMedian_trainepoch.11-0.426.h5') | |
| model = convert_model(model) | |
| gene_name = args.g | |
| ref = '' | |
| output_json = f"{gene_name}_info.json" | |
| retriever = GeneInfoRetriever() | |
| if not os.path.exists(os.path.join('./.cache/',output_json)): | |
| # Retrieve gene information | |
| gene_info = retriever.get_gene_info(gene_name, output_json=output_json) | |
| if "error" in gene_info: | |
| print(f"Error: {gene_info['error']}") | |
| else: | |
| ref = gene_info["promoter_sequence"] | |
| else: | |
| with open(os.path.join('./.cache/',output_json), "r") as f: | |
| gene_info = json.load(f) | |
| ref = gene_info["promoter_sequence"] | |
| original_gene_sequence = ref | |
| wgan = tf.keras.models.load_model(gpath) | |
| """ | |
| Data: | |
| """ | |
| noise = tf.Variable(tf.random.normal(shape=[BATCH_SIZE,DIM])) | |
| tf.random.set_seed(25) | |
| np.random.seed(25) | |
| seqs_orig = one_hot([original_gene_sequence[:10500]]) | |
| pred_orig = model(seqs_orig) | |
| ################ TE Optimization ###################### | |
| te_model = torch.load(tpath,map_location=torch.device(device))['state_dict'] | |
| te_model.train().to(device) | |
| MODEL = "TE" | |
| opt_model = te_model | |
| noise = tf.Variable(tf.random.normal(shape=[BATCH_SIZE,DIM])) | |
| sequences_init = wgan(noise) | |
| gen_seqs_init = sequences_init.numpy().astype('float') | |
| seqs_gen_init = recover_seq(gen_seqs_init, rev_rna_vocab) | |
| seqs_init = retriever.replace_utr_in_sequence(f"./.cache/{gene_name}_info.json", seqs_gen_init) | |
| seqs_init = one_hot(seqs_init) | |
| pred_init = model(seqs_init) | |
| t = tf.reshape(pred_init,(-1)) | |
| init_t = t.numpy().astype('float') | |
| one_hots = one_hot_all_motif(np.array(seqs_gen_init)) | |
| seqs = torch.tensor(one_hots,dtype=torch.double) | |
| seqs = torch.transpose(seqs, 1, 2) | |
| seqs = seqs.float().to(device) | |
| pred_init = opt_model.forward(seqs) | |
| pred_init = torch.flatten(pred_init) | |
| preds_init = pred_init.cpu().detach().numpy() | |
| pred_init = np.average(preds_init) | |
| max_init = np.max(pred_init) | |
| min_init = np.min(pred_init) | |
| OPTIMIZE = True | |
| means = [] | |
| maxes = [] | |
| noise_small = tf.random.normal(shape=[BATCH_SIZE,DIM],stddev=1e-4) | |
| optimizer = tf.keras.optimizers.Adam(learning_rate=1e-1) | |
| STEPS = args.s | |
| if OPTIMIZE: | |
| iter_ = 0 | |
| for opt_iter in tqdm(range(int(STEPS))): | |
| with tf.GradientTape() as gtape: | |
| gtape.watch(noise) | |
| sequences = wgan(noise) | |
| seqs_gen = recover_seq(sequences, rev_rna_vocab) | |
| seqs_str = seqs_gen | |
| seqs = torch.tensor(np.array(one_hot_all_motif(seqs_gen),dtype=np.float32)) | |
| seqs = torch.transpose(seqs, 1, 2) | |
| seqs = seqs.float() | |
| seqs = torch.tensor(seqs.to(device), requires_grad=True) | |
| pred = opt_model.forward(seqs) | |
| pred = torch.flatten(pred) | |
| score = torch.mean(pred) | |
| t = torch.flatten(pred) | |
| mx = t.cpu().detach().numpy() | |
| mx = np.max(mx) | |
| sum_ = torch.mean(t).cpu().detach().numpy() | |
| maxes.append(mx) | |
| means.append(sum_/BATCH_SIZE) | |
| pred.backward(torch.ones_like(pred)) | |
| g1 = seqs.grad | |
| # print(g1.grad) | |
| g1 = g1.cpu().detach().numpy() | |
| g1 = tf.convert_to_tensor(g1) | |
| # print(tf.shape(g1)) | |
| g1 = tf.transpose(g1, perm=[0,2,1]) | |
| g1 = tf.pad(g1,tf.constant([[0, 0], [0, 0], [0, 1]]),"CONSTANT") | |
| g1 = tf.math.scalar_mul(-1.0,g1) | |
| g2 = gtape.gradient(sequences,noise,output_gradients=g1) | |
| a1 = g2 + noise_small | |
| change = [(a1,noise)] | |
| optimizer.apply_gradients(change) | |
| # iters_.append(iter_) | |
| iter_ += 1 | |
| sequences_opt = wgan(noise) | |
| gen_seqs_opt = sequences_opt.numpy().astype('float') | |
| seqs_gen_opt = recover_seq(gen_seqs_opt, rev_rna_vocab) | |
| one_hots = np.array(one_hot_all_motif(seqs_gen_opt)) | |
| # print(np.shape(one_hots)) | |
| seqs = torch.tensor(one_hots,dtype=torch.double) | |
| seqs = torch.transpose(seqs, 1, 2) | |
| seqs = seqs.float().to(device) | |
| preds_opt = opt_model.forward(seqs) | |
| preds_opt = preds_opt.cpu().data.numpy() | |
| ########################################################### | |
| diffs = [] | |
| init_exps = [] | |
| opt_exps = [] | |
| orig_vals = [] | |
| noise_small = tf.random.normal(shape=[BATCH_SIZE,DIM],stddev=1e-5) | |
| optimizer = tf.keras.optimizers.Adam(learning_rate=5e-2) | |
| ''' | |
| Original Gene Expression | |
| ''' | |
| ''' | |
| Optimization takes place here. | |
| ''' | |
| bind_scores_list = [] | |
| bind_scores_means = [] | |
| sequences_list = [] | |
| iters_ = [] | |
| OPTIMIZE = True | |
| DNA_SEL = False | |
| gan_noise = noise.numpy().astype('float') | |
| noise = tf.Variable(tf.convert_to_tensor(gan_noise,dtype=tf.float32)) | |
| sequences_step = wgan(noise) | |
| gen_seqs_step = sequences_step.numpy().astype('float') | |
| seqs_gen_step = recover_seq(gen_seqs_step, rev_rna_vocab) | |
| seqs_step = retriever.replace_utr_in_sequence(f"./.cache/{gene_name}_info.json", seqs_gen_step) | |
| seqs_step = one_hot(seqs_step) | |
| pred_step = model(seqs_step) | |
| intermediate_pred = tf.reshape(pred_step,(-1)) | |
| intermediate_pred = intermediate_pred.numpy().astype('float') | |
| seqs_te = torch.transpose(torch.tensor(np.array(one_hot_all_motif(seqs_gen_init),dtype=np.float32)),2,1).float().to(device) | |
| te_preds_init = te_model.forward(seqs_te).cpu().data.numpy() | |
| means = [] | |
| maxes = [] | |
| STEPS = args.s | |
| seqs_collection = [] | |
| scores_collection = [] | |
| if OPTIMIZE: | |
| iter_ = 0 | |
| for opt_iter in tqdm(range(STEPS)): | |
| with tf.GradientTape() as gtape: | |
| gtape.watch(noise) | |
| sequences = wgan(noise) | |
| seqs_collection.append(seqs_gen) | |
| seqs_gen = recover_seq(sequences, rev_rna_vocab) | |
| seqs2 = retriever.replace_utr_in_sequence(f"./.cache/{gene_name}_info.json", seqs_gen) | |
| seqs = one_hot(seqs2) | |
| seqs = tf.convert_to_tensor(seqs,dtype=tf.float32) | |
| with tf.GradientTape() as ptape: | |
| ptape.watch(seqs) | |
| pred = model(seqs) | |
| t = tf.reshape(pred,(-1)) | |
| scores_collection.append(t.numpy().astype('float')) | |
| mx = np.amax(t.numpy().astype('float'),axis=0) | |
| mx = np.max(mx) | |
| sum_ = tf.reduce_sum(t) | |
| maxes.append(mx) | |
| means.append(sum_/BATCH_SIZE) | |
| pred = tf.math.scalar_mul(-1.0, pred) | |
| g1 = ptape.gradient(pred,seqs) | |
| g1 = tf.slice(g1,[0,7000,0],[-1,SEQ_LEN,-1]) | |
| tmp_g = g1.numpy().astype('float') | |
| tmp_seqs = seqs_gen | |
| tmp_lst = np.zeros(shape=(BATCH_SIZE,SEQ_LEN,5)) | |
| for i in range(len(tmp_seqs)): | |
| len_ = len(tmp_seqs[i]) | |
| edited_g = tmp_g[i][:len_,:] | |
| edited_g = np.pad(edited_g,((0,SEQ_LEN-len_),(0,1)),'constant') | |
| tmp_lst[i] = edited_g | |
| g1 = tf.convert_to_tensor(tmp_lst,dtype=tf.float32) | |
| g2 = gtape.gradient(sequences,noise,output_gradients=g1) | |
| a1 = g2 + noise_small | |
| change = [(a1,noise)] | |
| optimizer.apply_gradients(change) | |
| iters_.append(iter_) | |
| iter_ += 1 | |
| sequences_opt = wgan(noise) | |
| gen_seqs_opt = sequences_opt.numpy().astype('float') | |
| seqs_gen_opt = recover_seq(gen_seqs_opt, rev_rna_vocab) | |
| seqs_opt= retriever.replace_utr_in_sequence(f"./.cache/{gene_name}_info.json", seqs_gen_opt) | |
| seqs_opt = one_hot(seqs_opt) | |
| pred_opt = model(seqs_opt) | |
| t = tf.reshape(pred_opt,(-1)) | |
| opt_t = t.numpy().astype('float') | |
| seqs_te = torch.transpose(torch.tensor(np.array(one_hot_all_motif(seqs_gen_opt),dtype=np.float32)),2,1).float().to(device) | |
| te_preds_opt = te_model.forward(seqs_te).cpu().data.numpy() | |
| best_seqs, best_scores = select_best(scores_collection, seqs_collection) | |
| os.makedirs("./outputs_joint", exist_ok=True) | |
| with open('./outputs_joint/init_exps_'+gene_name+'.txt', 'w') as f: | |
| for item in init_t: | |
| f.write(f'{item}\n') | |
| with open('./outputs_joint/opt_exps_'+gene_name+'.txt', 'w') as f: | |
| for item in opt_t: | |
| f.write(f'{item}\n') | |
| with open('./outputs_joint/best_seqs_'+gene_name+'.txt', 'w') as f: | |
| for item in seqs_gen_opt: | |
| f.write(f'{item}\n') | |
| with open('./outputs_joint/init_seqs_'+gene_name+'.txt', 'w') as f: | |
| for item in seqs_gen_init: | |
| f.write(f'{item}\n') | |
| print("TE Optimization Step:") | |
| print(f"Avg. Initial TE:{np.mean(preds_init)}") | |
| print(f"Max Initial TE:{np.amax(preds_init)}") | |
| print(f"Avg. Opt TE:{np.mean(preds_opt)}") | |
| print(f"Max Opt TE:{np.amax(preds_opt)}") | |
| print(f"Avg. Exp. Before First Step: {np.mean(init_t)}") | |
| print("Exp. Optimizization Step:") | |
| print(f'Avg. Exp. After First Step: {np.mean(intermediate_pred)}') | |
| print(f'Avg. Best Exp. After Second Step: {np.mean(best_scores)}') | |
| print("TE:") | |
| print(f'TE After First Step: {np.average(preds_opt)}') | |
| print(f'TE After Second Step: {np.average(te_preds_opt)}') | |