{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "0466a4b0",
   "metadata": {},
   "source": [
    "---\n",
    "title: 空间转录组数据处理：SeekSpace 拼片样本拆分方法\n",
    "author: SeekGene\n",
    "date: 2026-01-29\n",
    "tags:\n",
    "  - 空间转录组\n",
    "  - 分析指南\n",
    "  - Notebooks\n",
    "  - 基础分析\n",
    "---\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f7420f61-9683-4d00-a8fe-950c5ab5f476",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-09-02T05:30:12.711589Z",
     "iopub.status.busy": "2025-09-02T05:30:12.710353Z",
     "iopub.status.idle": "2025-09-02T05:30:12.722231Z",
     "shell.execute_reply": "2025-09-02T05:30:12.720942Z"
    },
    "tags": []
   },
   "source": [
    "# 空间转录组数据处理：SeekSpace 拼片样本拆分方法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "8ddecc6e-b80f-4db8-ad9a-898fa2f114d9",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-09-02T05:35:09.064999Z",
     "iopub.status.busy": "2025-09-02T05:35:09.063418Z",
     "iopub.status.idle": "2025-09-02T05:35:09.080418Z",
     "shell.execute_reply": "2025-09-02T05:35:09.079150Z"
    },
    "vscode": {
     "languageId": "r"
    }
   },
   "outputs": [],
   "source": [
    "library(Seurat)\n",
    "library(tidyverse)\n",
    "library(Matrix)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "080bd283-898b-4638-bb4f-a8cf4551659c",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-09-02T05:35:11.059118Z",
     "iopub.status.busy": "2025-09-02T05:35:11.057899Z",
     "iopub.status.idle": "2025-09-02T05:35:11.068597Z",
     "shell.execute_reply": "2025-09-02T05:35:11.067321Z"
    },
    "vscode": {
     "languageId": "r"
    }
   },
   "outputs": [],
   "source": [
    "#base64转png图函数\n",
    "Base64ToPng <- function(obj, width_px = 1000) {\n",
    "  for (i in seq_along(obj@misc$info)) {\n",
    "    for (j in c(\"img\", \"img_he\")) {\n",
    "      val <- obj@misc$info[[i]][[j]]\n",
    "      if (is.null(val) || is.na(val)) next\n",
    "\n",
    "      b64 <- stringr::str_remove(val, '^data:[^;]*;base64,')\n",
    "      img_raw <- base64enc::base64decode(b64)\n",
    "\n",
    "      grob <- magick::image_read(img_raw) %>%\n",
    "        magick::image_resize(sprintf(\"%d>\", width_px)) %>%\n",
    "        grid::rasterGrob(x = 0, y = 0,\n",
    "                         width = grid::unit(1, \"npc\"), height = grid::unit(1, \"npc\"),\n",
    "                         just = c(0, 0), interpolate = TRUE)\n",
    "\n",
    "      key <- if (j == \"img\") \"img_gg\" else \"img_he_gg\"\n",
    "      obj@misc$info[[i]][[key]] <<- grob\n",
    "    }\n",
    "  }\n",
    "  invisible(obj)\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "1ba06bff-6cbb-430f-a2df-568e2e5c153a",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-09-02T05:35:11.653331Z",
     "iopub.status.busy": "2025-09-02T05:35:11.652047Z",
     "iopub.status.idle": "2025-09-02T05:35:24.855441Z",
     "shell.execute_reply": "2025-09-02T05:35:24.853189Z"
    },
    "tags": [],
    "vscode": {
     "languageId": "r"
    }
   },
   "outputs": [],
   "source": [
    "obj <- readRDS(object)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "85496acb-5f5f-4c6e-adae-98d6220b691e",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-09-02T05:35:24.859999Z",
     "iopub.status.busy": "2025-09-02T05:35:24.858407Z",
     "iopub.status.idle": "2025-09-02T05:35:32.583633Z",
     "shell.execute_reply": "2025-09-02T05:35:32.582163Z"
    },
    "vscode": {
     "languageId": "r"
    }
   },
   "outputs": [],
   "source": [
    "# 将base64转成PNG图\n",
    "Base64ToPng(obj)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "58b07d46-df92-4db4-b38e-1e2513282827",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-09-02T05:35:32.587008Z",
     "iopub.status.busy": "2025-09-02T05:35:32.585962Z",
     "iopub.status.idle": "2025-09-02T05:35:33.328442Z",
     "shell.execute_reply": "2025-09-02T05:35:33.326963Z"
    },
    "tags": [],
    "vscode": {
     "languageId": "r"
    }
   },
   "outputs": [],
   "source": [
    "meta <- read.table(metadata,sep = '\\t',header = T, row.names = 1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "690ed978-c542-45f9-947e-b06fe4db4233",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-09-02T05:35:33.331343Z",
     "iopub.status.busy": "2025-09-02T05:35:33.330333Z",
     "iopub.status.idle": "2025-09-02T05:35:33.378085Z",
     "shell.execute_reply": "2025-09-02T05:35:33.376710Z"
    },
    "tags": [],
    "vscode": {
     "languageId": "r"
    }
   },
   "outputs": [],
   "source": [
    "obj <- AddMetaData(obj, meta)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "67d9c32b-5da6-4d99-821c-9e16b3b4ed76",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-09-02T05:35:33.381008Z",
     "iopub.status.busy": "2025-09-02T05:35:33.380022Z",
     "iopub.status.idle": "2025-09-02T05:37:15.930958Z",
     "shell.execute_reply": "2025-09-02T05:37:15.929495Z"
    },
    "tags": [],
    "vscode": {
     "languageId": "r"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Warning message in dir.create(paste0(i, \"_filtered_feature_bc_matrix\")):\n",
      "“'KO_57_filtered_feature_bc_matrix' already exists”\n",
      "Warning message in dir.create(paste0(i, \"_filtered_feature_bc_matrix\")):\n",
      "“'KO_13_filtered_feature_bc_matrix' already exists”\n"
     ]
    }
   ],
   "source": [
    "for (i in unique(obj@meta.data$Sample)){\n",
    "dir.create(paste0(i,'_filtered_feature_bc_matrix'))\n",
    "\n",
    "obj1 <- subset(obj, subset=Sample==i)\n",
    "names(obj1@misc$info) <- i\n",
    "\n",
    "data <- Embeddings(obj1, reduction = 'spatial') %>% as.data.frame()\n",
    "colnames(data) <- c(\"X\",\"Y\")\n",
    "data <-rownames_to_column(data, 'Barcode')\n",
    "write_delim(data, paste0(i,'_filtered_feature_bc_matrix/cell_locations.tsv'), delim = '\\t')\n",
    "\n",
    "writeMM(obj1@assays$RNA@counts, file = paste0(i,'_filtered_feature_bc_matrix/matrix.mtx'))\n",
    "data.frame(GeneID = rownames(obj1), Gene = rownames(obj1)) %>%\n",
    "write.table(paste0(i,'_filtered_feature_bc_matrix/genes.tsv'), row.names = F, col.names = F, sep = '\\t', quote = F)\n",
    "data.frame(Barcode = colnames(obj1)) %>%\n",
    "write.table(paste0(i,'_filtered_feature_bc_matrix/barcodes.tsv'), row.names = F, col.names = F, sep = '\\t', quote = F)\n",
    "\n",
    "saveRDS(obj1, paste0(i, \".rds\"))\n",
    "    }"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a2f388a7-1db6-4706-a7ce-415df262fbc1",
   "metadata": {
    "vscode": {
     "languageId": "r"
    }
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "R",
   "language": "R",
   "name": "ir"
  },
  "language_info": {
   "codemirror_mode": "r",
   "file_extension": ".r",
   "mimetype": "text/x-r-source",
   "name": "R",
   "pygments_lexer": "r",
   "version": "4.4.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
