{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "Failed to detect the name of this notebook, you can set it manually with the WANDB_NOTEBOOK_NAME environment variable to enable code saving.\n", "\u001b[34m\u001b[1mwandb\u001b[0m: Currently logged in as: \u001b[33msarosavo\u001b[0m. Use \u001b[1m`wandb login --relogin`\u001b[0m to force relogin\n" ] }, { "data": { "text/plain": [ "True" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%load_ext autoreload\n", "%autoreload 2\n", "%matplotlib inline\n", "\n", "import torch\n", "import numpy as np\n", "import pandas as pd\n", "import scipy as sp\n", "import sys \n", "sys.path.append(\"../../\")\n", "sys.path.append(\"../../src/\")\n", "sys.path.append(\"../../src/model\")\n", "\n", "from src.model import ddsm as ddsm\n", "from src.model import ddsm_model as modeld\n", "from src.model.lightning_model_diffusion import LightningDiffusion as lightning_dif\n", "import src.utils.sequence as utils\n", "\n", "import scipy as spz\n", "from matplotlib import pyplot as plt\n", "\n", "import wandb\n", "wandb.login(host=\"https://api.wandb.ai\") " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Preparation " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If you wanna download a good model already, download it from W&B" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/html": [ "Tracking run with wandb version 0.17.4" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "Run data is saved locally in /raid/home/zhaoy183/projects/RLfinetuning_Diffusion_Bioseq/tutorials/UTR/wandb/run-20240718_155302-74ctp3wp" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "Syncing run wobbly-firebrand-5 to Weights & Biases (docs)
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ " View project at https://wandb.ai/sarosavo/RLfinetuning_Diffusion_Bioseq-tutorials_UTR" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ " View run at https://wandb.ai/sarosavo/RLfinetuning_Diffusion_Bioseq-tutorials_UTR/runs/74ctp3wp" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[34m\u001b[1mwandb\u001b[0m: Downloading large artifact UTR-dataset:v0, 3683.51MB. 4 files... \n", "\u001b[34m\u001b[1mwandb\u001b[0m: 4 of 4 files downloaded. \n", "Done. 0:0:7.1\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "08eda91bd97b422b9fcfc8524d9f89e7", "version_major": 2, "version_minor": 0 }, "text/plain": [ "VBox(children=(Label(value='0.280 MB of 0.280 MB uploaded\\r'), FloatProgress(value=1.0, max=1.0)))" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ " View run wobbly-firebrand-5 at: https://wandb.ai/sarosavo/RLfinetuning_Diffusion_Bioseq-tutorials_UTR/runs/74ctp3wp
View project at: https://wandb.ai/sarosavo/RLfinetuning_Diffusion_Bioseq-tutorials_UTR
Synced 7 W&B file(s), 0 media file(s), 0 artifact file(s) and 1 other file(s)" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "Find logs at: ./wandb/run-20240718_155302-74ctp3wp/logs" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "The new W&B backend becomes opt-out in version 0.18.0; try it out with `wandb.require(\"core\")`! See https://wandb.me/wandb-core for more information." ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "062f74ade1ba486bb9b5eda1d2eafebe", "version_major": 2, "version_minor": 0 }, "text/plain": [ "VBox(children=(Label(value='Waiting for wandb.init()...\\r'), FloatProgress(value=0.011112645289136304, max=1.0…" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "Tracking run with wandb version 0.17.4" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "Run data is saved locally in /raid/home/zhaoy183/projects/RLfinetuning_Diffusion_Bioseq/tutorials/UTR/wandb/run-20240718_155320-tjd8mzbr" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "Syncing run light-glitter-6 to Weights & Biases (docs)
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ " View project at https://wandb.ai/sarosavo/RLfinetuning_Diffusion_Bioseq-tutorials_UTR" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ " View run at https://wandb.ai/sarosavo/RLfinetuning_Diffusion_Bioseq-tutorials_UTR/runs/tjd8mzbr" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[34m\u001b[1mwandb\u001b[0m: Downloading large artifact UTR-Model:v0, 1499.65MB. 3 files... \n", "\u001b[34m\u001b[1mwandb\u001b[0m: 3 of 3 files downloaded. \n", "Done. 0:0:3.2\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "c39a5b0e58264d778558696f656c54ac", "version_major": 2, "version_minor": 0 }, "text/plain": [ "VBox(children=(Label(value='0.280 MB of 0.280 MB uploaded\\r'), FloatProgress(value=1.0, max=1.0)))" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ " View run light-glitter-6 at: https://wandb.ai/sarosavo/RLfinetuning_Diffusion_Bioseq-tutorials_UTR/runs/tjd8mzbr
View project at: https://wandb.ai/sarosavo/RLfinetuning_Diffusion_Bioseq-tutorials_UTR
Synced 7 W&B file(s), 0 media file(s), 0 artifact file(s) and 1 other file(s)" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "Find logs at: ./wandb/run-20240718_155320-tjd8mzbr/logs" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "The new W&B backend becomes opt-out in version 0.18.0; try it out with `wandb.require(\"core\")`! See https://wandb.me/wandb-core for more information." ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "run = wandb.init() \n", "artifact = run.use_artifact('fderc_diffusion/Diffusion-DNA-RNA/UTR-dataset:v0')\n", "dir = artifact.download()\n", "wandb.finish()\n", "\n", "run = wandb.init()\n", "artifact = run.use_artifact('fderc_diffusion/Diffusion-DNA-RNA/UTR-Model:v0')\n", "dir = artifact.download()\n", "wandb.finish()\n" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "LightningDiffusion(\n", " (model): ScoreNet_Conditional(\n", " (embed): Sequential(\n", " (0): GaussianFourierProjection()\n", " (1): Linear(in_features=256, out_features=256, bias=True)\n", " )\n", " (linear): Conv1d(4, 256, kernel_size=(9,), stride=(1,), padding=(4,))\n", " (blocks): ModuleList(\n", " (0-1): 2 x Conv1d(256, 256, kernel_size=(9,), stride=(1,), padding=(4,))\n", " (2): Conv1d(256, 256, kernel_size=(9,), stride=(1,), padding=(16,), dilation=(4,))\n", " (3): Conv1d(256, 256, kernel_size=(9,), stride=(1,), padding=(64,), dilation=(16,))\n", " (4): Conv1d(256, 256, kernel_size=(9,), stride=(1,), padding=(256,), dilation=(64,))\n", " (5-6): 2 x Conv1d(256, 256, kernel_size=(9,), stride=(1,), padding=(4,))\n", " (7): Conv1d(256, 256, kernel_size=(9,), stride=(1,), padding=(16,), dilation=(4,))\n", " (8): Conv1d(256, 256, kernel_size=(9,), stride=(1,), padding=(64,), dilation=(16,))\n", " (9): Conv1d(256, 256, kernel_size=(9,), stride=(1,), padding=(256,), dilation=(64,))\n", " (10-11): 2 x Conv1d(256, 256, kernel_size=(9,), stride=(1,), padding=(4,))\n", " (12): Conv1d(256, 256, kernel_size=(9,), stride=(1,), padding=(16,), dilation=(4,))\n", " (13): Conv1d(256, 256, kernel_size=(9,), stride=(1,), padding=(64,), dilation=(16,))\n", " (14): Conv1d(256, 256, kernel_size=(9,), stride=(1,), padding=(256,), dilation=(64,))\n", " (15-16): 2 x Conv1d(256, 256, kernel_size=(9,), stride=(1,), padding=(4,))\n", " (17): Conv1d(256, 256, kernel_size=(9,), stride=(1,), padding=(16,), dilation=(4,))\n", " (18): Conv1d(256, 256, kernel_size=(9,), stride=(1,), padding=(64,), dilation=(16,))\n", " (19): Conv1d(256, 256, kernel_size=(9,), stride=(1,), padding=(256,), dilation=(64,))\n", " )\n", " (denses): ModuleList(\n", " (0-19): 20 x Dense(\n", " (dense): Linear(in_features=256, out_features=256, bias=True)\n", " )\n", " )\n", " (norms): ModuleList(\n", " (0-19): 20 x GroupNorm(1, 256, eps=1e-05, affine=True)\n", " )\n", " (cls_layers): ModuleList(\n", " (0-19): 20 x Dense(\n", " (dense): Linear(in_features=256, out_features=256, bias=True)\n", " )\n", " )\n", " (embed_class): Embedding(4, 256)\n", " (relu): ReLU()\n", " (softplus): Softplus(beta=1.0, threshold=20.0)\n", " (final): Sequential(\n", " (0): Conv1d(256, 256, kernel_size=(1,), stride=(1,))\n", " (1): GELU(approximate='none')\n", " (2): Conv1d(256, 4, kernel_size=(1,), stride=(1,))\n", " )\n", " )\n", ")" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "class ModelParameters:\n", " diffusion_weights_file = 'artifacts/UTR-dataset:v0/steps400.cat4.speed_balance.time4.0.samples100000.pth'\n", " time_schedule = \"artifacts/UTR-dataset:v0/time_dependent.npz\"\n", " checkpoint_path = 'artifacts/UTR-Model:v0/diffusion_epoch=030.ckpt'\n", " \n", "config = ModelParameters() \n", "DEVICE = \"cuda:1\" # Any number is fine\n", "\n", "score_model = lightning_dif.load_from_checkpoint(checkpoint_path = config.checkpoint_path, weight_file = config.diffusion_weights_file, time_schedule = config.time_schedule, all_class_number = 3)\n", "score_model.cuda(device = DEVICE) " ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "sampler = ddsm.Euler_Maruyama_sampler\n", "yS = 2.0 * torch.ones(128)\n", "yS = yS.type(torch.LongTensor)\n", "yS = yS.to(DEVICE)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Generate Samples with High Translational Efficiency for Evaluation" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "100%|██████████| 100/100 [00:02<00:00, 41.13it/s]\n", "100%|██████████| 100/100 [00:01<00:00, 65.11it/s]\n", "100%|██████████| 100/100 [00:01<00:00, 65.74it/s]\n", "100%|██████████| 100/100 [00:01<00:00, 65.48it/s]\n", "100%|██████████| 100/100 [00:01<00:00, 65.14it/s]\n" ] } ], "source": [ "#generate sequence samples\n", "# Condition on 2 (High expression)\n", "\n", "allsamples_original = []\n", "for t in range(5):\n", " samples=[]\n", " score_model.eval()\n", " samples.append(sampler(score_model,\n", " (50,4),\n", " batch_size=128,\n", " new_class = yS,\n", " class_number = 3,\n", " strength = 10, \n", " max_time= 4.0,\n", " min_time= 1.0/400,\n", " time_dilation=1,\n", " num_steps=100, \n", " eps=1e-5,\n", " speed_balanced= True,\n", " device= DEVICE, \n", " ).cpu().detach().numpy())\n", " allsamples_original.append(samples)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(640, 50, 4)\n" ] } ], "source": [ "allsamples = np.concatenate(allsamples_original, axis=1)\n", "allsamples = allsamples[0,:,:,:]\n", "print(allsamples.shape)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Get Original Data" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(9781, 50, 4)\n" ] } ], "source": [ "data = np.load(\"artifacts/UTR-dataset:v0/RNA_seq.npz\")['x']\n", "label = np.load(\"artifacts/UTR-dataset:v0/RNA_seq.npz\")['y'] \n", "valsamples = data[label == 2, :, :]\n", "print(valsamples.shape)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Plot Propeties " ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "\u001b[34m\u001b[1mwandb\u001b[0m: Downloading large artifact human_state_dict:latest, 939.29MB. 1 files... \n", "\u001b[34m\u001b[1mwandb\u001b[0m: 1 of 1 files downloaded. \n", "Done. 0:0:0.7\n" ] }, { "data": { "text/plain": [ "LightningModel(\n", " (model): EnformerPretrainedModel(\n", " (embedding): EnformerTrunk(\n", " (conv_tower): EnformerConvTower(\n", " (blocks): ModuleList(\n", " (0): Sequential(\n", " (0): Conv1d(4, 768, kernel_size=(15,), stride=(1,), padding=same)\n", " (1): ConvBlock(\n", " (norm): Norm(\n", " (layer): BatchNorm1d(768, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", " )\n", " (conv): Conv1d(768, 768, kernel_size=(1,), stride=(1,), padding=same)\n", " (act): Activation(\n", " (layer): GELU()\n", " )\n", " (pool): Pool(\n", " (layer): AttentionPool(\n", " (pool_fn): Rearrange('b d (n p) -> b d n p', p=2)\n", " (to_attn_logits): Conv2d(768, 768, kernel_size=(1, 1), stride=(1, 1), bias=False)\n", " )\n", " )\n", " (dropout): Dropout(\n", " (layer): Identity()\n", " )\n", " (channel_transform): ChannelTransform(\n", " (layer): Identity()\n", " )\n", " )\n", " )\n", " (1): Sequential(\n", " (0): ConvBlock(\n", " (norm): Norm(\n", " (layer): BatchNorm1d(768, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", " )\n", " (conv): Conv1d(768, 768, kernel_size=(5,), stride=(1,), padding=same)\n", " (act): Activation(\n", " (layer): GELU()\n", " )\n", " (pool): Pool(\n", " (layer): Identity()\n", " )\n", " (dropout): Dropout(\n", " (layer): Identity()\n", " )\n", " )\n", " (1): ConvBlock(\n", " (norm): Norm(\n", " (layer): BatchNorm1d(768, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", " )\n", " (conv): Conv1d(768, 768, kernel_size=(1,), stride=(1,), padding=same)\n", " (act): Activation(\n", " (layer): GELU()\n", " )\n", " (pool): Pool(\n", " (layer): AttentionPool(\n", " (pool_fn): Rearrange('b d (n p) -> b d n p', p=2)\n", " (to_attn_logits): Conv2d(768, 768, kernel_size=(1, 1), stride=(1, 1), bias=False)\n", " )\n", " )\n", " (dropout): Dropout(\n", " (layer): Identity()\n", " )\n", " (channel_transform): ChannelTransform(\n", " (layer): Identity()\n", " )\n", " )\n", " )\n", " (2): Sequential(\n", " (0): ConvBlock(\n", " (norm): Norm(\n", " (layer): BatchNorm1d(768, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", " )\n", " (conv): Conv1d(768, 896, kernel_size=(5,), stride=(1,), padding=same)\n", " (act): Activation(\n", " (layer): GELU()\n", " )\n", " (pool): Pool(\n", " (layer): Identity()\n", " )\n", " (dropout): Dropout(\n", " (layer): Identity()\n", " )\n", " )\n", " (1): ConvBlock(\n", " (norm): Norm(\n", " (layer): BatchNorm1d(896, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", " )\n", " (conv): Conv1d(896, 896, kernel_size=(1,), stride=(1,), padding=same)\n", " (act): Activation(\n", " (layer): GELU()\n", " )\n", " (pool): Pool(\n", " (layer): AttentionPool(\n", " (pool_fn): Rearrange('b d (n p) -> b d n p', p=2)\n", " (to_attn_logits): Conv2d(896, 896, kernel_size=(1, 1), stride=(1, 1), bias=False)\n", " )\n", " )\n", " (dropout): Dropout(\n", " (layer): Identity()\n", " )\n", " (channel_transform): ChannelTransform(\n", " (layer): Identity()\n", " )\n", " )\n", " )\n", " (3): Sequential(\n", " (0): ConvBlock(\n", " (norm): Norm(\n", " (layer): BatchNorm1d(896, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", " )\n", " (conv): Conv1d(896, 1024, kernel_size=(5,), stride=(1,), padding=same)\n", " (act): Activation(\n", " (layer): GELU()\n", " )\n", " (pool): Pool(\n", " (layer): Identity()\n", " )\n", " (dropout): Dropout(\n", " (layer): Identity()\n", " )\n", " )\n", " (1): ConvBlock(\n", " (norm): Norm(\n", " (layer): BatchNorm1d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", " )\n", " (conv): Conv1d(1024, 1024, kernel_size=(1,), stride=(1,), padding=same)\n", " (act): Activation(\n", " (layer): GELU()\n", " )\n", " (pool): Pool(\n", " (layer): AttentionPool(\n", " (pool_fn): Rearrange('b d (n p) -> b d n p', p=2)\n", " (to_attn_logits): Conv2d(1024, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)\n", " )\n", " )\n", " (dropout): Dropout(\n", " (layer): Identity()\n", " )\n", " (channel_transform): ChannelTransform(\n", " (layer): Identity()\n", " )\n", " )\n", " )\n", " (4): Sequential(\n", " (0): ConvBlock(\n", " (norm): Norm(\n", " (layer): BatchNorm1d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", " )\n", " (conv): Conv1d(1024, 1152, kernel_size=(5,), stride=(1,), padding=same)\n", " (act): Activation(\n", " (layer): GELU()\n", " )\n", " (pool): Pool(\n", " (layer): Identity()\n", " )\n", " (dropout): Dropout(\n", " (layer): Identity()\n", " )\n", " )\n", " (1): ConvBlock(\n", " (norm): Norm(\n", " (layer): BatchNorm1d(1152, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", " )\n", " (conv): Conv1d(1152, 1152, kernel_size=(1,), stride=(1,), padding=same)\n", " (act): Activation(\n", " (layer): GELU()\n", " )\n", " (pool): Pool(\n", " (layer): AttentionPool(\n", " (pool_fn): Rearrange('b d (n p) -> b d n p', p=2)\n", " (to_attn_logits): Conv2d(1152, 1152, kernel_size=(1, 1), stride=(1, 1), bias=False)\n", " )\n", " )\n", " (dropout): Dropout(\n", " (layer): Identity()\n", " )\n", " (channel_transform): ChannelTransform(\n", " (layer): Identity()\n", " )\n", " )\n", " )\n", " (5): Sequential(\n", " (0): ConvBlock(\n", " (norm): Norm(\n", " (layer): BatchNorm1d(1152, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", " )\n", " (conv): Conv1d(1152, 1280, kernel_size=(5,), stride=(1,), padding=same)\n", " (act): Activation(\n", " (layer): GELU()\n", " )\n", " (pool): Pool(\n", " (layer): Identity()\n", " )\n", " (dropout): Dropout(\n", " (layer): Identity()\n", " )\n", " )\n", " (1): ConvBlock(\n", " (norm): Norm(\n", " (layer): BatchNorm1d(1280, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", " )\n", " (conv): Conv1d(1280, 1280, kernel_size=(1,), stride=(1,), padding=same)\n", " (act): Activation(\n", " (layer): GELU()\n", " )\n", " (pool): Pool(\n", " (layer): AttentionPool(\n", " (pool_fn): Rearrange('b d (n p) -> b d n p', p=2)\n", " (to_attn_logits): Conv2d(1280, 1280, kernel_size=(1, 1), stride=(1, 1), bias=False)\n", " )\n", " )\n", " (dropout): Dropout(\n", " (layer): Identity()\n", " )\n", " (channel_transform): ChannelTransform(\n", " (layer): Identity()\n", " )\n", " )\n", " )\n", " (6): Sequential(\n", " (0): ConvBlock(\n", " (norm): Norm(\n", " (layer): BatchNorm1d(1280, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", " )\n", " (conv): Conv1d(1280, 1536, kernel_size=(5,), stride=(1,), padding=same)\n", " (act): Activation(\n", " (layer): GELU()\n", " )\n", " (pool): Pool(\n", " (layer): Identity()\n", " )\n", " (dropout): Dropout(\n", " (layer): Identity()\n", " )\n", " )\n", " (1): ConvBlock(\n", " (norm): Norm(\n", " (layer): BatchNorm1d(1536, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", " )\n", " (conv): Conv1d(1536, 1536, kernel_size=(1,), stride=(1,), padding=same)\n", " (act): Activation(\n", " (layer): GELU()\n", " )\n", " (pool): Pool(\n", " (layer): AttentionPool(\n", " (pool_fn): Rearrange('b d (n p) -> b d n p', p=2)\n", " (to_attn_logits): Conv2d(1536, 1536, kernel_size=(1, 1), stride=(1, 1), bias=False)\n", " )\n", " )\n", " (dropout): Dropout(\n", " (layer): Identity()\n", " )\n", " (channel_transform): ChannelTransform(\n", " (layer): Identity()\n", " )\n", " )\n", " )\n", " )\n", " )\n", " (transformer_tower): EnformerTransformerTower(\n", " (blocks): ModuleList(\n", " (0-2): 3 x EnformerTransformerBlock(\n", " (norm): Norm(\n", " (layer): LayerNorm((1536,), eps=1e-05, elementwise_affine=True)\n", " )\n", " (mha): Attention(\n", " (to_q): Linear(in_features=1536, out_features=512, bias=False)\n", " (to_k): Linear(in_features=1536, out_features=512, bias=False)\n", " (to_v): Linear(in_features=1536, out_features=1536, bias=False)\n", " (to_out): Linear(in_features=1536, out_features=1536, bias=True)\n", " (to_rel_k): Linear(in_features=192, out_features=512, bias=False)\n", " (pos_dropout): Dropout(p=0.01, inplace=False)\n", " (attn_dropout): Dropout(p=0.05, inplace=False)\n", " )\n", " (dropout): Dropout(\n", " (layer): Dropout(p=0.4, inplace=False)\n", " )\n", " (ffn): FeedForwardBlock(\n", " (dense1): LinearBlock(\n", " (norm): Norm(\n", " (layer): LayerNorm((1536,), eps=1e-05, elementwise_affine=True)\n", " )\n", " (linear): Linear(in_features=1536, out_features=3072, bias=True)\n", " (dropout): Dropout(\n", " (layer): Dropout(p=0.4, inplace=False)\n", " )\n", " (act): Activation(\n", " (layer): ReLU()\n", " )\n", " )\n", " (dense2): LinearBlock(\n", " (norm): Norm(\n", " (layer): Identity()\n", " )\n", " (linear): Linear(in_features=3072, out_features=1536, bias=True)\n", " (dropout): Dropout(\n", " (layer): Dropout(p=0.4, inplace=False)\n", " )\n", " (act): Activation(\n", " (layer): Identity()\n", " )\n", " )\n", " )\n", " )\n", " )\n", " )\n", " (pointwise_conv): ConvBlock(\n", " (norm): Norm(\n", " (layer): BatchNorm1d(1536, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", " )\n", " (conv): Conv1d(1536, 3072, kernel_size=(1,), stride=(1,), padding=same)\n", " (act): Activation(\n", " (layer): GELU()\n", " )\n", " (pool): Pool(\n", " (layer): Identity()\n", " )\n", " (dropout): Dropout(\n", " (layer): Identity()\n", " )\n", " )\n", " (act): Activation(\n", " (layer): GELU()\n", " )\n", " (crop): Crop(\n", " (layer): Identity()\n", " )\n", " )\n", " (head): ConvHead(\n", " (channel_transform): ChannelTransformBlock(\n", " (norm): Norm(\n", " (layer): Identity()\n", " )\n", " (conv): ChannelTransform(\n", " (layer): Conv1d(3072, 1, kernel_size=(1,), stride=(1,), padding=same)\n", " )\n", " (act): Activation(\n", " (layer): Identity()\n", " )\n", " (dropout): Dropout(\n", " (layer): Identity()\n", " )\n", " )\n", " (pool): AdaptivePool(\n", " (layer): AdaptiveAvgPool1d(output_size=1)\n", " )\n", " )\n", " )\n", " (loss): MSELoss()\n", " (activation): Identity()\n", " (val_metrics): MetricCollection(\n", " (mse): MSE()\n", " (pearson): PearsonCorrCoef(\n", " (pearson): PearsonCorrCoef()\n", " ),\n", " prefix=val_\n", " )\n", " (test_metrics): MetricCollection(\n", " (mse): MSE()\n", " (pearson): PearsonCorrCoef(\n", " (pearson): PearsonCorrCoef()\n", " ),\n", " prefix=test_\n", " )\n", " (transform): Identity()\n", ")" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from grelu.lightning import LightningModel\n", "model = LightningModel.load_from_checkpoint(\"artifacts/UTR-Model:v0/reward_model.ckpt\")\n", "model.eval()\n", "model.to(DEVICE)" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(640, 1, 1)\n" ] } ], "source": [ "data_loader = torch.utils.data.DataLoader(valsamples.astype(\"float32\"), batch_size = 128 , num_workers=0)\n", "val_samples = []\n", "\n", "for batch in data_loader:\n", " batch = torch.permute(batch, (0, 2, 1)).to(DEVICE)\n", " val_samples.append( model(batch).detach().cpu() ) \n", "\n", "val_samples = np.concatenate(val_samples)\n", "\n", "generated_samples = []\n", "data_loader = torch.utils.data.DataLoader(allsamples.astype(\"float32\"), batch_size = 128 , num_workers=0)\n", "for batch in data_loader:\n", " batch = (batch > 0.5) * torch.ones_like(batch)\n", " batch = torch.permute(batch, (0, 2, 1)).to(DEVICE)\n", " generated_samples.append( model(batch).detach().cpu() ) \n", "\n", "generated_samples = np.concatenate(generated_samples)\n", "print(generated_samples.shape)\n" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0.47260746\n", "0.81325275\n" ] }, { "data": { "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/png": "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qY7H45HH46n1vgEACLWwOE96z549GjBggNq2baupU6dq7969ysvLU15eXpV1unTponXr1kmSdu7cqSeffFLr169Xdna23nnnHY0ePVqXXHKJevToYddLAQCgxsJi4Nh7772nrKwsZWVlqU2bNlWWHe6tr6ioUGZmpkpKSiRJUVFRWrZsmaZPn67i4mIlJSVpxIgReuihh+q9fgAATkbYniddXzhPGgBgl7Do7gYA4HRESAMA4FCENAAADkVIAwDgUIQ0AAAORUgDAOBQhDQAAA4VFhczsdPh08i5GxYAINSaNGkiy7KqXU5In8D3338vSUpKSrK5EgBAQ3OiC2VxxbETCAQC+uabb074awf16/DdyXbv3s2V4IDj4LPibLSkT5HL5TrqeuFwjtjYWL54gBrgsxKeGDgGAIBDEdIAADgUIY2w5PF49Oijj8rj8dhdCuBofFbCGwPHAABwKFrSAAA4FCENAIBDEdIIiezsbFmWpU2bNtV4m7lz56pp06a21yFJ7du31/Tp00NaC4BD+HydPEIaQbt379ZNN92kVq1aKSoqSu3atdOdd96pgoKCE26blJSk3NxcnXPOOTV+vmuuuUbbt28/lZJtUxc/MNAw5OXl6c4771RycrKio6OVkJCgiy66SC+99JJKSkrsLq/GCFZn4GImkCR9+eWXSklJ0dlnn63XXntNHTp00Oeff657771X//rXv7RmzRo1a9bsmNuWl5crKipKiYmJtXrOmJgYxcTEhKJ8wBG+/PJLXXTRRWratKmeeuopnXvuufJ4PNq6datmzZql1q1b64orrrCtPmOM/H6/IiL46g8bBjDGpKWlmTZt2piSkpIq83Nzc43X6zXjx48PzmvXrp154oknzPXXX2+aNGlibrjhBvPVV18ZSWbjxo3B9d5++22TnJxsPB6PGTBggJk7d66RZL777jtjjDFz5swxcXFxwfUfffRRc95555n58+ebdu3amdjYWHPNNdcYn88XXOdf//qXueiii0xcXJxp1qyZGTJkiMnKygouP1YdP5afn2+GDh1qoqOjTfv27c0rr7xi2rVrZ6ZNmxZc5w9/+IM555xzjNfrNW3atDG33nqr+f77740xxnzwwQdGUpXHo48+aowxZv78+aZ3796mcePGJiEhwVx77bUmPz+/hn8FhLvU1FTTpk0bU1RUdMzlgUAg+O/vvvvOjB071rRo0cI0adLEDBw40GzatCm4vCafB7/fb5566inTvn17Ex0dbXr06GHefPPN4PLD79WlS5eaXr16mcjISPPBBx+YrKwsc8UVV5gzzzzTNGrUyPTp08e89957we369+9/1Hv8sI8++shcfPHFJjo62rRp08bcfvvtVV5vTT5fqDlCGqagoMBYlmWeeuqpYy4fN26cOeOMM4JfMIe/MKZOnWqysrJMVlbWUeH45ZdfmsjISHPPPfeYjIwM89prr5nWrVufMKQbN25srr76arN161bz4YcfmsTERPPb3/42uM4//vEP889//tPs2LHDbNy40QwbNsyce+65xu/3G2NqFtKXX365Oe+888zq1avNp59+avr162diYmKqfIlMmzbNvP/+++arr74yy5cvN507dza33nqrMcaYsrIyM336dBMbG2tyc3NNbm5uMMBffvlls3TpUrNz506zevVqk5KSYi6//PLa/DkQpvbt22csyzJTpkyp0fqDBg0yw4YNM5988onZvn27mThxomnevLkpKCgwxtTs8/C73/3OdOnSxaSnp5udO3eaOXPmGI/HY1asWGGM+SGke/ToYf7zn/+YrKwsU1BQYDZt2mRmzpxptm7darZv324eeughEx0dbXbt2mWMOfSd0KZNG/PEE08E3+PGGJOVlWUaNWpkpk2bZrZv325WrVplzj//fDNmzJhgTTX5fKHmCGmYNWvWGElm0aJFx1z+3HPPGUnBFmG7du3M8OHDq6zz43C8//77zTnnnFNlnQcffPCEIe31equ0FO69915zwQUXVFv73r17jSSzdevWY9bxY5mZmUaSWbduXXDetm3bjKTjfom8+eabpnnz5sHpH9denU8++cRICoY4Gq7Dn6OFCxdWmd+8eXPTqFEj06hRI3PfffcZYw61RmNjY01paWmVdTt16mT+/Oc/G2NO/HkoLS01Xq/XfPzxx1X2MXbsWHPttdcaY34I6bfeeuuE9Xfv3t3MmDEjOH2s1u/YsWPNLbfcUmXeRx99ZFwulzl48OBJf75QPQ5MIMjU4ro2ffr0Oe7yzMxM/eQnP6kyr2/fvifcb/v27dWkSZPgdMuWLfXtt98Gp3fs2KFHHnlEa9eu1b59+xQIBCRJOTk5NRq0tm3bNkVERKh3797BeV26dDlqENiyZcs0ZcoUZWRkyOfzqbKyUqWl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GTJEs2fPliQtXrxYZWVlGjlyZJX1UlJSjpo+3JLevHmzsrKy1KRJEzVu3FiNGzdWs2bNVFpaqp07d9bPCwHCDHfBAlAjN998s66//npNmzZNc+bM0TXXXCOv11vj7YuKitS7d2+9+uqrRy2Lj48PZalAg0FIAzhKVFSU/H5/lXmDBw9Wo0aN9NJLLyk9PV0ffvjhUdutWbNGo0ePrjJ9/vnnS5J69eql119/XWeeeaZiY2Pr9gUADQTd3QCO0r59e61du1bZ2dnat2+fAoGA3G63xowZo0mTJumss846qmtbkt58803Nnj1b27dv16OPPqp169bptttukyRdd911atGiha688kp99NFH+uqrr7RixQrdcccd+vrrr+v7JQJhgZAGcJR77rlHbrdb3bp1U3x8vHJyciRJY8eOVXl5uW688cZjbvf444/r73//u3r06KH58+frtddeU7du3SRJXq9XH374odq2baurr75aXbt21dixY1VaWkrLGqiGZYwxdhcBIDx89NFHuvTSS7V7924lJCRUWWZZlhYtWqThw4fbUxzQAHFMGsAJlZWVae/evXrsscc0cuTIowIaQN2guxvACb322mtq166dDhw4oGeeecbucoDTBt3dAAA4FC1pAAAcipAGAMChCGkAAByKkAYAwKEIaQAAHIqQBgDAoQhpAAAcipAGAMChCGkAABzq/wPxNkk5RTQSuQAAAABJRU5ErkJggg==", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%matplotlib inline\n", "import seaborn as sns\n", "import matplotlib.pyplot as plt\n", "\n", "plt.figure(figsize=(80, 10))\n", "\n", "compare = np.concatenate( (val_samples[:,0], generated_samples[:,0] ), axis= 0)\n", "\n", "type1 = ['Original data' for i in range(len(val_samples[:,0] ))]\n", "#type2 = ['Generated (Strong Sig)' for i in range(len(generated_samples[:,0] ))]\n", "type3 = ['Generated ' for i in range(len(generated_samples[:,0]))]\n", "\n", "type = type1 + type3\n", "data_dict = {'type': type, 'value': compare[:,0] }\n", "plot_data = pd.DataFrame(data_dict)\n", "fig = sns.catplot(data=plot_data, x = 'type', y = 'value', hue=\"type\", kind=\"boxen\" )\n", "sns.set_context(\"paper\", rc={\"figure.figsize\": (80, 10)})\n", "#fig.savefig(\"../media/RNA_output_high.png\")\n", "\n", "print(np.mean(val_samples[:,0] ))\n", "print(np.mean(generated_samples[:,0] ))\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Generate normal samples" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [], "source": [ "sampler = ddsm.Euler_Maruyama_sampler\n", "yS = 3.0 * torch.ones(128)\n", "yS = yS.type(torch.LongTensor)\n", "yS = yS.to(DEVICE)" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "100%|██████████| 100/100 [00:01<00:00, 54.31it/s]\n", "100%|██████████| 100/100 [00:01<00:00, 64.86it/s]\n", "100%|██████████| 100/100 [00:01<00:00, 61.55it/s]\n", "100%|██████████| 100/100 [00:01<00:00, 62.40it/s]\n", "100%|██████████| 100/100 [00:01<00:00, 64.77it/s]\n" ] } ], "source": [ "# # Generate sequences with y=3 (unconditional)\n", "\n", "allsamples_original = []\n", "for t in range(5):\n", " samples=[]\n", " score_model.eval()\n", " samples.append(sampler(score_model,\n", " (50,4),\n", " batch_size=128,\n", " new_class = yS,\n", " class_number = 3,\n", " strength = 2, \n", " max_time= 4.0,\n", " min_time= 1.0/400,\n", " time_dilation=1,\n", " num_steps=100, \n", " eps=1e-5,\n", " speed_balanced= True,\n", " device= DEVICE, \n", " ).cpu().detach().numpy())\n", " allsamples_original.append(samples)" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(640, 50, 4)\n" ] } ], "source": [ "allsamples = np.concatenate(allsamples_original, axis=1)\n", "allsamples = allsamples[0,:,:,:]\n", "print(allsamples.shape)" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "data = np.load(\"artifacts/UTR-dataset:v0/RNA_seq.npz\")['x']\n", "valsamples = data" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [], "source": [ "seq_gen_int = np.argmax(allsamples, axis=-1)\n", "seq_gen_str = [''.join([['A','C','G','T'][num] for num in seq]) for seq in seq_gen_int]\n", "gen_kmers = utils.count_kmers(seq_gen_str)\n", "seq_val_int = np.argmax(valsamples, axis=-1)\n", "seq_val_str = [''.join([['A','C','G','T'][num] for num in seq]) for seq in seq_val_int]\n", "val_kmers = utils.count_kmers(seq_val_str)" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "image/png": "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KtK0adNUWloa7GECAAAm1lR1ssLl9ge0pqqTGQ4rtzQCiIigw5lhGIqJCVwtJiYm4OpTa2w2m2bPnq3+/fvLYrHo9NNP1+jRo/WPf/yj1XWXLFmigQMH6tprr5XVatVtt90mn8+nFStWSJJeeuklXXfddRo+fLgcDofmzJmjJUuWqLq6WpJUVFSkWbNmKSMjQ3369NFvf/tbLViwQJJUVlam1atXa86cOUpMTNSYMWM0YcIEvfzyy21+bQAAoGPIzXQoMzlBlbUe7XPVq7LW0yGrTgKIHkGHs1/84heaPn26ampqJEnV1dW68cYb9Ytf/KLdnaitrdVXX32l/Px8/7JJkyape/fuGjNmjD7//HP/8tLSUhUUFPgfWywWDRs2zH9169D23NxcxcfHa9OmTaqqqtKuXbsC2gsKCgLW7du3r7p27dpie0t2796t4uLiw342btzY3sMBAACOg6aqk6f0S1NB7646pV+a8rJTuKURQMQEfc3+iSee0Hnnnae0tDSlpaWpqqpK+fn5evfdd9vVAZ/Pp8mTJ2vkyJEaN26cJGnhwoUaMWKEpMYrYePHj9f69evVt29fuVyugPAkSampqXI6nZIkl8ul1NTUFttdLpf/cfO2+vp6eb3eo657JPPmzdODDz7YnpcOAABMoCNXnQQQXYIOZz179tTatWu1Zs0a7dy5U71799Ypp5xy2K2ObWEYhqZPn65du3bp/fff95fjP/300/3PmTFjhhYtWqTly5dr+vTpstvt/lsUm1RXV8vhaLwF4Wjtdrvd/7j57wkJCYqLi2t12y254YYbNGHChMOWb9y4URMnTmzroQAAIKxqO/icZADQGQT97ux2uxUTE6NRo0Zp1KhRkqSGhgY1NDTIam37106GYeimm25SSUmJVqxY4Q9LLWk+pi0/P1/z588P2M4333yjGTNm+NtLSkp0zTXXSJI2b94st9utE088USkpKerZs6dKSkqUnZ0tSSopKfHfTpmfn6/t27dr//79/itozdtbkpWVpaysrDa/bgAAjieP16eycqf2ON2SGisRZjisys10mOr2PcIjALRjzNm5554bUFVRkr744gv96le/Cmo7M2fO1P/+7//q/fffV3Jysn/5jh07tGrVKnk8Hnk8Hj3//PP68ssv/bc8XnzxxSorK9PChQvl8Xj01FNPSZLGjh0rSZo8ebKKior09ddfy+Vy6b777tPFF1+slJQUf/sf/vAH7d27Vzt37tTjjz+uKVOmSGocnzZy5Ejdd999qqur06effqply5Zp0qRJwR4mAABMoazcqfKaeqXZ4tXNnqA0W7zKa+pVVu5UrdurqlqPat3eiPXP4/Vpww/VWrO1UiU7q7Rma6U2/FD90zxkANC5BP3V1Lp163TaaacFLDvttNP09ddft3kb27dv1zPPPCOr1arevXv7l99zzz268MILdfPNN2vz5s2Kj4/XkCFD9O6772rAgAGSpPT0dL399tuaOXOmpk2bpvz8fC1btsx/1e7ss8/WAw88oPPOO081NTUaN26cXnzxRf8+CgsLtW/fPuXm5io2NlbTpk0LKLW/aNEiTZkyRenp6crIyNC8efOOeuUMAACzqnV7tcfpVrrd6p9sOcZiUXJiF325tVI7Kg8ooUvjfF+RuprWFB6b+ugzDJXX1EuS8rJTjmtfACDSLEYwNfAlde/eXTt37lRCQoJ/WX19vbKzs1VRURHyDnZUxcXFGjFihNauXavhw4dHujsAgE6oqtajkp1V6mZPCFi+Za9LW/e5dHJOmlIT4/3ze2UmJxzXQFTr9mrN1kql2eL94VFqnG+sstajU/qlcYsjgKjQ1mwQ9Ndjw4YN00svvRSw7JVXXtHQoUOD7iQAAAifxqtgFv8ky5JU1+BVpcut5IQussbGSmq8mpZut2qP031cb3FsvHXRCAhmTf2RDG5tBNDpBP111EMPPaSzzjpL7733nk444QR9++23+vDDD/2TQAMAAHOwWeOU4bAG3Dbo9vpUU9+gnG42JcbH+p/bPBAdr7LyzcPjoVfOJIupCpYAwPEQ9Lvev/3bv+nLL79U3759tXHjRvXu3VtffvnlYePQAABA5OVmOpSZnKDKWo/2uerlrG9QalK8enVNCnheJAJRU3iscLn9V/eabrHMcFi5pRFAp9Oud728vDw9/fTToe4LAAAIsfi4GOVlpyinWan6bftqf7qaFuMvwtE05ux4B6LczMa5RJuX+s9MTvAvB4DOhK+kAADoBGzWOP/timYKRC2FR66YAeisePcDACBKHWliZzMGoubhEQA6K8IZAABRxuP1qazcGXBlrKV5zAhEAGAuQY36PXjwoNasWaOGhoZw9QcAAByjpomd02zx6mZPUJotXuU19Sord0a6awCAowgq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szHGYlG63ao9Trdq3d4I9xAAYFZtvq3xjDPOkMViUX19vX7+858HtO3YsUMnn3xyyDsHAEBH4/H6JBn+YNak8bEhj9cnmzUiXQMAmFybw9nYsWMlSatXr9ZZZ53lXx4TE6MePXroiiuuCH3vAADoYBrHlFnkMwIDms9oHHvGmDMAwJG0OZwVFhZKknJzc3X11VeHrUMAAHRkNmucMhxWldfU+29t9BmGKlxuZSYnhLVqI9UhAaBjC/qdu3kwMwwjYAxaTAzfBgIAkJvpkKSAao2ZyQn+5aFGdUgAiA5Bh7PKykrdfPPN+uCDD1RZWRnQdvDgwZB1DACAjio+LkZ52SnKOU5XspqqQza/UldeUy9JystOCdt+AQChFfTXabfeequ+++47Pf/880pKStJf//pXnXzyyXrqqafC0T8AADosmzVOXW3xYb+VkeqQABAdgg5nK1as0JtvvqkLL7xQsbGxuvDCC7Vw4UItWrQoqO243W5NnTpV/fr1k8PhUF5enl5//XV/e2lpqUaNGqWkpCQNGTJEH330UcD6b731lgYMGKCkpCSdddZZ2r59e0D7/fffr+7duyslJUVTp06V2+32t+3fv1+XX365HA6HevbsqSeffDJg3db2DQCAWbSlOiQAoGMIOpzV1taqd+/ekiSr1aqGhgbl5uZq/fr1QW3H6/WqZ8+e+vvf/66amhrNmzdPM2bM0BdffKGGhgadf/75mjBhgqqqqlRYWKiLLrpIe/bskSRt3LhRkydP1rPPPquKigoNGzZMl19+uX/bL7zwgl577TWtXr1a3333nTZt2qRZs2b522fOnCm3260ffvhB77//vh5++GEtX75cklrdNwAAZtK8OmRzVIcEgI4n6HfsPn36aPPmzZKkgQMHaunSpfr73/8um80W1HZsNptmz56t/v37y2Kx6PTTT9fo0aP1j3/8QytXrtSBAwd01113yWq16oorrlB+fr4WL14sSVq4cKHOOeccjRs3TomJiZo9e7bWrVunDRs2SJKKiop0++23q3///kpPT1dhYaGKiookNYbLxYsXa86cOUpOTtbQoUM1bdo0LViwQJJa3fehdu/ereLi4sN+Nm7cGOyhBQAgaE3VIStcbn9Aa6oOmeGwUrURADqQoN+xZ8yYofXr12vgwIG64447dPnll8swDD3yyCPH1JHa2lp99dVX+s1v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ffr0Merr6w3DMIwPPvjASEtLM9auXWvU1NQYl112mXH55Zf7t33vvfcaI0eONMrLy43t27cbgwYNMp555pnwvuAw++tf/2osXbrUuOmmm4wrrrjCv9zj8Rg5OTnGnDlzjPr6emPRokVGcnKyUV5ebhiGYfzf//2fYbPZjPfff984cOCAceuttxqnnHKKf/3nn3/e6Nevn7FlyxZj3759xujRo40777zT3360c7y1fXcURzq2hmEYffv2NZYvX97ieuE+T4/2N9JRuFwu4/777ze2bNli+Hw+Y9WqVUZycrLxj3/8g3P3GB3t2BoG524obNiwwThw4IBhGIaxY8cOY/DgwcZf/vIXzt0QONKxNQzO3VCaPHmyccYZZxinnnqqYRj8n8FsCGch5nK5jPj4+IA/2nvuuce49NJLI9gr8zhaOPv222+NuLg4o7Ky0r/s6quvNn77298ahmEY8+fPN0aMGOFv8/l8Rq9evYx3333X/9w77rjjsO3t37/fMAzD6Nmzp/HOO+/42+fPn2+cfPLJoXtxEVRYWBgQID744AMjIyPDOHjwoH/ZaaedZsydO9cwjMZz8pJLLvG31dTUGFar1SgtLfU/9+mnnw7YXvfu3Q3DaP0cb23fHc2hx9Ywjv6fhHCep639jXRk48ePN/7rv/6LczcMmo6tYXDuhtqOHTuMvLw8Y86cOZy7Idb82BoG526orFy50hg9erSxYMECfzjj3DUXbmsMsW+//VY+n0/5+fn+ZQUFBSotLY1gr8xl/vz5SktL00knnaQFCxb4l5eWlqpv377q2rWrf1nzY1daWqqCggJ/m8Vi0bBhw47Ynpubq/j4eG3atElVVVXatWtXQHs0/7uUlpZq6NChion515/40Y6lw+HQgAEDjtheUFCgvXv3qry8vNVzvLV9R4tJkyape/fuGjNmjD7//HP/8nCep639jXRUtbW1+uqrr5Sfn8+5G2LNj20Tzt1jd/fdd8tms6lPnz6qra3VxIkTOXdDpKVj24Rz99h4PB7NnDlTf/7zn2WxWPzLOXfNhXAWYi6XSykpKQHLUlNT5XQ6I9Qjc7nlllv07bffas+ePXryySd155136q9//aukxmOXmpoa8Pzmx+5Y2l0ul/9x87b6+np5vd7QvUCTCPWxbPq96Vge7RxvbdvRYOHChdq2bZt27NihK664QuPHj/fffx/O8zQaj63P59PkyZM1cuRIjRs3jnM3hA49thLnbqg88sgjcrlcWrNmja6++mp17dqVczdEWjq2EuduKDz66KMaO3asTjrppIDlnLvmQjgLMbvdrpqamoBl1dXVcjgcEeqRuQwfPlzdunVTXFyczjzzTN10001avHixpMZjV11dHfD85sfuWNrtdrv/cfO2hIQExcXFhfZFmkCoj2XT703H8mjneGvbjgann366EhMTlZiYqBkzZuhnP/uZli9fLim852m0HVvDMDR9+nTt2rVLf/nLX2SxWDh3Q6SlYytx7oaSxWLRyJEjlZCQoMLCQs7dEDr02Eqcu8dq8+bNeumll/Tggw8e1sa5ay6EsxAbNGiQLBaLNmzY4F9WUlIScDkX/xITE+OviJSfn6/t27dr//79/vbmxy4/P18lJSX+NsMw9M033xyxffPmzXK73TrxxBPVtWtX9ezZM6A9mv9d8vPztX79evl8Pv+yox1Ll8ulLVu2HLG9pKRE3bt3V2ZmZqvneGv7jkaHnsfhOk9b+xvpSAzD0E033aSSkhItX77c/x8kzt1jd6Rj2xLO3WPn9Xr95yDnbmg1HduWcO4G57PPPtOPP/6oQYMGqUePHvrNb36j4uJi9ejRQ/379+fcNZPIDHWLbldffbVxwQUXGDU1Ncb69euNzMxMqjX+5C9/+YtRU1NjHDx40Fi1apXRrVs344033vC3n3baacZNN91kHDhwwPjkk08Mh8NxWLXGV1991XC73cYTTzxh9O7dO6AaU3p6ulFcXGw4nU7jiiuuCKjGdM899xinnnqqsWfPHmPHjh3GiSee2OGrNTY0NBh1dXXGvffea1x22WVGXV2d4fF4/NWPHnnkEaO+vt548803W6y89OGHHxp1dXXG7bffHlB5af78+caAAQOM7777zqioqDDOOOOMgMpLRzvHW9t3R3GkY7t9+3bj008/Ndxut+F2u4358+cbNpvN2Lx5s2EY4T9Pj/Y30pHceOONxs9+9rOAQfaG0fr5w7nbuiMdW87dY1dZWWm88sorRnV1tXHw4EHjs88+M7p372786U9/4tw9Rkc7tpy7x+7AgQPG7t27/T9PPvmkMXz4cGP37t2cuyZDOAuDqqoq49JLLzVsNpvRo0cP44knnoh0l0zjjDPOMFJSUgy73W4MGTLEeO655wLad+zYYYwdO9ZITEw0+vbta7z++usB7R9//LGRl5dnJCQkGCeffLLx9ddfB7Q//fTTRlZWlmGz2YyLLroo4D8nbrfbuP76642UlBQjLS3N+P3vf2/4fL6wvdbjobCw0JAU8DNp0iTDMAzjm2++MU455RQjISHBOPHEE40VK1YErPvmm28a/fr1MxITE40zzzzT2LZtm7/N5/MZ9957r5Genm4kJycbU6ZM8X/IGUbr53hr++4IjnRsN2zYYJx00kmGzWYzunbtaowePdr4+OOPA9YN53na2t9IR7Bt2zZDkmG1Wg2bzeb/aarKxrnbfkc7tpy7x66qqso488wzjdTUVMNutxsnnHCC8eijj/pfJ+du+x3t2HLuhl5RUZG/WqNhcO6aicUwOvgsvAAAAAAQBRhzBgAAAAAmQDgDAAAAABMgnAEAAACACRDOAAAAAMAECGcAAAAAYAKEMwAAAAAwAcIZAAAAAJgA4QwA0Onl5OTohRdeiHQ3AACdHOEMABAxdrvd/xMfH6/Y2NiAZatWrYp0F9GCl156Sb169Yp0NwAg6sRFugMAgM7L5XL5f7/vvvv02WefaeXKlS0+1+PxKD4+/jj1zBwaGhrUpUuXSHcDAHCccOUMAGBKDzzwgE4//XTdf//96tmzpwoKCiRJFotFK1as8D9v27Ztslgs2rx5s3/Ze++9p1NPPVVdu3ZVbm6u/vSnP7V5v16vV9OnT9fPfvYzff/99y0+Z+XKlbJYLPrLX/6iQYMGKSkpSeeff77279+v+++/X1lZWerWrZsKCwsD1tu0aZN+9atfKTMzU9nZ2brxxhtVW1vrb8/JyVFhYaHOOeccORwOPf744y3u//vvv9c111yjXr16KTk5WQUFBSouLpYk1dfX6/e//7369eunrl276owzztDq1asPO67NTZ48WRMnTgzox+zZs3XuuefK4XBowIABWrp0qSRp1apVmj59unbt2uW/wvnaa6+1+fgCAI6McAYAMK3//d//VZcuXfTdd9/pq6++atM6H3/8sa6++mo9/PDDqqio0NKlS/XHP/6xTQGiqqpK55xzjnbt2qVVq1a1euvef//3f2vt2rXatm2b/vnPf+rUU09VZmamdu7cqXfffVdz5szRF198IUnat2+fzjjjDJ111lnasWOH1q1bp2+//Va33nprwDbnzZunwsJC1dTU6JZbbjlsn3V1dfr3f/93xcfHq6SkRPv379frr7+u9PR0SdLvfvc7vffee/rwww9VXl6uCy+8UGPHjj1i0DySF154QQ899JCqq6t10003adKkSaqpqdEZZ5yh5557Tj179pTL5ZLL5dI111wT1LYBAC0jnAEATCszM1P333+/EhISlJSU1KZ1nnjiCc2YMUNnnXWWYmJilJ+fr+nTp6uoqOio65WVlWnUqFEaNmyY3n77bdnt9lb3NWfOHDkcDmVkZOi8886TJM2cOVNxcXEaNWqUBg8erDVr1kiSXnnlFQ0cOFC33XabrFarunXrpgcffFCvvPKKDh486N/mddddp//fvv2EQv7HcRx/zbfWn5DZGtMghiUH5SKXbVlRSCn/jnJYKdqL5CIHpeSk9iCMg9qQi5SLkz9JykFy8Lf8p0QN7TZCwvd38v3tLLHza3/9vtvv+aipmc+nz7v353OYes13Pu/fv5fD4Xh2z5OTkzo/P5fP55PL5ZJhGMrMzJTX69XDw4MGBwfV2dmp9PR0hYWFqaWlRe/evdPIyMgvnd+j+vp6ZWdnyzAMNTQ0KBAIaHNzM6QaAIDQcOcMAGBbXq9XDocjpDXb29uanp5Wf3+/NXZ/f6/k5OQX1w0NDenNmzdqa2uTYfz922VjY6MVbLxer9bX1625+Ph4631UVFTQ58exQCBg9bW8vCyn02nNm6Yph8Oh09NTJSYmSpJSU1Nf7HN/f18pKSkKDw9/Muf3+3V9fa20tLSg8fT0dB0dHb1Y92cJCQlB+5Bk7QUA8O/gyRkAwLZ+DEmPoqOjg+5pnZycBM17PB61trbq27dv1isQCASFqud0dHSotLRUeXl5Oj4+tsZ9Pp/1973XarzE4/EoNzc3qK/v37/r5ubGCmbS83v+UUpKig4ODnR7e/tkzuVyKSIiQru7u0Hju7u7VjiNiYkJOj/p6Rm+5rUeAQD/DN+uAIA/Sk5Ojr5+/aqbmxudnZ2po6MjaL6pqUk9PT2amZnR3d2d7u7utLa2pvn5+RfrGoahgYEBVVZW6sOHD9ra2vqtfX/69EkrKyvq6+vT1dWVTNPU8fGxJiYmQqpTVlamt2/f6vPnz/L7/TJNUxsbGzo8PJRhGKqrq1N7e7v29vZ0e3urL1++aGdnx7oXlpOTo9XVVS0sLOj+/l5jY2Ovns3PPB6P/H6/zs/PQ1oHAHgZ4QwA8Efp7e3V6empXC6XioqKVFtbGzRfUVGh4eFhtbe3y+12y+12q76+Xn6//5fqd3V1qbm5WR8/ftTS0tJv6zs5OVmLi4uamppSWlqanE6nSkpKtLq6GlKdyMhIzc7O6vLyUllZWYqNjVVNTY0uLi4kSd3d3SouLlZBQYHcbrfGx8c1NTWlpKQkSVJ+fr7a2tpUVVWluLg4zc3Nqbq6OqQeCgsLVV5eroyMDDmdTo2Ojoa0HgDwPIdpmuZ/3QQAAAAA/N/x5AwAAAAAbIBwBgAAAAA2QDgDAAAAABsgnAEAAACADRDOAAAAAMAGCGcAAAAAYAOEMwAAAACwAcIZAAAAANgA4QwAAAAAbIBwBgAAAAA2QDgDAAAAABsgnAEAAACADfwFtVU49Tcb+csAAAAASUVORK5CYII=", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "PearsonRResult(statistic=0.9673470681785534, pvalue=1.1477418560792788e-38)" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "kmer_set = set(gen_kmers.keys()) | set(val_kmers.keys())\n", "counts = np.zeros((len(kmer_set), 2))\n", "for i, kmer in enumerate(kmer_set):\n", " if kmer in gen_kmers:\n", " counts[i][1] = gen_kmers[kmer] * valsamples.shape[0]/allsamples.shape[0]\n", " if kmer in val_kmers:\n", " counts[i][0] = val_kmers[kmer]\n", " \n", "fig, ax = plt.subplots(figsize=(10, 10))\n", "ax.scatter(counts[:, 0], counts[:, 1], alpha=0.2)\n", "ax.set_title(\"Comparison of 3-mer counts\")\n", "ax.set_xlabel(\"True k-mer count\")\n", "ax.set_ylabel(\"Generated k-mer count\")\n", "ax.set_ylim((-5, np.max(counts) + 5))\n", "ax.set_xlim((-5, np.max(counts) + 5))\n", "plt.show()\n", "\n", "sp.stats.pearsonr(counts[:, 0], counts[:, 1])" ] } ], "metadata": { "kernelspec": { "display_name": "diffusion", "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.12.4" } }, "nbformat": 4, "nbformat_minor": 2 }