用 aardio 给 R 程序写图形界面——CircosHeatmap-aardio 开发记录与分享

阿甘 2月前 599

做一个基于 R 语言的环形热图(Circos Heatmap)绘制工具,通过 Aardio 实现图形界面。

项目地址:CircosHeatmap-aardio

示例:

demo

输出:

  • aardio:用于开发图形界面,提供友好的用户交互体验。

  • R 语言:用于数据处理和环形热图绘制。

  • R 包:

    • circlize:用于绘制环形热图。

    • ComplexHeatmap:用于热图的聚类和高级可视化。

    • RColorBrewer:提供颜色梯度。

    • dendextend:用于树状图的颜色分支。


编译打包前的准备:

修改 aardio\lib\process\r\_.aardio 文件中:


Code AardioLine:1复制
  • 1.
    • setLibPaths({..io.appData("aardio/std/r/site-library")});

    修改为

    Code AardioLine:7复制
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
    • if (_STUDIO_INVOKED) {
    • // 开发环境
    • setLibPaths({..io.appData("aardio/std/r/site-library")});
    • } else {
    • // 打包后环境
    • setLibPaths({"lib\r-library"});
    • }

    修改它的目的:初次接触 aardio + R 的开发,安装 R 的相关库时遇到无法安装部分 R 库的问题,所以干脆把安装好的 R 相关库放入程序根目录下,便于将程序分发给别人使用。

    这样做缺点:R 库体积偏大,100MB+,不过真正需要的人应该不在乎体积吧


    TODO:

    • 优化 UI:进一步提升用户交互体验,增加更多可视化选项

    • 支持更多文件格式:扩展支持更多数据文件格式

    • 增加高级功能:如自定义颜色梯度、调整聚类参数等


    1、aardio 图形界面开发

    Code AardioLine:59复制
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
    • import win.ui;
    • /*DSG{{*/
    • mainForm = win.form(text="CircosHeatmap-aardio";right=800;bottom=600)
    • mainForm.add(
    • btnRun={cls="plus";text="运行";left=740;top=10;right=791;bottom=41;activebgcolor=19354;bgcolor=-5197169;font=LOGFONT(h=-16);hoverbgcolor=23477;textcolor=16777215;z=4};
    • btnSelectFile={cls="plus";text="选择输入文件";left=608;top=10;right=732;bottom=41;activebgcolor=19354;bgcolor=-5197169;font=LOGFONT(h=-16);hoverbgcolor=23477;textcolor=16777215;z=3};
    • editConsole={cls="edit";left=10;top=467;right=791;bottom=591;bgcolor=16777215;db=1;dl=1;dr=1;edge=1;hscroll=1;multiline=1;textcolor=0;vscroll=1;z=1};
    • editRScript={cls="edit";left=10;top=48;right=791;bottom=451;bgcolor=16777215;db=1;dl=1;dr=1;dt=1;edge=1;hscroll=1;multiline=1;textcolor=0;vscroll=1;z=5};
    • inputFile={cls="edit";left=10;top=10;right=600;bottom=40;bgcolor=16777215;edge=1;textcolor=0;z=2}
    • )
    • /*}}*/
    • btskin = {
    • background={
    • active=0xFFD3E0BC;
    • default=0xFF8FB2B0;
    • hover=0xFF928BB3
    • }
    • }
    • mainForm.btnRun.skin(btskin);
    • mainForm.btnSelectFile.skin(btskin);
    • import console;
    • import process.r;
    • import fsys.dlg;
    • mainForm.editRScript.print($"\res\heatmap_script.R");
    • // 选择文件按钮点击事件
    • mainForm.btnSelectFile.oncommand = function(id, event) {
    • var filePath = fsys.dlg.open("CSV 文件|*.csv||",, "选择输入文件");
    • if (filePath) {
    • mainForm.inputFile.text = filePath; // 将选择的文件路径显示在输入框中
    • }
    • }
    • // 运行按钮点击事件
    • mainForm.btnRun.oncommand = function(id, event) {
    • var inputFilePath = mainForm.inputFile.text;
    • if (!inputFilePath) {
    • console.log("请先选择输入文件!");
    • return;
    • }
    • // 弹出保存文件对话框,选择PDF保存路径
    • var outputFilePath = fsys.dlg.save("PDF 文件|*.pdf||",, "选择保存路径");
    • if (!outputFilePath) {
    • console.log("请选择PDF文件的保存路径!");
    • return;
    • }
    • // 执行 R 脚本
    • var out = process.r.exec(mainForm.editRScript.text, inputFilePath, outputFilePath);
    • mainForm.editConsole.print(out);
    • }
    • // 显示主窗口
    • mainForm.show();
    • return win.loopMessage();


    2、 R 脚本实现

    R 脚本是该程序的核心,负责数据处理和环形热图的绘制。

    Code AardioLine:84复制
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
    • # 加载所需的包
    • suppressPackageStartupMessages(library(circlize))
    • suppressPackageStartupMessages(library(RColorBrewer))
    • suppressPackageStartupMessages(library(ComplexHeatmap))
    • suppressPackageStartupMessages(library(dendextend))
    • # 获取命令行参数
    • args <- commandArgs(trailingOnly = TRUE)
    • # 检查参数数量
    • if (length(args) != 2) {
    • stop("请提供两个参数:输入CSV文件路径和输出PDF文件路径。", call. = FALSE)
    • }
    • # 获取输入CSV文件路径和输出PDF文件路径
    • input_csv <- args[1]
    • output_pdf <- args[2]
    • # 检查输入文件是否存在
    • if (!file.exists(input_csv)) {
    • stop("输入文件不存在。请检查文件路径。", call. = FALSE)
    • }
    • # 函数加载和预处理数据
    • load_and_preprocess_data <- function(file_path) {
    • data <- read.table(file = file_path, header = TRUE, row.names = 1, sep = ',')
    • data_matrix <- as.matrix(data)
    • normalized_data <- t(scale(t(data_matrix)))
    • normalized_data[is.na(normalized_data)] <- 0
    • return(normalized_data)
    • }
    • # 加载和预处理数据
    • cir1 <- load_and_preprocess_data(input_csv)
    • # 打印数据维度和头部
    • print(dim(cir1))
    • print(head(cir1))
    • # 定义颜色梯度
    • mycol <- colorRamp2(c(-2.5, 0.3, 3.1), c("blue", "white", "red"))
    • # 打开PDF设备,设置宽度和高度相等
    • pdf(output_pdf, width = 8, height = 8)
    • # 设置绘图参数
    • circos.par(gap.after = c(30))
    • # 绘制调整后的圆形热图
    • circos.heatmap(cir1,
    • col = mycol,
    • dend.side = "inside",
    • rownames.side = "outside",
    • rownames.col = "black",
    • rownames.cex = 1.3,
    • track.height = 0.35, # 增加轨道高度
    • cluster = TRUE,
    • dend.track.height = 0.18,
    • dend.callback = function(dend, m, si) {
    • color_branches(dend, k = 15, col = 1:15)
    • })
    • # 添加列名
    • circos.track(track.index = get.current.track.index(), panel.fun = function(x, y) {
    • if (CELL_META$sector.numeric.index == 1) {
    • cn <- colnames(cir1)
    • n <- length(cn)
    • circos.text(rep(CELL_META$cell.xlim[2], n) + convert_x(0.5, "mm"),
    • 1:n + 2.5,
    • cn, cex = 0.6, adj = c(0, 0.5), facing = "inside")
    • }
    • }, bg.border = NA)
    • # 添加图例
    • lg <- Legend(title = "Exp", col_fun = mycol, direction = "vertical")
    • grid.draw(lg)
    • # 清除圆形图
    • circos.clear()
    • # 关闭PDF设备
    • dev.off()
    • message("热图已成功保存至: ", output_pdf)


    最新回复 (4)
    • 阿甘 2月前
      0 2
      如果可以的话其实不想用 R 语言来写工具,因为不熟悉环境和用法,好在 aardio 很方便调用 R 来做界面。 这是我用到的第一个 R 程序,可能极少会用到它,但真正要用的时候还是希望能一键运行使用,而不是每次运行都要打开 Rstudio 或者在新电脑上配置 R 环境。
    • 光庆 2月前
      0 3
      真羡慕你们这些什么都会的
    • 阿甘 2月前
      0 4
      光庆 真羡慕你们这些什么都会的

      庆帝才是yyds

    • 阿甘 2月前
      0 5

      才注意到有设置寻找依赖的函数:

      Code AardioLine:7复制
    • 1.
    • 2.
    • 3.
    • 4.
    • 5.
    • 6.
    • 7.
      • if (_STUDIO_INVOKED) {
      • process.r.setLibPaths({"/dist/lib/r-library"});
      • }
      • else {
      • process.r.setLibPaths({"/lib/r-library"});
      • }

    返回