{ "cells": [ { "cell_type": "markdown", "id": "14f0c29f", "metadata": {}, "source": [ "# Pooled rare variants\n", "\n", "{func}`~mantispy.ds.pooled_rare` serves `cpg0032-pooled-rare`, already aggregated to one profile per barcode. There is no plate, well or cell count in `obs`: this is the example of a pre-aggregated input, the shape a screen takes once wells have been collapsed to perturbations upstream. The 290 barcodes cover 132 genes, each barcode either a wild-type gene or one specific coding variant of it, so the genes come as allele series.\n", "\n", "**Use it if** your own data is already aggregated to one profile per perturbation, with no well or cell counts, or is an allele series (a wild type plus coding variants of the same gene). No tutorial is built on it; the profile-space tools apply directly, since the aggregation is already done." ] }, { "cell_type": "code", "execution_count": 1, "id": "6417eede", "metadata": { "execution": { "iopub.execute_input": "2026-10-21T01:00:19.017628Z", "iopub.status.busy": "2026-10-21T01:00:19.017221Z", "iopub.status.idle": "2026-10-21T01:00:24.343148Z", "shell.execute_reply": "2026-10-21T01:00:24.341150Z" } }, "outputs": [], "source": [ "import numpy as np\n", "import pandas as pd\n", "import plotly.express as px\n", "import scanpy as sc\n", "\n", "import mantispy as mt" ] }, { "cell_type": "code", "execution_count": 2, "id": "01b8a6c6", "metadata": { "execution": { "iopub.execute_input": "2026-10-21T01:00:24.346742Z", "iopub.status.busy": "2026-10-21T01:00:24.346481Z", "iopub.status.idle": "2026-10-21T01:00:24.535047Z", "shell.execute_reply": "2026-10-21T01:00:24.533569Z" } }, "outputs": [ { "data": { "text/plain": [ "AnnData object with n_obs × n_vars = 290 × 4417\n", " obs: 'Metadata_Foci_Barcode_MatchedTo_GeneCode', 'Metadata_Perturbation', 'Metadata_Perturbation_Type', 'Metadata_Gene', 'Metadata_Allele'\n", " var: 'object', 'feature_group', 'feature', 'channel', 'scale', 'angle', 'gray_levels', 'radial_bin', 'params', 'is_feature', 'feature_kind'\n", " uns: 'mantispy'\n", " layers: None (.X)" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "adata = mt.ds.pooled_rare()\n", "adata" ] }, { "cell_type": "markdown", "id": "4f20fad1", "metadata": {}, "source": [ "## An allele series\n", "\n", "`Metadata_Gene` is the gene and `Metadata_Allele` the full variant label, so the rows of one gene are its wild type and its variants." ] }, { "cell_type": "code", "execution_count": 3, "id": "20d7caf2", "metadata": { "execution": { "iopub.execute_input": "2026-10-21T01:00:24.538594Z", "iopub.status.busy": "2026-10-21T01:00:24.538431Z", "iopub.status.idle": "2026-10-21T01:00:24.549282Z", "shell.execute_reply": "2026-10-21T01:00:24.547784Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Metadata_GeneMetadata_AlleleMetadata_Perturbation
0ACTBACTBACTB
1ACTBACTB E364KACTB E364K
2ACTBACTB R183WACTB R183W
\n", "
" ], "text/plain": [ " Metadata_Gene Metadata_Allele Metadata_Perturbation\n", "0 ACTB ACTB ACTB\n", "1 ACTB ACTB E364K ACTB E364K\n", "2 ACTB ACTB R183W ACTB R183W" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "obs = adata.obs\n", "obs.loc[obs[\"Metadata_Gene\"] == \"ACTB\", [\"Metadata_Gene\", \"Metadata_Allele\", \"Metadata_Perturbation\"]]" ] }, { "cell_type": "markdown", "id": "010ac156", "metadata": {}, "source": [ "## Barcodes in profile space\n", "\n", "On the first two principal components each point is a barcode. Colouring the wild-type genes apart from the variant alleles shows how far a coding change moved the profile from its reference." ] }, { "cell_type": "code", "execution_count": 4, "id": "08ce884d", "metadata": { "execution": { "iopub.execute_input": "2026-10-21T01:00:24.551896Z", "iopub.status.busy": "2026-10-21T01:00:24.551744Z", "iopub.status.idle": "2026-10-21T01:00:25.219623Z", "shell.execute_reply": "2026-10-21T01:00:25.218208Z" } }, "outputs": [ { "data": { "text/html": [ " \n", " \n", " " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
\n", "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "scaled = adata.copy()\n", "sc.pp.scale(scaled)\n", "scaled.X = np.nan_to_num(scaled.X)\n", "sc.pp.pca(scaled, n_comps=10)\n", "coords = pd.DataFrame(scaled.obsm[\"X_pca\"][:, :2], columns=[\"PC1\", \"PC2\"])\n", "coords[\"allele\"] = adata.obs[\"Metadata_Allele\"].to_numpy()\n", "is_variant = adata.obs[\"Metadata_Allele\"].astype(str) != adata.obs[\"Metadata_Gene\"].astype(str)\n", "coords[\"kind\"] = np.where(is_variant.to_numpy(), \"variant\", \"wild type\")\n", "fig = px.scatter(\n", " coords,\n", " x=\"PC1\",\n", " y=\"PC2\",\n", " color=\"kind\",\n", " hover_name=\"allele\",\n", " title=\"Pooled rare variants in profile space\",\n", ")\n", "fig.show()" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "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.13.15" } }, "nbformat": 4, "nbformat_minor": 5 }