直接让claude code帮我复现单细胞文章
一、写在前面
1、玩一下Claude Code
Claude Code是Anthropic推出的终端AI编程助手(Coding Agent)。它既不是聊天机器人,也不是只提示下一行代码的编辑器插件(AI无缝接入Rstudio≈言出法随),而是一个能够独立理解、规划、执行并验证任务的自主编程代理。只需要给它一个目标/指令,它就能在自己专属的代理循环(Agentic Loop)中自动完成规划、编写、执行和验证,全程无需人工复制粘贴或切换窗口。
例如,本教程我将给它一句话指令,直接让它帮我分析一个数据集:“我希望复现GSE163973数据集对应来源文章的全部单细胞分析相关内容,请在本地运行并给我输出图表和代码”。最终,我得到了以下分析图片:
![[图片]](https://i-blog.csdnimg.cn/img_convert/df9d9e377c70f1dc4f04cde3d4b500bc.jpeg)
这个数据集我们也曾人工复现过:
代码复现| scRNA-seq揭示人纤维化皮肤病中的成纤维细胞异质性与增殖
![[图片]](https://i-blog.csdnimg.cn/img_convert/87b965d4b310220f9e0c547fe73431c7.jpeg)
2、聊聊感受
实际使用下来,觉得Claude交互有点太多了。虽然我尽量用一句话描述了我的目的,但是启动流程、下载文件、创建脚本、创建文件夹、甚至解压已经下载的文件都需要和你交互确认。所以前前后后我在Claude Code的代码框里花了七个小时。按照这个模式来,一个懂代码的人,通过与语言大模型的交互,自行输入代码运行,分析进度会比这快很多。但对于不会写代码的人而言,Claude Code可就是跨越阶级的工具了,毕竟在你不会代码的情况下,直接花七个小时分析一篇文章,这事放在五年前属于会法术。并且,这一整套流程下来,不算服务器的成本,只需要花8¥。
关于输出的图片,我也与原文进行了对比。画风和配色基本一致,细胞也能够正常注释,并通过亚群分析一定程度上重现原文对于纤维化的评估。当然也有缺陷,首先原文有大量的分析图表,Claude Code只输出了一部分,并且并不能做到1:1完美复现,例如上文的气泡图,原本应该是一张stack小提琴图。
如果需要Claude Code在服务器中代为部署,也欢迎联系客服[Biomamba_zhushou]聊聊
二、配置并使用Claude Code
1、获取tocken
如果你可以科学上网并拥有一个Gmail,那你可以直接从官网注册:
https://claude.com
![[图片]](https://i-blog.csdnimg.cn/img_convert/fe3be2dbbbf9e6073c9f81c9d0bdf240.png)
如果你和我一样因为是新账户被claude拒绝了,可以试一下代理:
https://api.aigc.bar/register?aff=JSu9
注册,登录
![[图片]](https://i-blog.csdnimg.cn/img_convert/f2983f07aad9a5044377075a5619db17.png)
选好令牌模型,这里我选的是Claude-code,大家也可以试试其它模型好不好用。
![[图片]](https://i-blog.csdnimg.cn/img_convert/8c53e239245ac6609cda17a77c713e22.png)
接下来需要在自己的钱包管理中充值额度,这样API才能够正确调用,与Claude code交互是需要消耗tocken的,这里我先充10¥为敬:
![[图片]](https://i-blog.csdnimg.cn/img_convert/cd91672f7edfe0f39838309d558c098c.png)
设置好过期时间和新建数量,提交后就可以获得一个新的令牌,后续只需要复制密匙来配置Claude code即可:
![[图片]](https://i-blog.csdnimg.cn/img_convert/3a7e50cac41421d9e7a9e7c499ff686a.png)
2、在Linux中的安装Claude code
不推荐用自己的电脑做生信,我们直接在Linux服务器中配置Claude code,或者你拥有一个符合以下条件的Linux环境:
· Linux 发行版 (Ubuntu 18.04+, CentOS 7+, Debian 9+)
· Node.js 18+
· 网络连接
发行版和网络连接我们的镜像都能满足,直接按照以下流程安装配置就好
2.1 安装Node.js
# 更新包列表
sudo apt update
# 安装 nvm(如果还没有)
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
# 重新加载 shell
source ~/.bashrc # 或 source ~/.zshrc
# 安装并使用 Node 20
nvm install 20
nvm use 20
nvm alias default 20
2.2 安装claude-code
# 配置镜像,否则后续安装可能超时
npm config set registry https://registry.npmmirror.com
# 安装claude-code
npm install -g @anthropic-ai/claude-code
# added 2 packages in 1m
claude --version
能正常返回版本号,即为安装成功:
![[图片]](https://i-blog.csdnimg.cn/img_convert/a2dccd7af1667b8c38dc8f525ecc7d82.png)
如果你显示正常安装但是却返回claude not found,那你可以通过这个绝对路径的方式访问(注意v20.20.2换成你自己的版本号)
~/.nvm/versions/node/v20.20.2/bin/claude
2.3 配置环境变量:
注意将sk-xxx替换为您的真实密钥,这样claude code才能够识别到你充值的tocken。就是刚才你在网页中获取的令牌密匙:
https://api.aigc.bar/register?aff=JSu9
![[图片]](https://i-blog.csdnimg.cn/img_convert/00096fff1c7c5ed321db20265b8a9228.png)
echo 'export ANTHROPIC_AUTH_TOKEN="sk-XXX你自己的令牌"' >> ~/.bashrc
echo 'export ANTHROPIC_BASE_URL="https://api.aigc.bar"' >> ~/.bashrc
source ~/.bashrc
为了防止claude抽风,可以切换到一个安全的文件目录下:
mkdir claude_test
cd claude_test
3、让Claude Code开始干活
此时,在终端敲下claude,即可启动,此时会有一个弹窗,询问你是否信任当前文件夹,直接敲回车即可:
![[图片]](https://i-blog.csdnimg.cn/img_convert/aece4be4d1fceec38e19905af00f60cd.png)
激动的心颤抖的手,此时就可以直接和claude对话了:
![[图片]](https://i-blog.csdnimg.cn/img_convert/10966f84cc2faf42d27f6ba2d4c7003b.png)
按下Ctrl+C就可以跳出当前对Claude-code的对话,并且对话可以被恢复:
![[图片]](https://i-blog.csdnimg.cn/img_convert/7b589307e4f4926d4d185b8b9762d9e5.png)
# 把"session-code"换成你终止时返回的具体值就好
claude --resume session-code
测试下实际需求,例如我输入的是“我希望复现GSE163973数据集对应文章的全部单细胞分析相关内容,请在本地运行并给我输出图表和代码”
claude-code的运行逻辑是每一步都会问你细节,并且想你发起询问是否执行,方向键可以换选项,回车选中即可,一般来说会给你三个选项,第一个选项问你是否执行,第二个问你是否要忽略当前指令的类似请求询问直接执行,第三个问你是否拒绝当前请求。
![[图片]](https://i-blog.csdnimg.cn/img_convert/5811e6f2bea0d76d3803a15848b69c4c.png)
第二步我们直接试试don't ask again
![[图片]](https://i-blog.csdnimg.cn/img_convert/47b501b4cd973731a46e424e78707f32.png)
但其实到第三步它还是会和你确认这一步的信息:
![[图片]](https://i-blog.csdnimg.cn/img_convert/5db8a220f1acac1719c640fcda3669d2.png)
开始检索数据:
![[图片]](https://i-blog.csdnimg.cn/img_convert/37b71f94917eba3cb41a29d68bc2705d.png)
缺点还是有的,相较于我们和语言大模型对话秒出结果,claude-code通常要反应并且分析很久。
![[图片]](https://i-blog.csdnimg.cn/img_convert/942fd94458820cfd5fa5b30c9c9624ec.png)
可以识别本地的R版本与环境:
![[图片]](https://i-blog.csdnimg.cn/img_convert/919014f587c0441e4c7e853c9628dcce.png)
终于到处理阶段:
![[图片]](https://i-blog.csdnimg.cn/img_convert/c72a30837d1cfb8a7c8516b9f6abbd8c.png)
注释数据能够自动读取解析。
![[图片]](https://i-blog.csdnimg.cn/img_convert/58f39352ca7a5f91c6c275af891d1c97.png)
实际使用下来,觉得交互有点太多了,下载文件、创建脚本、创建文件夹、甚至解压已经下载的文件都需要和你交互确认。按照这个模式来,那还是一个懂代码的人,通过与语言大模型的交互,自行输入代码,分析进度会快很多。
这一套流程大约花费了8.74¥,请求次数为73次。这个花费倒是不多。
![[图片]](https://i-blog.csdnimg.cn/img_convert/32e49065eb9cd6cdca7e449b60e3316c.png)
finally,提示运行完毕。在本地保存了代码并输出了图片结果
![[图片]](https://i-blog.csdnimg.cn/img_convert/f0f809dedd312f3aa8bad1ded5ee0627.png)
三、结果
claude code自动在本地输出了以下文件,我们存在百度云里供大家下载学习
链接:
https://pan.baidu.com/s/112L2MuR_wKO32hvGrS6ubw
提取码:联系客服[Biomamba_zhushou]领取
![[图片]](https://i-blog.csdnimg.cn/img_convert/d450fda5319a9813ec7eb4373e2fca26.png)
最后,大家可以学习并检查一下代码:
suppressPackageStartupMessages({
library(Seurat)
library(ggplot2)
library(dplyr)
library(patchwork)
library(RColorBrewer)
library(data.table)
})
dir.create("figures", showWarnings = FALSE)
# ── Load fibroblast subtype Seurat object ─────────────────────────────────────
cat("Loading fib_clusters Seurat object...\n")
load("data/fib_clusters.Rdata")
fib <- get(ls()[sapply(ls(), function(x) is(get(x), "Seurat"))])
cat("Cells:", ncol(fib), "| Reductions:", paste(names(fib@reductions), collapse=", "), "\n")
# Paper's 4 fibroblast subtypes mapped from cluster IDs (res 0.45)
# Based on: Deng et al. 2021, Fig 2 marker genes
subtype_map <- c(
"0"="Secretory-reticular", "1"="Secretory-papillary",
"2"="Mesenchymal", "3"="Pro-inflammatory",
"4"="Secretory-reticular", "5"="Mesenchymal",
"6"="Pro-inflammatory", "8"="Secretory-papillary"
)
subtype_colors <- c(
"Secretory-papillary" ="#4DBBD5", "Secretory-reticular"="#E64B35",
"Mesenchymal" ="#00A087", "Pro-inflammatory" ="#F39B7F"
)
condition_colors <- c("KF"="#E64B35", "NF"="#4DBBD5")
fib$subtype <- subtype_map[as.character(fib$integrated_snn_res.0.45)]
fib$condition <- ifelse(grepl("KF|KL", fib$condition), "KF", "NF")
# ── Fig 1: UMAP colored by subtype ───────────────────────────────────────────
Idents(fib) <- "subtype"
p1 <- DimPlot(fib, cols=subtype_colors, pt.size=0.3, label=TRUE, label.size=4,
repel=TRUE) +
ggtitle("Fibroblast subpopulations") + theme_classic() +
theme(legend.position="right")
ggsave("figures/fig1_UMAP_subtype.pdf", p1, width=8, height=6)
ggsave("figures/fig1_UMAP_subtype.png", p1, width=8, height=6, dpi=150)
cat("fig1 saved\n")
# ── Fig 2: UMAP split by condition ───────────────────────────────────────────
p2 <- DimPlot(fib, group.by="condition", cols=condition_colors,
pt.size=0.3, split.by="condition") +
ggtitle("Fibroblasts: KF vs NF") + theme_classic()
ggsave("figures/fig2_UMAP_condition.pdf", p2, width=10, height=5)
ggsave("figures/fig2_UMAP_condition.png", p2, width=10, height=5, dpi=150)
cat("fig2 saved\n")
# ── Fig 3: Marker dot plot ────────────────────────────────────────────────────
markers <- c("SFRP2","DPP4","CFD","APOE","CCL19","CXCL12",
"POSTN","FN1","COL11A1","CXCL1","CXCL6","IL6")
markers <- markers[markers %in% rownames(fib)]
Idents(fib) <- "integrated_snn_res.0.45"
p3 <- DotPlot(fib, features=markers, dot.scale=6) +
RotatedAxis() +
scale_color_gradient2(low="blue", mid="white", high="red") +
ggtitle("Marker genes by cluster") +
theme(axis.text.x=element_text(angle=45, hjust=1))
ggsave("figures/fig3_marker_dotplot.pdf", p3, width=10, height=6)
ggsave("figures/fig3_marker_dotplot.png", p3, width=10, height=6, dpi=150)
cat("fig3 saved\n")
# ── Fig 4: Subtype proportion stacked bar ────────────────────────────────────
meta <- fib@meta.data
prop_df <- meta %>%
group_by(condition, subtype) %>% summarise(n=n(), .groups="drop") %>%
group_by(condition) %>% mutate(prop=n/sum(n)*100)
p4 <- ggplot(prop_df, aes(x=condition, y=prop, fill=subtype)) +
geom_bar(stat="identity", position="stack") +
scale_fill_manual(values=subtype_colors) +
labs(x="Condition", y="Proportion (%)", fill="Subtype",
title="Fibroblast subpopulation proportions") +
theme_classic()
ggsave("figures/fig4_subtype_proportion.pdf", p4, width=5, height=6)
ggsave("figures/fig4_subtype_proportion.png", p4, width=5, height=6, dpi=150)
cat("fig4 saved\n")
# ── Fig 5: Per-sample proportion ─────────────────────────────────────────────
sample_prop <- meta %>%
group_by(dataset, condition, subtype) %>% summarise(n=n(), .groups="drop") %>%
group_by(dataset) %>% mutate(prop=n/sum(n)*100)
p5 <- ggplot(sample_prop, aes(x=dataset, y=prop, fill=subtype)) +
geom_bar(stat="identity", position="stack") +
scale_fill_manual(values=subtype_colors) +
facet_wrap(~condition, scales="free_x") +
labs(x="Sample", y="Proportion (%)", fill="Subtype",
title="Per-sample fibroblast proportions") +
theme_classic() + theme(axis.text.x=element_text(angle=45, hjust=1))
ggsave("figures/fig5_persample_proportion.pdf", p5, width=8, height=6)
ggsave("figures/fig5_persample_proportion.png", p5, width=8, height=6, dpi=150)
cat("fig5 saved\n")
# ── Fig 6: Mesenchymal marker feature plots ───────────────────────────────────
mesen_markers <- c("POSTN","FN1","COL11A1","COL5A2")
mesen_markers <- mesen_markers[mesen_markers %in% rownames(fib)]
p6 <- FeaturePlot(fib, features=mesen_markers, ncol=2,
cols=c("lightgrey","#E64B35"), pt.size=0.2) &
theme_classic()
ggsave("figures/fig6_mesenchymal_markers.pdf", p6, width=10, height=8)
ggsave("figures/fig6_mesenchymal_markers.png", p6, width=10, height=8, dpi=150)
cat("fig6 saved\n")
# ── Fig 7: Violin plots for subtype markers ───────────────────────────────────
Idents(fib) <- "subtype"
vln_genes <- c("POSTN","SFRP2","APOE","CXCL1")
vln_genes <- vln_genes[vln_genes %in% rownames(fib)]
p7 <- VlnPlot(fib, features=vln_genes, ncol=2, pt.size=0,
cols=subtype_colors) &
theme(axis.text.x=element_text(angle=45, hjust=1))
ggsave("figures/fig7_violin_markers.pdf", p7, width=10, height=8)
ggsave("figures/fig7_violin_markers.png", p7, width=10, height=8, dpi=150)
cat("fig7 saved\n")
# ── Fig 8: All-cell type proportions from metadata ───────────────────────────
all_meta <- fread("data/all_meta.csv.gz")
cell_colors <- c(
"Fibroblast"="#E64B35", "Endothelial"="#4DBBD5",
"Keratinocyte"="#00A087", "muscle_fiber"="#3C5488",
"Immune_cell"="#F39B7F", "Lymphatic_endothelial"="#8491B4",
"Glandular"="#91D1C2", "Melanocytes"="#DC0000",
"Neural_cell"="#7E6148", "Unknown"="#B09C85"
)
ct_prop <- all_meta %>%
mutate(condition=ifelse(grepl("KF|KL", dataset), "KF", "NF")) %>%
group_by(condition, cellType) %>% summarise(n=n(), .groups="drop") %>%
group_by(condition) %>% mutate(prop=n/sum(n)*100)
p8 <- ggplot(ct_prop, aes(x=condition, y=prop, fill=cellType)) +
geom_bar(stat="identity", position="stack") +
scale_fill_manual(values=cell_colors) +
labs(x="Condition", y="Proportion (%)", fill="Cell type",
title="Cell type proportions (KF vs NF)") +
theme_classic()
ggsave("figures/fig8_celltype_proportion.pdf", p8, width=6, height=6)
ggsave("figures/fig8_celltype_proportion.png", p8, width=6, height=6, dpi=150)
cat("fig8 saved\n")
cat("\nAll figures saved to ./figures/\n")
print(list.files("figures/"))
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)