{
"cells": [
{
"cell_type": "markdown",
"id": "3c6fb7a4",
"metadata": {},
"source": [
"# Kinase inhibitors over a dose range\n",
"\n",
"{func}`~mantispy.ds.pki` serves `cpg0008-pki` from the Cell Painting Gallery {cite:p}`Weisbart_2024`, a collaboration between the Broad Institute and the Gray lab that profiles selective protein kinase inhibitors. Fifteen kinase inhibitors were run over a seven-point dose range, eleven of them at three doses and four at a single dose, across eight plates in four cell lines, two plates each: PATU-8988T, MDA-MB-231, U2OS and A549. Every plate carries the same plate map, so a treatment's 32 to 64 replicate wells span all four lines, 8 to 16 in each. `Metadata_CellLine` records the line of each well. The object is well-level.\n",
"\n",
"The four lines differ biologically, so a treatment's wells in two lines are not interchangeable replicates. Subset or group by `Metadata_CellLine` before counting replicates or scoring reproducibility. The tutorials that use `pki` pool the four lines, and say so where it matters.\n",
"\n",
"The design spends wells on replicates rather than on a full concentration ladder, so it is the workhorse compound screen here for hit calling and normalization, not for curve fitting. For a screen laid out the other way, many concentrations per compound for fitting a concentration-response curve, see [OASIS pilot](oasis_pilot.ipynb).\n",
"\n",
"**Use it if** your own data is a compound screen with many replicate wells per treatment and you want to call hits, normalize against controls or check for plate artifacts. [Hits, effects and cell loss](../tutorials/compounds/hits.ipynb), [Normalize, select, aggregate](../tutorials/profiles/normalize_and_select.ipynb) and [Plate artifacts and corrections](../tutorials/profiles/artifacts.ipynb) all run on it."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "22aac5cb",
"metadata": {
"execution": {
"iopub.execute_input": "2026-10-31T22:15:07.397147Z",
"iopub.status.busy": "2026-10-31T22:15:07.396741Z",
"iopub.status.idle": "2026-10-31T22:15:16.499873Z",
"shell.execute_reply": "2026-10-31T22:15:16.498222Z"
}
},
"outputs": [],
"source": [
"import pandas as pd\n",
"\n",
"import mantispy as mt"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "52bbe2fa",
"metadata": {
"execution": {
"iopub.execute_input": "2026-10-31T22:15:16.503216Z",
"iopub.status.busy": "2026-10-31T22:15:16.502724Z",
"iopub.status.idle": "2026-10-31T22:15:18.502109Z",
"shell.execute_reply": "2026-10-31T22:15:18.500710Z"
}
},
"outputs": [
{
"data": {
"text/plain": [
"AnnData object with n_obs × n_vars = 3072 × 5839\n",
" obs: 'Metadata_plate_map_name', 'Metadata_broad_sample', 'Metadata_mg_per_ml', 'Metadata_mmoles_per_liter', 'Metadata_solvent', 'Metadata_Plate', 'Metadata_Well', 'Metadata_Site_Count', 'Metadata_Count_Cells', 'Metadata_Count_CellsIncludingEdges', 'Metadata_Count_Cytoplasm', 'Metadata_Count_Nuclei', 'Metadata_Count_NucleiIncludingEdges', 'Metadata_Object_Count', 'Metadata_Barcode', 'Metadata_Supplier', 'Metadata_Supplier_Catalog', 'Metadata_pert_type', 'Metadata_control_type', 'Metadata_Row', 'Metadata_Col', 'Metadata_CellCount', 'Metadata_SiteCount', 'Metadata_Control_Type', 'Metadata_Control', 'Metadata_Compound', 'Metadata_Concentration', 'Metadata_ConcentrationUnit', 'Metadata_MOA', 'Metadata_Perturbation', 'Metadata_Perturbation_Type', 'Metadata_CellLine'\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.pki()\n",
"adata"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "7d1c0e42",
"metadata": {
"execution": {
"iopub.execute_input": "2026-10-31T22:15:18.505272Z",
"iopub.status.busy": "2026-10-31T22:15:18.504841Z",
"iopub.status.idle": "2026-10-31T22:15:18.871546Z",
"shell.execute_reply": "2026-10-31T22:15:18.870385Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
" \n",
" | Metadata_CellLine | \n",
" A549 | \n",
" MDA-MB-231 | \n",
" PATU-8988T | \n",
" U2OS | \n",
"
\n",
" \n",
" | Metadata_Plate | \n",
" | \n",
" | \n",
" | \n",
" | \n",
"
\n",
" \n",
" \n",
" \n",
" | BR00122970 | \n",
" 0 | \n",
" 0 | \n",
" 384 | \n",
" 0 | \n",
"
\n",
" \n",
" | BR00122971 | \n",
" 0 | \n",
" 0 | \n",
" 384 | \n",
" 0 | \n",
"
\n",
" \n",
" | BR00122972 | \n",
" 0 | \n",
" 384 | \n",
" 0 | \n",
" 0 | \n",
"
\n",
" \n",
" | BR00122973 | \n",
" 0 | \n",
" 384 | \n",
" 0 | \n",
" 0 | \n",
"
\n",
" \n",
" | BR00122974 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 384 | \n",
"
\n",
" \n",
" | BR00122975 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 384 | \n",
"
\n",
" \n",
" | BR00122977 | \n",
" 384 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
"
\n",
" \n",
" | BR00122978 | \n",
" 384 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
"Metadata_CellLine A549 MDA-MB-231 PATU-8988T U2OS\n",
"Metadata_Plate \n",
"BR00122970 0 0 384 0\n",
"BR00122971 0 0 384 0\n",
"BR00122972 0 384 0 0\n",
"BR00122973 0 384 0 0\n",
"BR00122974 0 0 0 384\n",
"BR00122975 0 0 0 384\n",
"BR00122977 384 0 0 0\n",
"BR00122978 384 0 0 0"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pd.crosstab(adata.obs[\"Metadata_Plate\"], adata.obs[\"Metadata_CellLine\"])"
]
},
{
"cell_type": "markdown",
"id": "8eef7215",
"metadata": {},
"source": [
"## The dose design\n",
"\n",
"`Metadata_Compound` names the compound and `Metadata_Concentration` is the platemap's `mmoles_per_liter` (millimolar). The values reach 2 mM, high for a final in-well dose, so this is most likely the source concentration; the final dose is not recorded upstream. Counting wells per compound and dose shows the ladder each treatment was run on. `Metadata_Control_Type` is `negcon` for the DMSO wells and `poscon` for the four positive-control compounds, and `Metadata_Control` is `True` for both (schema 2.0). Normalize with `reference=\"negcon\"`, and select the non-DMSO wells with `Metadata_Control_Type != \"negcon\"`."
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "649d7539",
"metadata": {
"execution": {
"iopub.execute_input": "2026-10-31T22:15:18.874253Z",
"iopub.status.busy": "2026-10-31T22:15:18.873819Z",
"iopub.status.idle": "2026-10-31T22:15:18.999768Z",
"shell.execute_reply": "2026-10-31T22:15:18.998340Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | Metadata_Concentration | \n",
" 0.004 | \n",
" 0.010 | \n",
" 0.040 | \n",
" 0.200 | \n",
" 0.400 | \n",
" 1.000 | \n",
" 2.000 | \n",
"
\n",
" \n",
" | Metadata_Compound | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
"
\n",
" \n",
" \n",
" \n",
" | BRD-K15179513-001-03-4 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 32 | \n",
"
\n",
" \n",
" | BRD-K15819326-001-01-6 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 32 | \n",
"
\n",
" \n",
" | BRD-K40109029-001-06-9 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 32 | \n",
"
\n",
" \n",
" | BRD-K95785537-001-26-9 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 32 | \n",
"
\n",
" \n",
" | BRD-U00086672-001-01-9 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 64 | \n",
" 64 | \n",
" 64 | \n",
" 0 | \n",
"
\n",
" \n",
" | BRD-U00086673-001-01-9 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 64 | \n",
" 64 | \n",
" 64 | \n",
" 0 | \n",
"
\n",
" \n",
" | BRD-U00086674-001-01-9 | \n",
" 0 | \n",
" 0 | \n",
" 64 | \n",
" 64 | \n",
" 64 | \n",
" 0 | \n",
" 0 | \n",
"
\n",
" \n",
" | BRD-U00086675-001-01-9 | \n",
" 0 | \n",
" 0 | \n",
" 64 | \n",
" 64 | \n",
" 64 | \n",
" 0 | \n",
" 0 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
"Metadata_Concentration 0.004 0.010 0.040 0.200 0.400 1.000 2.000\n",
"Metadata_Compound \n",
"BRD-K15179513-001-03-4 0 0 0 0 0 0 32\n",
"BRD-K15819326-001-01-6 0 0 0 0 0 0 32\n",
"BRD-K40109029-001-06-9 0 0 0 0 0 0 32\n",
"BRD-K95785537-001-26-9 0 0 0 0 0 0 32\n",
"BRD-U00086672-001-01-9 0 0 0 64 64 64 0\n",
"BRD-U00086673-001-01-9 0 0 0 64 64 64 0\n",
"BRD-U00086674-001-01-9 0 0 64 64 64 0 0\n",
"BRD-U00086675-001-01-9 0 0 64 64 64 0 0"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"obs = adata.obs\n",
"design = pd.crosstab(obs[\"Metadata_Compound\"], obs[\"Metadata_Concentration\"])\n",
"design.iloc[:8]"
]
},
{
"cell_type": "markdown",
"id": "6ddd0ff4",
"metadata": {},
"source": [
"## Cells thin out as the dose rises\n",
"\n",
"Reading cells per well against concentration already shows the cytotoxic arm of the dose response, before any profile distance is computed: the highest doses leave fewer cells than DMSO."
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "0a525d3d",
"metadata": {
"execution": {
"iopub.execute_input": "2026-10-31T22:15:19.002248Z",
"iopub.status.busy": "2026-10-31T22:15:19.002016Z",
"iopub.status.idle": "2026-10-31T22:15:32.125940Z",
"shell.execute_reply": "2026-10-31T22:15:32.124674Z"
}
},
"outputs": [
{
"data": {
"text/html": [
" \n",
" \n",
" "
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"mt.pl.cell_counts(adata, groupby=\"Metadata_Concentration\")"
]
}
],
"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
}