我们生信入门培训班有个学员问到能不能给他写个帖子分析一个空转的数据,那必须可以的!
进入AI后,感觉很多事情我都想偷懒,不想手搓代码了,于是我让AI来帮我完成这件事情。前面大家觉得我用codex的chatgpt去做mac配置和安装包太奢侈了,这次我先用deepseek看看。
数据情况
入门培训班了解见这里,有超级贴心的答疑以及课后实战训练:AI加持,全新改版!生信入门&数据挖掘线上直播课6月班
数据来自这篇2025年3月6号发表在 Cell Stem Cell 杂志上的文献,标题为《Spatiotemporal single-cell roadmap of human skin wound healing》。研究采集了同一批个体在受伤前的完整皮肤,以及伤后第1天(Wound1)、第7天(Wound7)和第30天(Wound30)的全层同心伤口边缘组织样本(图1A;表S1)。

其中,Visium ST-seq (N) 数据放到GEO上面,共有16个样本:
https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSE241124
GSM7717016 Donor4-Skin
GSM7717017 Donor4-Wound1
GSM7717018 Donor4-Wound7
GSM7717019 Donor4-Wound30
GSM8238462 Donor1-Skin
GSM8238463 Donor1-Wound1
GSM8238464 Donor1-Wound7
GSM8238465 Donor1-Wound30
GSM8238466 Donor2-Skin
GSM8238467 Donor2-Wound1
GSM8238468 Donor2-Wound7
GSM8238469 Donor2-Wound30
GSM8238470 Donor3-Skin
GSM8238471 Donor3-Wound1
GSM8238472 Donor3-Wound7
GSM8238473 Donor3-Wound30
可下载的文件:我其实可以用AI给我下载,但是我的网不好,
我用了技能树的专线去下载的,速度嘎嘎快!
GSE241124_RAW.tar 228.7 Mb (http)(custom) TAR (of H5, ZIP)
GSE241124_spatialseq_metadata_acutewound.txt.gz 331.6 Kb (ftp)(http) TXT
deepseek整理文件目录
GSE241124_RAW.tar 下载下来后,为了整理为可以使用 Load10x_Spatial 读取的格式,这里使用AI帮我完成这个简单的小任务。
这里使用aisdk 接入的deepseek进行的操作。方便在R里面使用,配置见:aisdk:在R console聊天,让AI干活!(活人版本教程)
在Rstudio中输入:
rm(list=ls())
library(aisdk)
packageVersion("aisdk")
ls("package:aisdk")
console_chat()
提示词如下:
使用getwd获取当前目录。
将解压 "data\GSE241124_RAW.tar" 包中的文件到 "data\GSE241124_RAW 目录",整理为空转 Load10x_Spatial 可以读取的格式。每个样本一个文件夹,里面有h5文件和spatial目录
感觉整理的不太对,因为每个样本的spatial目录下面还有一个spatial目录嵌套在:

我质疑了一下:
感觉整理的不太对呢?你检查一下

整理完后,他说有18个样本,这不是胡说八道吗?要不是我知道是16个样本就给他蒙混过去了!

我又质疑了一下:
应该是16个样本吧,为什么有18个呢?然后外面的spatial_images.zip文件请清除

这回看起来没有什么问题了。然后我让他把刚刚的执行过程写成一个R脚本。
我自己运行的时候,发现运行不通啊!!!
有点气人,不想跟他啰嗦了。
使用codex看看
在当前目录打开Windows终端,输入codex,我全程只用了一句话:
使用R语言,写一个代码,将解压 "data\GSE241124_RAW.tar" 包中的文件到 "data\GSE241124_RAW 目录",整理为空转 Load10x_Spatial 可以读取的格式。每个样本一个文件夹,里面有h5文件和spatial目录
自己第一轮写了个脚本:

自己开始第一轮检查,并优化:

自己第二轮检查又发现了一个问题:

修正后又做了一轮自检

这回发现没有问题了!
为什么codex的模型他会自己去好好检查呢,一个来回对话就能搞定任务?
deepseek 他自己不检查吗?
codex提供的脚本如下
codex的脚本分享给大家,配置可以有一点推荐,我的v联系 Biotree123 :
## Prepare GSE241124 RAW files for LoaX_Spatial / 10x Visium-style loading.
##
## Output layout:
## GSE241124_RAW/
## /
## filtered_feature_bc_matrix.h5
## spatial/
## ...
tar_file "data", "GSE241124_RAW.tar")
out_dir "data", "GSE241124_RAW")
if (!file.exists(tar_file) && file.exists("GSE241124_RAW.tar")) {
tar_file "GSE241124_RAW.tar"
out_dir "GSE241124_RAW"
}
if (!file.exists(tar_file)) {
stop("Cannot find tar file: ", normalizePath(tar_file, mustWork = FALSE))
}
dir.create(out_dir, recursive = TRUE, showWarnings = FALSE)
message("Extracting ", tar_file, " to ", out_dir)
utils::untar(tar_file, exdir = out_dir)
h5_files
out_dir,
pattern = "_filtered_feature_bc_matrix\\.h5$",
full.names = TRUE,
recursive = FALSE
)
zip_files
out_dir,
pattern = "_spatial_images\\.zip$",
full.names = TRUE,
recursive = FALSE
)
sample_from_h5 function(x) {
sub("_filtered_feature_bc_matrix\\.h5$", "", basename(x))
}
sample_from_zip function(x) {
sub("_spatial_images\\.zip$", "", basename(x))
}
zip_by_sample
if (length(h5_files) == 0) {
stop("No *_filtered_feature_bc_matrix.h5 files found under ", out_dir)
}
move_file function(from, to) {
if (normalizePath(from, mustWork = TRUE) == normalizePath(to, mustWork = FALSE)) {
return(invisible(TRUE))
}
if (file.exists(to)) {
file.remove(to)
}
ok
if (!ok) {
file.copy(from, to, overwrite = TRUE)
file.remove(from)
}
invisible(TRUE)
}
for (h5 in h5_files) {
sample_id
sample_dir
spatial_dir "spatial")
dir.create(spatial_dir, recursive = TRUE, showWarnings = FALSE)
h5_target "filtered_feature_bc_matrix.h5")
move_file(h5, h5_target)
zip
if (is.null(zip) || is.na(zip) || !file.exists(zip)) {
warning("No matching spatial zip found for sample: ", sample_id)
next
}
tmp_spatial "_spatial_"))
dir.create(tmp_spatial)
utils::unzip(zip, exdir = tmp_spatial)
spatial_source
repeat {
if (file.exists(file.path(spatial_source, "scalefactors_json.json"))) {
break
}
items
items "__MACOSX" & !grepl("^\\._", basename(items))]
dirs
files
if (length(dirs) == 1 && length(files) == 0) {
spatial_source dirs[[1]]
} else {
break
}
}
spatial_items
for (item in spatial_items) {
if (basename(item) == "__MACOSX" || grepl("^\\._", basename(item))) {
next
}
target
if (file.exists(target)) {
unlink(target, recursive = TRUE, force = TRUE)
}
ok
if (!ok) {
if (dir.exists(item)) {
dir.create(target, recursive = TRUE, showWarnings = FALSE)
file.copy(list.files(item, all.files = TRUE, no.. = TRUE, full.names = TRUE),
target, recursive = TRUE, overwrite = TRUE)
} else {
file.copy(item, target, overwrite = TRUE)
}
unlink(item, recursive = TRUE, force = TRUE)
}
}
unlink(tmp_spatial, recursive = TRUE, force = TRUE)
unlink(file.path(spatial_dir, "__MACOSX"), recursive = TRUE, force = TRUE)
unlink(list.files(spatial_dir, pattern = "^\\._", all.files = TRUE, full.names = TRUE),
recursive = TRUE, force = TRUE)
nested_spatial "spatial")
if (dir.exists(nested_spatial)) {
nested_items
for (item in nested_items) {
target
if (file.exists(target)) {
unlink(target, recursive = TRUE, force = TRUE)
}
ok
if (!ok) {
if (dir.exists(item)) {
dir.create(target, recursive = TRUE, showWarnings = FALSE)
file.copy(list.files(item, all.files = TRUE, no.. = TRUE, full.names = TRUE),
target, recursive = TRUE, overwrite = TRUE)
} else {
file.copy(item, target, overwrite = TRUE)
}
unlink(item, recursive = TRUE, force = TRUE)
}
}
unlink(nested_spatial, recursive = TRUE, force = TRUE)
}
file.remove(zip)
message("Prepared sample: ", sample_id)
}
message("Done. Prepared directories are under: ", normalizePath(out_dir, mustWork = TRUE))
今天分享到这~