一、写在前面

1、玩一下Claude Code

Claude Code是Anthropic推出的终端AI编程助手(Coding Agent)。它既不是聊天机器人,也不是只提示下一行代码的编辑器插件(AI无缝接入Rstudio≈言出法随),而是一个能够独立理解、规划、执行并验证任务的自主编程代理。只需要给它一个目标/指令,它就能在自己专属的代理循环(Agentic Loop)中自动完成规划、编写、执行和验证,全程无需人工复制粘贴或切换窗口。

例如,本教程我将给它一句话指令,直接让它帮我分析一个数据集:“我希望复现GSE163973数据集对应来源文章的全部单细胞分析相关内容,请在本地运行并给我输出图表和代码”。最终,我得到了以下分析图片:

[图片]

这个数据集我们也曾人工复现过:

代码复现| scRNA-seq揭示人纤维化皮肤病中的成纤维细胞异质性与增殖

[图片]

2、聊聊感受

实际使用下来,觉得Claude交互有点太多了。虽然我尽量用一句话描述了我的目的,但是启动流程、下载文件、创建脚本、创建文件夹、甚至解压已经下载的文件都需要和你交互确认。所以前前后后我在Claude Code的代码框里花了七个小时。按照这个模式来,一个懂代码的人,通过与语言大模型的交互,自行输入代码运行,分析进度会比这快很多。但对于不会写代码的人而言,Claude Code可就是跨越阶级的工具了,毕竟在你不会代码的情况下,直接花七个小时分析一篇文章,这事放在五年前属于会法术。并且,这一整套流程下来,不算服务器的成本,只需要花8¥。

关于输出的图片,我也与原文进行了对比。画风和配色基本一致,细胞也能够正常注释,并通过亚群分析一定程度上重现原文对于纤维化的评估。当然也有缺陷,首先原文有大量的分析图表,Claude Code只输出了一部分,并且并不能做到1:1完美复现,例如上文的气泡图,原本应该是一张stack小提琴图。

如果需要Claude Code在服务器中代为部署,也欢迎联系客服[Biomamba_zhushou]聊聊

二、配置并使用Claude Code

1、获取tocken

如果你可以科学上网并拥有一个Gmail,那你可以直接从官网注册:

https://claude.com

[图片]

如果你和我一样因为是新账户被claude拒绝了,可以试一下代理:

https://api.aigc.bar/register?aff=JSu9

注册,登录

[图片]

选好令牌模型,这里我选的是Claude-code,大家也可以试试其它模型好不好用。

[图片]

接下来需要在自己的钱包管理中充值额度,这样API才能够正确调用,与Claude code交互是需要消耗tocken的,这里我先充10¥为敬:

[图片]

设置好过期时间和新建数量,提交后就可以获得一个新的令牌,后续只需要复制密匙来配置Claude code即可:

[图片]

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

能正常返回版本号,即为安装成功:

[图片]

如果你显示正常安装但是却返回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

[图片]

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,即可启动,此时会有一个弹窗,询问你是否信任当前文件夹,直接敲回车即可:

[图片]

激动的心颤抖的手,此时就可以直接和claude对话了:

[图片]

按下Ctrl+C就可以跳出当前对Claude-code的对话,并且对话可以被恢复:

[图片]

# 把"session-code"换成你终止时返回的具体值就好
claude --resume session-code

测试下实际需求,例如我输入的是“我希望复现GSE163973数据集对应文章的全部单细胞分析相关内容,请在本地运行并给我输出图表和代码”

claude-code的运行逻辑是每一步都会问你细节,并且想你发起询问是否执行,方向键可以换选项,回车选中即可,一般来说会给你三个选项,第一个选项问你是否执行,第二个问你是否要忽略当前指令的类似请求询问直接执行,第三个问你是否拒绝当前请求。

[图片]

第二步我们直接试试don't ask again

[图片]

但其实到第三步它还是会和你确认这一步的信息:

[图片]

开始检索数据:

[图片]

缺点还是有的,相较于我们和语言大模型对话秒出结果,claude-code通常要反应并且分析很久。

[图片]

可以识别本地的R版本与环境:

[图片]

终于到处理阶段:

[图片]

注释数据能够自动读取解析。

[图片]

实际使用下来,觉得交互有点太多了,下载文件、创建脚本、创建文件夹、甚至解压已经下载的文件都需要和你交互确认。按照这个模式来,那还是一个懂代码的人,通过与语言大模型的交互,自行输入代码,分析进度会快很多。

这一套流程大约花费了8.74¥,请求次数为73次。这个花费倒是不多。

[图片]

finally,提示运行完毕。在本地保存了代码并输出了图片结果

[图片]

三、结果

claude code自动在本地输出了以下文件,我们存在百度云里供大家下载学习

链接:

 https://pan.baidu.com/s/112L2MuR_wKO32hvGrS6ubw 

提取码:联系客服[Biomamba_zhushou]领取

[图片]

最后,大家可以学习并检查一下代码:

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/"))
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐