From 4b10f4e9311468e26673714892984acf64080e85 Mon Sep 17 00:00:00 2001 From: Mark Keller <7525285+keller-mark@users.noreply.github.com> Date: Mon, 11 Dec 2023 16:09:50 -0500 Subject: [PATCH 1/3] Create mini dataset notebook --- docs/notebooks/create_mini_dataset.ipynb | 674 +++++++++++++++++++++++ 1 file changed, 674 insertions(+) create mode 100644 docs/notebooks/create_mini_dataset.ipynb diff --git a/docs/notebooks/create_mini_dataset.ipynb b/docs/notebooks/create_mini_dataset.ipynb new file mode 100644 index 00000000..07ca8147 --- /dev/null +++ b/docs/notebooks/create_mini_dataset.ipynb @@ -0,0 +1,674 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 192, + "id": "28eae108-fcaa-465d-9fd0-4fe0cffeafe1", + "metadata": {}, + "outputs": [], + "source": [ + "from anndata import AnnData\n", + "from mudata import MuData\n", + "import numpy as np\n", + "import pandas as pd\n", + "from skimage.draw import disk\n", + "from tifffile import imread\n", + "import scanpy as sc\n", + "from vitessce.data_utils import (\n", + " rgb_img_to_ome_tiff,\n", + " multiplex_img_to_ome_tiff,\n", + " optimize_adata,\n", + " VAR_CHUNK_SIZE,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 144, + "id": "ada13ec1-a7e4-4ee8-aff0-a6df2ce4c118", + "metadata": {}, + "outputs": [], + "source": [ + "img_arr = imread(\"/Users/mkeller/Downloads/exemplar-001.pyramid.ome.tif\")" + ] + }, + { + "cell_type": "code", + "execution_count": 145, + "id": "5903f357-0208-4651-bf8d-27e5acb72d6f", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(12, 3138, 2509)" + ] + }, + "execution_count": 145, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "img_arr.shape" + ] + }, + { + "cell_type": "code", + "execution_count": 146, + "id": "3104abce-d31a-4156-9272-4cd070153695", + "metadata": {}, + "outputs": [], + "source": [ + "bitmask_arr = imread(\"/Users/mkeller/Downloads/cellMask.pyramid.ome.tif\")" + ] + }, + { + "cell_type": "code", + "execution_count": 147, + "id": "7af584e4-6a68-4cc8-8ca1-b50ae26d237c", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(3138, 2509)" + ] + }, + "execution_count": 147, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "bitmask_arr.shape" + ] + }, + { + "cell_type": "code", + "execution_count": 148, + "id": "6070ce48-149e-4748-bb73-ef1fc383b4a6", + "metadata": {}, + "outputs": [], + "source": [ + "img_crop_arr = img_arr[0:4, 1000:1250, 1000:1250]" + ] + }, + { + "cell_type": "code", + "execution_count": 149, + "id": "566d5acd-d9fb-479e-ab74-3ae0d2e41e2d", + "metadata": {}, + "outputs": [], + "source": [ + "cells_bitmask_crop_arr = bitmask_arr[1000:1250, 1000:1250]" + ] + }, + { + "cell_type": "code", + "execution_count": 150, + "id": "267af046-78db-4371-9a1d-de43153b3a50", + "metadata": {}, + "outputs": [], + "source": [ + "multiplex_img_to_ome_tiff(img_crop_arr, [\"DNA\", \"FDX1\", \"CD1D\", \"CD357\"], \"/Users/mkeller/Downloads/exemplar-001.crop.ome.tif\", axes='CYX')" + ] + }, + { + "cell_type": "code", + "execution_count": 151, + "id": "44a5e826-0de7-4112-b45e-ec1683591e82", + "metadata": {}, + "outputs": [], + "source": [ + "shapes_bitmask_crop_arr = np.zeros((250, 250))\n", + "radius = 5\n", + "for i in range(16):\n", + " for j in range(16):\n", + " disk_center = (10 + i*15, 10 + j*15)\n", + " shapes_bitmask_crop_arr[disk(disk_center, radius)] = i*16+j+1 # add one (0 is reserved for the background)\n", + "\n", + "# Update the array axes so they are in CYX order to enable conversion to OME-TIFF.\n", + "shapes_bitmask_crop_arr = shapes_bitmask_crop_arr.transpose((1, 0)) # (y, x)" + ] + }, + { + "cell_type": "code", + "execution_count": 152, + "id": "e7784e4f-c848-49f5-98ce-82161967f129", + "metadata": {}, + "outputs": [], + "source": [ + "multichannel_bitmask_arr = np.stack((cells_bitmask_crop_arr, shapes_bitmask_crop_arr))" + ] + }, + { + "cell_type": "code", + "execution_count": 153, + "id": "b378aa50-f97c-4514-82b7-8118d0d2f5b1", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(2, 250, 250)" + ] + }, + "execution_count": 153, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "multichannel_bitmask_arr.shape" + ] + }, + { + "cell_type": "code", + "execution_count": 154, + "id": "37bdc627-c703-4e6a-bbf9-07a94042e6b2", + "metadata": {}, + "outputs": [], + "source": [ + "multiplex_img_to_ome_tiff(multichannel_bitmask_arr, [\"Cells\", \"Circles\"], \"/Users/mkeller/Downloads/exemplar-001.crop.segmentations.ome.tif\", axes='CYX')" + ] + }, + { + "cell_type": "code", + "execution_count": 155, + "id": "f2cb43d3-a017-4433-8267-f39052cea395", + "metadata": {}, + "outputs": [], + "source": [ + "cell_ids = np.unique(multichannel_bitmask_arr[0, :, :])[1:]" + ] + }, + { + "cell_type": "code", + "execution_count": 156, + "id": "4653bce1-e66f-4a87-873e-736fe9a0727b", + "metadata": {}, + "outputs": [], + "source": [ + "circle_ids = np.unique(multichannel_bitmask_arr[1, :, :])[1:]" + ] + }, + { + "cell_type": "code", + "execution_count": 157, + "id": "e3a7b75b-5352-434f-8232-8d2940b35edd", + "metadata": {}, + "outputs": [], + "source": [ + "cell_df = pd.DataFrame(index=cell_ids.astype(int), data=[], columns=[])" + ] + }, + { + "cell_type": "code", + "execution_count": 158, + "id": "f7723381-598b-4293-a7ff-7c8e136660e0", + "metadata": {}, + "outputs": [], + "source": [ + "circle_df = pd.DataFrame(index=circle_ids.astype(int), data=[], columns=[\"X\", \"Y\"])" + ] + }, + { + "cell_type": "code", + "execution_count": 159, + "id": "0b627f36-3114-43cd-bf18-9aa097ee1144", + "metadata": {}, + "outputs": [], + "source": [ + "for i in range(16):\n", + " for j in range(16):\n", + " c_x = 10 + i*15\n", + " c_y = 10 + j*15\n", + " c_index = int(i*16+j+1)\n", + " circle_df.at[c_index, \"X\"] = c_x\n", + " circle_df.at[c_index, \"Y\"] = c_y" + ] + }, + { + "cell_type": "code", + "execution_count": 160, + "id": "2e6a931a-1564-4091-b65e-42383648921e", + "metadata": {}, + "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", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
1006
1007
1011
1012
1018
...
2012
2016
2021
2023
2024
\n", + "

218 rows × 0 columns

\n", + "
" + ], + "text/plain": [ + "Empty DataFrame\n", + "Columns: []\n", + "Index: [1006, 1007, 1011, 1012, 1018, 1021, 1028, 1029, 1030, 1041, 1056, 1064, 1068, 1069, 1070, 1073, 1074, 1075, 1081, 1085, 1091, 1099, 1103, 1104, 1110, 1111, 1112, 1117, 1122, 1125, 1126, 1131, 1135, 1136, 1140, 1144, 1150, 1159, 1161, 1164, 1171, 1172, 1185, 1193, 1194, 1199, 1200, 1204, 1209, 1210, 1212, 1219, 1220, 1229, 1238, 1239, 1240, 1245, 1251, 1260, 1261, 1264, 1265, 1266, 1267, 1288, 1289, 1293, 1298, 1304, 1305, 1311, 1321, 1322, 1323, 1335, 1337, 1346, 1347, 1350, 1354, 1355, 1361, 1362, 1369, 1378, 1381, 1389, 1390, 1395, 1396, 1402, 1403, 1419, 1422, 1423, 1428, 1439, 1440, 1441, ...]\n", + "\n", + "[218 rows x 0 columns]" + ] + }, + "execution_count": 160, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "cell_df" + ] + }, + { + "cell_type": "code", + "execution_count": 161, + "id": "2adc9038-88af-4493-a592-4c9f19e976d8", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[ 0., 0., 0., ..., 1012., 1012., 1012.],\n", + " [ 0., 0., 0., ..., 1012., 1012., 1012.],\n", + " [ 0., 0., 0., ..., 1012., 1012., 1012.],\n", + " ...,\n", + " [ 0., 0., 0., ..., 0., 0., 0.],\n", + " [ 0., 0., 0., ..., 0., 0., 0.],\n", + " [ 0., 0., 0., ..., 0., 0., 0.]])" + ] + }, + "execution_count": 161, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "multichannel_bitmask_arr[0, :, :]" + ] + }, + { + "cell_type": "code", + "execution_count": 183, + "id": "ee3a3b6a-bb4d-4542-be61-5ea3595c53f1", + "metadata": {}, + "outputs": [], + "source": [ + "def get_centroid(bitmask_arr, obs_id):\n", + " matching_px = np.argwhere(bitmask_arr == obs_id)\n", + " count = matching_px.shape[0]\n", + " result = matching_px.sum(0) / count\n", + " return (result[0], result[1])" + ] + }, + { + "cell_type": "code", + "execution_count": 184, + "id": "70b77e9b-6715-4bbc-a09a-ba5e9226acc3", + "metadata": {}, + "outputs": [], + "source": [ + "def get_channel_value(bitmask_arr, img_arr, obs_id):\n", + " matching_px = (bitmask_arr == obs_id)\n", + " matching_img = img_arr[matching_px]\n", + " return matching_img.sum() / matching_px.sum()" + ] + }, + { + "cell_type": "code", + "execution_count": 185, + "id": "439d6e24-95c2-4050-8e4b-3eeb6c60a31b", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "60204.72093023256" + ] + }, + "execution_count": 185, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "get_channel_value(multichannel_bitmask_arr[0, :, :], img_crop_arr[0, :, :], 1011)" + ] + }, + { + "cell_type": "code", + "execution_count": 186, + "id": "3d2f4553-181f-4877-a656-247263e97689", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(1.55, 191.525)" + ] + }, + "execution_count": 186, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "get_centroid(multichannel_bitmask_arr[0, :, :], 1006)" + ] + }, + { + "cell_type": "code", + "execution_count": 187, + "id": "401454f4-e250-405d-bb15-bc6bc3104018", + "metadata": {}, + "outputs": [], + "source": [ + "var_df = pd.DataFrame(index=[\"DNA\", \"FDX1\", \"CD1D\", \"CD357\"], data=[], columns=[])" + ] + }, + { + "cell_type": "code", + "execution_count": 165, + "id": "12fa9835-5ba8-49a9-b245-555ea03c8223", + "metadata": {}, + "outputs": [], + "source": [ + "cell_df[\"X\"] = [get_centroid(multichannel_bitmask_arr[0, :, :], int(i))[0] for i in cell_df.index]\n", + "cell_df[\"Y\"] = [get_centroid(multichannel_bitmask_arr[0, :, :], int(i))[1] for i in cell_df.index]" + ] + }, + { + "cell_type": "code", + "execution_count": 166, + "id": "7ecae4d3-3eea-4594-b8d1-1c23578a70b1", + "metadata": {}, + "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", + " \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", + " \n", + " \n", + " \n", + " \n", + " \n", + "
XY
10061.550000191.525000
10071.930556212.305556
10113.23255848.581395
10121.363636248.090909
10180.578947156.631579
.........
2012247.225806194.161290
2016248.214286217.785714
2021248.857143161.285714
2023249.00000066.000000
2024249.000000205.000000
\n", + "

218 rows × 2 columns

\n", + "
" + ], + "text/plain": [ + " X Y\n", + "1006 1.550000 191.525000\n", + "1007 1.930556 212.305556\n", + "1011 3.232558 48.581395\n", + "1012 1.363636 248.090909\n", + "1018 0.578947 156.631579\n", + "... ... ...\n", + "2012 247.225806 194.161290\n", + "2016 248.214286 217.785714\n", + "2021 248.857143 161.285714\n", + "2023 249.000000 66.000000\n", + "2024 249.000000 205.000000\n", + "\n", + "[218 rows x 2 columns]" + ] + }, + "execution_count": 166, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "cell_df" + ] + }, + { + "cell_type": "code", + "execution_count": 189, + "id": "25d7ba6e-f452-4033-af74-7400a356bc7f", + "metadata": {}, + "outputs": [], + "source": [ + "cell_X = np.zeros((cell_df.shape[0], var_df.shape[0]))" + ] + }, + { + "cell_type": "code", + "execution_count": 190, + "id": "3a7e9751-562f-4bc7-854e-bb382ffff24c", + "metadata": {}, + "outputs": [], + "source": [ + "for c_index in range(4):\n", + " for i, cell_id in enumerate(cell_df.index):\n", + " cell_X[i, c_index] = get_channel_value(multichannel_bitmask_arr[0, :, :], img_crop_arr[c_index, :, :], cell_id)" + ] + }, + { + "cell_type": "code", + "execution_count": 193, + "id": "b8b21ea2-33d4-4756-a890-9b67fb40824a", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/mkeller/software/miniconda3/envs/vitessce-python-notebooks/lib/python3.9/site-packages/anndata/_core/anndata.py:183: ImplicitModificationWarning: Transforming to str index.\n", + " warnings.warn(\"Transforming to str index.\", ImplicitModificationWarning)\n" + ] + } + ], + "source": [ + "adata = AnnData(X=cell_X, obs=cell_df, var=var_df)" + ] + }, + { + "cell_type": "code", + "execution_count": 194, + "id": "a1ed5534-c301-4af9-9d28-df23483af4ab", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "AnnData object with n_obs × n_vars = 218 × 4\n", + " obs: 'X', 'Y'" + ] + }, + "execution_count": 194, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "adata" + ] + }, + { + "cell_type": "code", + "execution_count": 201, + "id": "a3950efb-38e9-4f78-802b-624d5fbbec66", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/mkeller/software/miniconda3/envs/vitessce-python-notebooks/lib/python3.9/site-packages/scanpy/plotting/_anndata.py:1068: FutureWarning: is_categorical_dtype is deprecated and will be removed in a future version. Use isinstance(dtype, CategoricalDtype) instead\n", + " if isinstance(groupby, str) and is_categorical_dtype(adata.obs[groupby]):\n" + ] + }, + { + "data": { + "image/png": "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pk2Dr68vunfvjtLSUuTn5+PTTz+Fh4cHHnvsMd7j4OQ++eQTIT106FDZh/GxY8fw1FNPKRGWW2rYsCHWrl2LPXv2ICEhAd27d4fJZFI6LKc2evRopKeno3nz5pg6daosb/369dedc4iqZtCgQVi1alWFjuxHH32EWbNm4X//+59CkbmXcePGVdqp1el0mDVrVi1HRI70zDPPID8/H+vXr4fVasWCBQvQtWtX3HXXXfi///s/ZGZmYuzYsUqHSTWMlw66MKvVirS0NGGepZYtW8LHx0fpsIhcksViwUcffYQ9e/bgs88+g7+/v9IhERGRQoKCgpCRkQEvLy8AQFFREVq3bo20tDScP38effv25X28boAdLRdmMpnw119/CZPkNWvWjJfduKCSkhJhhLsOHTpAr9crHBGRY5nNZthsNrZfDpaamlphItWIiAilw3JrrOuuIyoqCj/++COaNm0KALhw4QL69esnjArNQWfcA+/RckH5+fkYOXIkAgIC0LFjRwwcOBAdO3ZEYGAgEhMTeSO5k3v44YeF9KlTp9CqVSs899xzeP7559GyZUscP35cueDczLWhyMPDw+Hn54fw8HD06tULn332mdKhOS3p3DI5OTkYNGgQfHx8oNfrMWDAAFy9elXB6FxDSkoKYmNj0bp1a0yZMgULFy7ElClT0Lp1a8TFxSE1NVXpEN0C67pre/HFFxEbG4vp06dj2rRpePDBBzFhwgQAwNmzZ9GkSROFI6TawDNaLmjw4MHQ6/V4/fXX0axZM+H5v/76C7Nnz0ZhYSE2bNigYIR0O6SjCvbp0we9evXClClTAAALFy7Eli1bsGvXLiVDdAtTp07Fd999h5deegnt2rUT9svx48excOFCPPLII3j77beVDtPpSOv36NGjUVxcjA8//BAqlQovvvgitFotO7K36YEHHsB9992HmTNnyi4nLy4uxty5c3Ho0CHs2bNHuQDdBOu669u5c6cw0Xrv3r2FwcjKyspQWlqKoKAgJcOjWsCOlgvy8/PDlStXrjv6XElJCerXry8bMpmci/TDuUGDBkhJSYGnpyeA8stFw8PD+UtoLQgJCcHvv/+OBg0aVMjLzMzEnXfeiezsbAUic27Sy2kiIiJw/PhxBAcHAwByc3Nx5513Ij09XckQnZ5er0dOTo4w7YeU0WhEUFAQiouLFYjMvbCuE7k+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er1e6TCdjq+vL3Jzc+Hh4VEhz2g0IigoiJe33aZ169bhzTffxNNPP40JEyZAo9EAKJ/X6cSJExy5tJZIpzIoKirCN998gzVr1mDPnj3o2rUrhg8fjtGjRyscJRHdDt6jRUR0GwIDA/H0009j9+7d+PPPP/HQQw9h4cKFPLNVTe3bt8e7774Ls9kse95iseC9995D+/btFYrMdQwdOhSHDx9GZmYmOnTogJ07dyodktvT6/UYOXIkduzYgZSUFDz66KNYsmSJ0mER0W3iGS0iomq42cTQZ86cQZs2bWoxItfw119/YdiwYTh//jxatWol/Op/7tw5tGrVCmvWrEGzZs2UDtNlnD9/HpMmTYJOp8O+fftw7tw5ntGqJZxcnsj1ccJiIqJqmDFjxg3z2cmqnmbNmuHw4cM4f/48Tp8+jaKiIuj1erRt25aDjtSAli1bYuvWrdi8eTOaNWsGX19fpUNyG6dPn1Y6BCKqYTyjRURERERE5GC8R4uIqIo4R4oyTCYTevbsqXQYLo1lXDdwPxC5Bp7RIiKqopvNkbJv3z5s2rSJ85k5mMFggI+PDywWi9KhuCyWcd3A/UDkGtjRIiKqBs6RUjNuNGmr1WrFhQsX+OXzNrGM6wbuByLXx44WERHVGYGBgViwYAGaN29eIc9gMKBfv3788nmbWMZ1A/cDkevjqINERFRndOrUCRqNBrGxsRXyDAbDTe+No5tjGdcN3A9Ero9ntIiIqM44c+YMdDodWrRocd38ixcvokmTJrUclWthGdcN3A9Ero8dLSIiIiIiIgfj8O5ERFQncNj8mscyrhu4H4jcAztaRERUJxw4cACtW7fG1KlTsWXLFpw/fx7p6ek4d+4cNm/ejJdeegktW7bEzz//rHSoTotlXDdwPxC5B146SEREdQaHza95LOO6gfuByPWxo0VERERERORgvHSQiIiIiIjIwdjRIiIiIiIicjB2tIiIiIiIiByMHS0iIiIiIiIHY0eLiIiIiIjIwdjRIiKiOstisaBLly74xz/+IXs+Pz8fERERePXVVxWKjIiI6MY4vDsREdVpFy5cwN13342lS5ciISEBADBixAicOHECR48ehYeHh8IREhERVcSOFhER1XkffvghZs+ejd9++w1Hjx7F448/jiNHjuDuu+9WOjQiIqLrYkeLiIjqPJvNhp49e0Kj0eDUqVP45z//ycsGiYioTmNHi4iInMLZs2fRpk0bxMTE4Ndff4VWq1U6JCIiokpxMAwiInIKn376KXx8fJCUlIS0tDSlwyEiIrohntEiIqI679ChQ+jRowe2bduGd999FxaLBbt27YJKpVI6NCIiouviGS0iIqrTSktLMXLkSDzzzDPo1asXPvnkExw9ehRLlixROjQiIqJKsaNFRER12rRp02C1WvHOO+8AACIjIzF//nxMmTIFycnJygZHRERUCV46SEREddbevXvx4IMPYs+ePejWrZssr0+fPjCbzbyEkIiI6iR2tIiIiIiIiByMlw4SERERERE5GDtaREREREREDsaOFhERERERkYOxo0VERERERORg7GgRERERERE5GDtaREREREREDsaOFhERERERkYOxo0VERERERORg7GgRERERERE5GDtaREREREREDsaOFhERERERkYOxo0VERERERORg/w8Uh4AtIqKPZAAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "ax = sc.pl.heatmap(adata, var_names = var_df.index.tolist(), groupby=\"X\", standard_scale=\"var\", swap_axes=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "abb4c395-3102-4205-8cbf-e7796f6b866b", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.9.0" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} From 48467727d57cb74705f7cd0592f5125707411b06 Mon Sep 17 00:00:00 2001 From: Mark Keller <7525285+keller-mark@users.noreply.github.com> Date: Wed, 17 Jan 2024 19:32:51 -0500 Subject: [PATCH 2/3] Update --- docs/notebooks/create_mini_dataset.ipynb | 396 ++++++++++++++++++++--- pyproject.toml | 2 +- 2 files changed, 355 insertions(+), 43 deletions(-) diff --git a/docs/notebooks/create_mini_dataset.ipynb b/docs/notebooks/create_mini_dataset.ipynb index 07ca8147..bbe25aa7 100644 --- a/docs/notebooks/create_mini_dataset.ipynb +++ b/docs/notebooks/create_mini_dataset.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 192, + "execution_count": 1, "id": "28eae108-fcaa-465d-9fd0-4fe0cffeafe1", "metadata": {}, "outputs": [], @@ -17,6 +17,8 @@ "from vitessce.data_utils import (\n", " rgb_img_to_ome_tiff,\n", " multiplex_img_to_ome_tiff,\n", + " rgb_img_to_ome_zarr,\n", + " multiplex_img_to_ome_zarr,\n", " optimize_adata,\n", " VAR_CHUNK_SIZE,\n", ")" @@ -24,7 +26,7 @@ }, { "cell_type": "code", - "execution_count": 144, + "execution_count": 2, "id": "ada13ec1-a7e4-4ee8-aff0-a6df2ce4c118", "metadata": {}, "outputs": [], @@ -34,7 +36,7 @@ }, { "cell_type": "code", - "execution_count": 145, + "execution_count": 3, "id": "5903f357-0208-4651-bf8d-27e5acb72d6f", "metadata": {}, "outputs": [ @@ -44,7 +46,7 @@ "(12, 3138, 2509)" ] }, - "execution_count": 145, + "execution_count": 3, "metadata": {}, "output_type": "execute_result" } @@ -55,7 +57,7 @@ }, { "cell_type": "code", - "execution_count": 146, + "execution_count": 4, "id": "3104abce-d31a-4156-9272-4cd070153695", "metadata": {}, "outputs": [], @@ -65,7 +67,7 @@ }, { "cell_type": "code", - "execution_count": 147, + "execution_count": 5, "id": "7af584e4-6a68-4cc8-8ca1-b50ae26d237c", "metadata": {}, "outputs": [ @@ -75,7 +77,7 @@ "(3138, 2509)" ] }, - "execution_count": 147, + "execution_count": 5, "metadata": {}, "output_type": "execute_result" } @@ -86,7 +88,7 @@ }, { "cell_type": "code", - "execution_count": 148, + "execution_count": 6, "id": "6070ce48-149e-4748-bb73-ef1fc383b4a6", "metadata": {}, "outputs": [], @@ -96,7 +98,7 @@ }, { "cell_type": "code", - "execution_count": 149, + "execution_count": 7, "id": "566d5acd-d9fb-479e-ab74-3ae0d2e41e2d", "metadata": {}, "outputs": [], @@ -106,7 +108,7 @@ }, { "cell_type": "code", - "execution_count": 150, + "execution_count": 8, "id": "267af046-78db-4371-9a1d-de43153b3a50", "metadata": {}, "outputs": [], @@ -116,7 +118,17 @@ }, { "cell_type": "code", - "execution_count": 151, + "execution_count": 9, + "id": "2121fbae-6e05-4a22-826a-093a35bda15e", + "metadata": {}, + "outputs": [], + "source": [ + "multiplex_img_to_ome_zarr(img_crop_arr, [\"DNA\", \"FDX1\", \"CD1D\", \"CD357\"], \"/Users/mkeller/Downloads/exemplar-001.crop.image.ome.zarr\")" + ] + }, + { + "cell_type": "code", + "execution_count": 10, "id": "44a5e826-0de7-4112-b45e-ec1683591e82", "metadata": {}, "outputs": [], @@ -134,7 +146,7 @@ }, { "cell_type": "code", - "execution_count": 152, + "execution_count": 11, "id": "e7784e4f-c848-49f5-98ce-82161967f129", "metadata": {}, "outputs": [], @@ -144,7 +156,7 @@ }, { "cell_type": "code", - "execution_count": 153, + "execution_count": 12, "id": "b378aa50-f97c-4514-82b7-8118d0d2f5b1", "metadata": {}, "outputs": [ @@ -154,7 +166,7 @@ "(2, 250, 250)" ] }, - "execution_count": 153, + "execution_count": 12, "metadata": {}, "output_type": "execute_result" } @@ -165,7 +177,7 @@ }, { "cell_type": "code", - "execution_count": 154, + "execution_count": 13, "id": "37bdc627-c703-4e6a-bbf9-07a94042e6b2", "metadata": {}, "outputs": [], @@ -175,7 +187,17 @@ }, { "cell_type": "code", - "execution_count": 155, + "execution_count": 39, + "id": "1500fbd0-9ace-4f12-826b-753458f8c4cc", + "metadata": {}, + "outputs": [], + "source": [ + "multiplex_img_to_ome_zarr(multichannel_bitmask_arr, [\"cell\", \"circle\"], \"/Users/mkeller/Downloads/exemplar-001.crop.segmentations.ome.zarr\")" + ] + }, + { + "cell_type": "code", + "execution_count": 15, "id": "f2cb43d3-a017-4433-8267-f39052cea395", "metadata": {}, "outputs": [], @@ -185,7 +207,7 @@ }, { "cell_type": "code", - "execution_count": 156, + "execution_count": 16, "id": "4653bce1-e66f-4a87-873e-736fe9a0727b", "metadata": {}, "outputs": [], @@ -195,7 +217,7 @@ }, { "cell_type": "code", - "execution_count": 157, + "execution_count": 17, "id": "e3a7b75b-5352-434f-8232-8d2940b35edd", "metadata": {}, "outputs": [], @@ -205,7 +227,7 @@ }, { "cell_type": "code", - "execution_count": 158, + "execution_count": 18, "id": "f7723381-598b-4293-a7ff-7c8e136660e0", "metadata": {}, "outputs": [], @@ -215,7 +237,7 @@ }, { "cell_type": "code", - "execution_count": 159, + "execution_count": 19, "id": "0b627f36-3114-43cd-bf18-9aa097ee1144", "metadata": {}, "outputs": [], @@ -231,7 +253,7 @@ }, { "cell_type": "code", - "execution_count": 160, + "execution_count": 20, "id": "2e6a931a-1564-4091-b65e-42383648921e", "metadata": {}, "outputs": [ @@ -305,7 +327,7 @@ "[218 rows x 0 columns]" ] }, - "execution_count": 160, + "execution_count": 20, "metadata": {}, "output_type": "execute_result" } @@ -316,7 +338,7 @@ }, { "cell_type": "code", - "execution_count": 161, + "execution_count": 21, "id": "2adc9038-88af-4493-a592-4c9f19e976d8", "metadata": {}, "outputs": [ @@ -332,7 +354,7 @@ " [ 0., 0., 0., ..., 0., 0., 0.]])" ] }, - "execution_count": 161, + "execution_count": 21, "metadata": {}, "output_type": "execute_result" } @@ -343,7 +365,7 @@ }, { "cell_type": "code", - "execution_count": 183, + "execution_count": 22, "id": "ee3a3b6a-bb4d-4542-be61-5ea3595c53f1", "metadata": {}, "outputs": [], @@ -357,7 +379,7 @@ }, { "cell_type": "code", - "execution_count": 184, + "execution_count": 23, "id": "70b77e9b-6715-4bbc-a09a-ba5e9226acc3", "metadata": {}, "outputs": [], @@ -370,7 +392,7 @@ }, { "cell_type": "code", - "execution_count": 185, + "execution_count": 24, "id": "439d6e24-95c2-4050-8e4b-3eeb6c60a31b", "metadata": {}, "outputs": [ @@ -380,7 +402,7 @@ "60204.72093023256" ] }, - "execution_count": 185, + "execution_count": 24, "metadata": {}, "output_type": "execute_result" } @@ -391,7 +413,7 @@ }, { "cell_type": "code", - "execution_count": 186, + "execution_count": 25, "id": "3d2f4553-181f-4877-a656-247263e97689", "metadata": {}, "outputs": [ @@ -401,7 +423,7 @@ "(1.55, 191.525)" ] }, - "execution_count": 186, + "execution_count": 25, "metadata": {}, "output_type": "execute_result" } @@ -412,7 +434,7 @@ }, { "cell_type": "code", - "execution_count": 187, + "execution_count": 26, "id": "401454f4-e250-405d-bb15-bc6bc3104018", "metadata": {}, "outputs": [], @@ -422,7 +444,7 @@ }, { "cell_type": "code", - "execution_count": 165, + "execution_count": 27, "id": "12fa9835-5ba8-49a9-b245-555ea03c8223", "metadata": {}, "outputs": [], @@ -433,7 +455,7 @@ }, { "cell_type": "code", - "execution_count": 166, + "execution_count": 28, "id": "7ecae4d3-3eea-4594-b8d1-1c23578a70b1", "metadata": {}, "outputs": [ @@ -540,7 +562,7 @@ "[218 rows x 2 columns]" ] }, - "execution_count": 166, + "execution_count": 28, "metadata": {}, "output_type": "execute_result" } @@ -551,7 +573,7 @@ }, { "cell_type": "code", - "execution_count": 189, + "execution_count": 29, "id": "25d7ba6e-f452-4033-af74-7400a356bc7f", "metadata": {}, "outputs": [], @@ -561,7 +583,7 @@ }, { "cell_type": "code", - "execution_count": 190, + "execution_count": 30, "id": "3a7e9751-562f-4bc7-854e-bb382ffff24c", "metadata": {}, "outputs": [], @@ -573,7 +595,7 @@ }, { "cell_type": "code", - "execution_count": 193, + "execution_count": 31, "id": "b8b21ea2-33d4-4756-a890-9b67fb40824a", "metadata": {}, "outputs": [ @@ -581,7 +603,9 @@ "name": "stderr", "output_type": "stream", "text": [ - "/Users/mkeller/software/miniconda3/envs/vitessce-python-notebooks/lib/python3.9/site-packages/anndata/_core/anndata.py:183: ImplicitModificationWarning: Transforming to str index.\n", + "/var/folders/36/83j6x3ln225bvbpk1_vdzrm00000gn/T/ipykernel_15643/3333765654.py:1: FutureWarning: X.dtype being converted to np.float32 from float64. In the next version of anndata (0.9) conversion will not be automatic. Pass dtype explicitly to avoid this warning. Pass `AnnData(X, dtype=X.dtype, ...)` to get the future behavour.\n", + " adata = AnnData(X=cell_X, obs=cell_df, var=var_df)\n", + "/Users/mkeller/software/miniconda3/envs/vitessce-python-notebooks/lib/python3.9/site-packages/anndata/_core/anndata.py:121: ImplicitModificationWarning: Transforming to str index.\n", " warnings.warn(\"Transforming to str index.\", ImplicitModificationWarning)\n" ] } @@ -592,7 +616,7 @@ }, { "cell_type": "code", - "execution_count": 194, + "execution_count": 32, "id": "a1ed5534-c301-4af9-9d28-df23483af4ab", "metadata": {}, "outputs": [ @@ -603,7 +627,7 @@ " obs: 'X', 'Y'" ] }, - "execution_count": 194, + "execution_count": 32, "metadata": {}, "output_type": "execute_result" } @@ -614,7 +638,7 @@ }, { "cell_type": "code", - "execution_count": 201, + "execution_count": 33, "id": "a3950efb-38e9-4f78-802b-624d5fbbec66", "metadata": {}, "outputs": [ @@ -643,10 +667,298 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 34, "id": "abb4c395-3102-4205-8cbf-e7796f6b866b", "metadata": {}, "outputs": [], + "source": [ + "adata.write_zarr(\"/Users/mkeller/Downloads/exemplar-001.crop.cells.adata.zarr\")" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "id": "9c97045b-85a2-4ff8-bd62-4d777bbf4fd7", + "metadata": {}, + "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", + " \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", + " \n", + " \n", + " \n", + " \n", + " \n", + "
XY
11010
21025
31040
41055
51070
.........
252235175
253235190
254235205
255235220
256235235
\n", + "

256 rows × 2 columns

\n", + "
" + ], + "text/plain": [ + " X Y\n", + "1 10 10\n", + "2 10 25\n", + "3 10 40\n", + "4 10 55\n", + "5 10 70\n", + ".. ... ...\n", + "252 235 175\n", + "253 235 190\n", + "254 235 205\n", + "255 235 220\n", + "256 235 235\n", + "\n", + "[256 rows x 2 columns]" + ] + }, + "execution_count": 35, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "circle_df" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "id": "a0923acc-a263-48ac-8965-f77a536dce2a", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/mkeller/software/miniconda3/envs/vitessce-python-notebooks/lib/python3.9/site-packages/anndata/_core/anndata.py:121: ImplicitModificationWarning: Transforming to str index.\n", + " warnings.warn(\"Transforming to str index.\", ImplicitModificationWarning)\n", + "/Users/mkeller/software/miniconda3/envs/vitessce-python-notebooks/lib/python3.9/site-packages/anndata/_core/anndata.py:121: ImplicitModificationWarning: Transforming to str index.\n", + " warnings.warn(\"Transforming to str index.\", ImplicitModificationWarning)\n" + ] + } + ], + "source": [ + "circle_adata = AnnData(X=None, obs=circle_df, var=pd.DataFrame(data=[]))" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "id": "887679dc-a9a8-4a7e-8da2-a527634e5d01", + "metadata": {}, + "outputs": [], + "source": [ + "circle_adata.obs['X'] = circle_adata.obs['X'].astype(int)\n", + "circle_adata.obs['Y'] = circle_adata.obs['Y'].astype(int)" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "id": "be19ef76-27c3-42a8-89ca-326b1d835f66", + "metadata": {}, + "outputs": [], + "source": [ + "circle_adata.write_zarr(\"/Users/mkeller/Downloads/exemplar-001.crop.circles.adata.zarr\")" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "id": "d238ead4-890d-45ed-813c-f4a770ce01ec", + "metadata": {}, + "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", + " \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", + " \n", + " \n", + " \n", + " \n", + " \n", + "
XY
10061.550000191.525000
10071.930556212.305556
10113.23255848.581395
10121.363636248.090909
10180.578947156.631579
.........
2012247.225806194.161290
2016248.214286217.785714
2021248.857143161.285714
2023249.00000066.000000
2024249.000000205.000000
\n", + "

218 rows × 2 columns

\n", + "
" + ], + "text/plain": [ + " X Y\n", + "1006 1.550000 191.525000\n", + "1007 1.930556 212.305556\n", + "1011 3.232558 48.581395\n", + "1012 1.363636 248.090909\n", + "1018 0.578947 156.631579\n", + "... ... ...\n", + "2012 247.225806 194.161290\n", + "2016 248.214286 217.785714\n", + "2021 248.857143 161.285714\n", + "2023 249.000000 66.000000\n", + "2024 249.000000 205.000000\n", + "\n", + "[218 rows x 2 columns]" + ] + }, + "execution_count": 40, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "adata.obs" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "16eca51a-2c94-4091-9eae-9adf52bcd081", + "metadata": {}, + "outputs": [], "source": [] } ], diff --git a/pyproject.toml b/pyproject.toml index d9e9406c..ab4103cc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,7 +34,7 @@ dependencies = [ 'numpy>=1.21.2', 'anndata>=0.7.8,<0.9', 'scanpy>=1.9.3', - 'ome-zarr==0.2.1', + 'ome-zarr==0.8.3', 'tifffile>=2020.10.1', 'jsonschema>=3.2' ] From 6a2b45a0ec7ac8927e3b0ed4842c7bb7fb512de3 Mon Sep 17 00:00:00 2001 From: Mark Keller <7525285+keller-mark@users.noreply.github.com> Date: Mon, 22 Jan 2024 13:21:25 -0500 Subject: [PATCH 3/3] Mini dataset notebook --- docs/notebooks/create_mini_dataset.ipynb | 324 ++++++++++++++--------- 1 file changed, 204 insertions(+), 120 deletions(-) diff --git a/docs/notebooks/create_mini_dataset.ipynb b/docs/notebooks/create_mini_dataset.ipynb index bbe25aa7..6b45dc46 100644 --- a/docs/notebooks/create_mini_dataset.ipynb +++ b/docs/notebooks/create_mini_dataset.ipynb @@ -187,7 +187,7 @@ }, { "cell_type": "code", - "execution_count": 39, + "execution_count": 14, "id": "1500fbd0-9ace-4f12-826b-753458f8c4cc", "metadata": {}, "outputs": [], @@ -603,7 +603,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "/var/folders/36/83j6x3ln225bvbpk1_vdzrm00000gn/T/ipykernel_15643/3333765654.py:1: FutureWarning: X.dtype being converted to np.float32 from float64. In the next version of anndata (0.9) conversion will not be automatic. Pass dtype explicitly to avoid this warning. Pass `AnnData(X, dtype=X.dtype, ...)` to get the future behavour.\n", + "/var/folders/36/83j6x3ln225bvbpk1_vdzrm00000gn/T/ipykernel_75334/3333765654.py:1: FutureWarning: X.dtype being converted to np.float32 from float64. In the next version of anndata (0.9) conversion will not be automatic. Pass dtype explicitly to avoid this warning. Pass `AnnData(X, dtype=X.dtype, ...)` to get the future behavour.\n", " adata = AnnData(X=cell_X, obs=cell_df, var=var_df)\n", "/Users/mkeller/software/miniconda3/envs/vitessce-python-notebooks/lib/python3.9/site-packages/anndata/_core/anndata.py:121: ImplicitModificationWarning: Transforming to str index.\n", " warnings.warn(\"Transforming to str index.\", ImplicitModificationWarning)\n" @@ -636,6 +636,208 @@ "adata" ] }, + { + "cell_type": "code", + "execution_count": 46, + "id": "37f46887-2f03-4dee-a5e1-9607ee8da2b8", + "metadata": {}, + "outputs": [], + "source": [ + "cell_types = [\n", + " [\"Astrocyte\", \"Astrocyte Gfap\"],\n", + " [\"Astrocyte\", \"Astrocyte Mfge8\"],\n", + " [\"Brain immune\", \"Microglia\"],\n", + " [\"Brain immune\", \"Perivascular Macrophage\"],\n", + " [\"Excitatory neurons\", \"Hippocampus\"]\n", + "]\n", + "leiden_clusters = [1, 2, 3, 4, 5, 6, 7, 8, 9]\n", + "\n", + "adata.obs[\"cell_type_i\"] = [ i % len(cell_types) for i in range(adata.obs.shape[0])]\n", + "adata.obs[\"cell_type_coarse\"] = adata.obs[\"cell_type_i\"].apply(lambda i: cell_types[i][0])\n", + "adata.obs[\"cell_type_fine\"] = adata.obs[\"cell_type_i\"].apply(lambda i: cell_types[i][1])\n", + "adata.obs[\"leiden_cluster\"] = [ leiden_clusters[i % len(leiden_clusters)] for i in range(adata.obs.shape[0])]\n", + "adata.obs[\"leiden_cluster_str\"] = [ f\"Cluster {leiden_clusters[i % len(leiden_clusters)] for i in range(adata.obs.shape[0])]" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "id": "da20e8cc-8396-48a6-938e-a643f7680a3b", + "metadata": {}, + "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", + " \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", + " \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", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
XYcell_type_icell_type_coarsecell_type_fineleiden_cluster
10061.550000191.5250000AstrocyteAstrocyte Gfap1
10071.930556212.3055561AstrocyteAstrocyte Mfge82
10113.23255848.5813952Brain immuneMicroglia3
10121.363636248.0909093Brain immunePerivascular Macrophage4
10180.578947156.6315794Excitatory neuronsHippocampus5
.....................
2012247.225806194.1612903Brain immunePerivascular Macrophage7
2016248.214286217.7857144Excitatory neuronsHippocampus8
2021248.857143161.2857140AstrocyteAstrocyte Gfap9
2023249.00000066.0000001AstrocyteAstrocyte Mfge81
2024249.000000205.0000002Brain immuneMicroglia2
\n", + "

218 rows × 6 columns

\n", + "
" + ], + "text/plain": [ + " X Y cell_type_i cell_type_coarse \\\n", + "1006 1.550000 191.525000 0 Astrocyte \n", + "1007 1.930556 212.305556 1 Astrocyte \n", + "1011 3.232558 48.581395 2 Brain immune \n", + "1012 1.363636 248.090909 3 Brain immune \n", + "1018 0.578947 156.631579 4 Excitatory neurons \n", + "... ... ... ... ... \n", + "2012 247.225806 194.161290 3 Brain immune \n", + "2016 248.214286 217.785714 4 Excitatory neurons \n", + "2021 248.857143 161.285714 0 Astrocyte \n", + "2023 249.000000 66.000000 1 Astrocyte \n", + "2024 249.000000 205.000000 2 Brain immune \n", + "\n", + " cell_type_fine leiden_cluster \n", + "1006 Astrocyte Gfap 1 \n", + "1007 Astrocyte Mfge8 2 \n", + "1011 Microglia 3 \n", + "1012 Perivascular Macrophage 4 \n", + "1018 Hippocampus 5 \n", + "... ... ... \n", + "2012 Perivascular Macrophage 7 \n", + "2016 Hippocampus 8 \n", + "2021 Astrocyte Gfap 9 \n", + "2023 Astrocyte Mfge8 1 \n", + "2024 Microglia 2 \n", + "\n", + "[218 rows x 6 columns]" + ] + }, + "execution_count": 47, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "adata.obs" + ] + }, { "cell_type": "code", "execution_count": 33, @@ -835,124 +1037,6 @@ "circle_adata.write_zarr(\"/Users/mkeller/Downloads/exemplar-001.crop.circles.adata.zarr\")" ] }, - { - "cell_type": "code", - "execution_count": 40, - "id": "d238ead4-890d-45ed-813c-f4a770ce01ec", - "metadata": {}, - "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", - " \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", - " \n", - " \n", - " \n", - " \n", - " \n", - "
XY
10061.550000191.525000
10071.930556212.305556
10113.23255848.581395
10121.363636248.090909
10180.578947156.631579
.........
2012247.225806194.161290
2016248.214286217.785714
2021248.857143161.285714
2023249.00000066.000000
2024249.000000205.000000
\n", - "

218 rows × 2 columns

\n", - "
" - ], - "text/plain": [ - " X Y\n", - "1006 1.550000 191.525000\n", - "1007 1.930556 212.305556\n", - "1011 3.232558 48.581395\n", - "1012 1.363636 248.090909\n", - "1018 0.578947 156.631579\n", - "... ... ...\n", - "2012 247.225806 194.161290\n", - "2016 248.214286 217.785714\n", - "2021 248.857143 161.285714\n", - "2023 249.000000 66.000000\n", - "2024 249.000000 205.000000\n", - "\n", - "[218 rows x 2 columns]" - ] - }, - "execution_count": 40, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "adata.obs" - ] - }, { "cell_type": "code", "execution_count": null,