diff --git a/examples/workflows/research-hotspot-tracker/README.md b/examples/workflows/research-hotspot-tracker/README.md new file mode 100644 index 0000000..0a7f16d --- /dev/null +++ b/examples/workflows/research-hotspot-tracker/README.md @@ -0,0 +1,135 @@ +# GitLink 科研热点追踪器 + +基于 GitLink 平台的开源科研仓库多维度自动化分析流水线。 + +## 这是什么 + +`repos.txt` 列出一批仓库 → `run_all.sh` 一键执行数据采集、分析、可视化 → 输出 CSV 统计表、PNG 图表和 Markdown 报告,帮你快速了解一批开源科研仓库的代码规模、活跃度、技术栈和贡献者生态。 + +分析流水线适配所有科研领域,当前示例是蛋白质结构预测领域的 5 个仓库,换成任何其他领域只需改 `repos.txt`。 + +## 项目结构 + +``` +├── repos.txt # 仓库列表(一行一个 owner/repo) +├── run_all.sh # 一键运行入口 +├── research_application_report.md # 科研场景应用报告(完整技术说明) +│ +├── scripts/ +│ ├── fetch_data_v2.sh # 批量数据采集(调用 gitlink-cli) +│ ├── analyze_v2.py # JSON → CSV 数据分析 +│ └── visualize.py # 生成 4 张可视化图表 +│ +├── data/ +│ ├── raw/ # 每仓库 4 个 JSON:info、code_stats、contributors、languages +│ └── processed/ # 分析后的 4 个 CSV 文件 +│ ├── repo_summary.csv # 仓库基本信息 +│ ├── code_stats.csv # 代码规模 + Top3 贡献者 +│ ├── contributor_network.csv # 贡献者跨仓库分布 +│ └── language_distribution.csv # 语言分布 +│ +└── output/ # 图表与报告 + ├── code_volume_comparison.png # 代码新增/删除对比柱状图 + ├── activity_bubble.png # 提交次数 vs 贡献者人数气泡图 + ├── language_distribution.png # 语言分布堆叠条形图 + ├── cross_repo_contributors.png # 跨仓库贡献者水平条形图 + ├── struct.svg # 系统架构图 + ├── research_trend_report.md # 科研趋势分析报告 + └── research-application-report.md # 科研场景应用报告 +``` + +## 快速开始 + +```bash +# 1. 安装依赖 +pip install pandas matplotlib + +# 2. 编辑仓库列表(可选,默认分析了 5 个蛋白质结构预测仓库) +# vim repos.txt + +# 3. 一键运行 +bash run_all.sh +``` + +运行后数据在 `data/processed/`,图表和报告在 `output/`。 + +## 流水线详解 + +`run_all.sh` 按顺序执行三步: + +### 第一步:数据采集(`scripts/fetch_data_v2.sh`) + +逐行读取 `repos.txt`,对每个仓库调用 `gitlink-cli` 四个子命令: + +| 命令 | 输出 JSON | 内容 | +|------|-----------|------| +| `repo +info` | `{owner}_{repo}_info.json` | 仓库名、大小、描述、默认分支 | +| `repo +code-stats` | `{owner}_{repo}_code_stats.json` | 代码新增/删除行数、提交次数、按作者统计 | +| `repo +contributors` | `{owner}_{repo}_contributors.json` | 贡献者列表(含邮箱、贡献占比) | +| `repo +languages` | `{owner}_{repo}_languages.json` | 各编程语言代码占比 | + +5 个仓库 → 20 个 JSON 文件,存入 `data/raw/`。 + +### 第二步:数据分析(`scripts/analyze_v2.py`) + +解析 raw JSON,输出 4 个标准化 CSV: + +- **repo_summary.csv** — 各仓库基本属性(大小、分支等) +- **code_stats.csv** — 代码新增/删除量、提交数、作者数、Top3 贡献者及提交数 +- **contributor_network.csv** — 每个贡献者的邮箱、覆盖仓库数、仓库列表 +- **language_distribution.csv** — 各仓库的编程语言百分比矩阵(直接可用于可视化) + +### 第三步:可视化(`scripts/visualize.py`) + +基于 CSV 数据生成 4 张 matplotlib 图表(dpi=150): + +1. **代码量对比柱状图** — 各仓库新增/删除行数对比 +2. **活跃度气泡图** — x 轴作者数、y 轴提交数、气泡大小 = 新增代码量 +3. **语言分布堆叠条形图** — 各仓库技术栈统一性一览 +4. **跨仓库贡献者条形图** — 参与多个仓库的核心开发者(Top 15) + +## 当前分析结论 + +基于 5 个蛋白质结构预测镜像仓库的真实数据: + +| 指标 | AlphaFold3 | alphafold | AlphaFill | RoseTTAFold | OpenFold | +|------|-----------|-----------|-----------|-------------|----------| +| 提交次数 | 244 | 198 | 279 | 34 | **604** | +| 贡献者 | 14 | **28** | 3 | 2 | 9 | +| 新增代码 | 8.4 万行 | 5.5 万行 | 27.2 万行 | **42.3 万行** | 16.6 万行 | +| 巴士因子 | ≥3 | ≥3 | 1 | 1 | ≥3 | +| 技术栈 | Python 85% + C++ 14% | Python 97% | C++ 80% | Python 98% | Python 94% | + +关键发现: +- **OpenFold** 提交 604 次,9 名贡献者高强度迭代,社区开放协作程度最高 +- **AlphaFill** 和 **RoseTTAFold** 巴士因子仅 1,高度依赖单一核心开发者 +- **Augustin Zidek**(DeepMind)是唯一跨 `AlphaFold3` 和 `alphafold` 的核心贡献者 +- 全部仓库 Python 占主导,技术栈高度统一 + +详细分析见 `output/research_trend_report.md`。 + +## 扩展到其他领域 + +修改 `repos.txt` 中的仓库列表即可: + +```txt +# 示例:气候模拟领域 +some-lab/CESM +some-lab/WRF +some-lab/MPAS + +# 示例:基因组学 +broadinstitute/gatk +luntergroup/octopus +``` + +重新运行 `bash run_all.sh`,整套管道自动适配。领域不影响任何分析逻辑——指标全部来自 GitLink 通用 API,不依赖领域知识。 + +补充说明:分析仓库必须是 GitLink 平台上的仓库。对于 GitHub 原仓库,需要先在 GitLink 上创建镜像。 + +## 环境要求 + +- **Python** 3.9+ +- **pip** 依赖:`pandas`, `matplotlib` +- **gitlink-cli**(用于数据采集阶段,需 GitLink 账号 token) +- 操作系统:Linux / macOS / WSL(脚本为 Bash) diff --git a/examples/workflows/research-hotspot-tracker/data/processed/code_stats.csv b/examples/workflows/research-hotspot-tracker/data/processed/code_stats.csv new file mode 100644 index 0000000..dc21601 --- /dev/null +++ b/examples/workflows/research-hotspot-tracker/data/processed/code_stats.csv @@ -0,0 +1,6 @@ +repo,total_additions,total_deletions,commit_count,author_count,top1_author,top1_commits,top2_author,top2_commits,top3_author,top3_commits +NSCCN/AlphaFold3,83809,16005,244,14,Augustin Zidek,206,Josh Abramson,11,James Spencer,9 +Supercomputing/alphafold,54960,9460,198,28,Augustin Zidek,67,Hamish Tomlinson,29,Ryan Pachauri,15 +NSCCN/AlphaFill,271596,64215,279,3,Maarten L. Hekkelman,274,IdaDeVries,4,rjoosten,1 +NSCCN/RoseTTAFold,423167,45227,34,2,Minkyung Baek,26,Minkyung Baek,8,, +scnc/openfold,166097,18503,604,9,Gustaf Ahdritz,534,Sachin Kadyan,51,Gustaf,7 diff --git a/examples/workflows/research-hotspot-tracker/data/processed/contributor_network.csv b/examples/workflows/research-hotspot-tracker/data/processed/contributor_network.csv new file mode 100644 index 0000000..e5cb619 --- /dev/null +++ b/examples/workflows/research-hotspot-tracker/data/processed/contributor_network.csv @@ -0,0 +1,81 @@ +email,repo_count,repo_list +augustinzidek@google.com,2,NSCCN/AlphaFold3; Supercomputing/alphafold +49699333+dependabot[bot]@users.noreply.github.com,2,NSCCN/AlphaFill; NSCCN/AlphaFold3 +jabramson@google.com,1,NSCCN/AlphaFold3 +jamessspencer@google.com,1,NSCCN/AlphaFold3 +jacobjinkelly@google.com,1,NSCCN/AlphaFold3 +ashutoshkumarsingh0x@gmail.com,1,NSCCN/AlphaFold3 +rocklover88@proton.me,1,NSCCN/AlphaFold3 +pasqmigl97@gmail.com,1,NSCCN/AlphaFold3 +ccoulombe@users.noreply.github.com,1,NSCCN/AlphaFold3 +j.j.carpenter@bham.ac.uk,1,NSCCN/AlphaFold3 +zohaibshahid7035@gmail.com,1,NSCCN/AlphaFold3 +ook077358@gmail.com,1,NSCCN/AlphaFold3 +akvi@google.com,1,NSCCN/AlphaFold3 +alex.morehead@gmail.com,1,NSCCN/AlphaFold3 +avisinha1711@gmail.com,1,NSCCN/AlphaFold3 +53904580+dailypartita@users.noreply.github.com,1,NSCCN/AlphaFold3 +90102437+dibyx@users.noreply.github.com,1,NSCCN/AlphaFold3 +o.kenway@ucl.ac.uk,1,NSCCN/AlphaFold3 +48257736+pasqm@users.noreply.github.com,1,NSCCN/AlphaFold3 +wttat8600@gmail.com,1,Supercomputing/alphafold +chunan.liu@ucl.ac.uk,1,Supercomputing/alphafold +francesco.oteri@gmail.com,1,Supercomputing/alphafold +33014714+yaoyinying@users.noreply.github.com,1,Supercomputing/alphafold +tru@pasteur.fr,1,Supercomputing/alphafold +htomlinson@google.com,1,Supercomputing/alphafold +bio.chunanliu@gmail.com,1,Supercomputing/alphafold +meesters@uni-mainz.de,1,Supercomputing/alphafold +rpachauri@google.com,1,Supercomputing/alphafold +noreply@google.com,1,Supercomputing/alphafold +umberto.lupo@gmail.com,1,Supercomputing/alphafold +33123184+dimamolod@users.noreply.github.com,1,Supercomputing/alphafold +geoffrey.yu96@icloud.com,2,Supercomputing/alphafold; scnc/openfold +dmolodenskiy@embl-hamburg.de,1,Supercomputing/alphafold +htiku@google.com,1,Supercomputing/alphafold +oliver@peptone.io,1,Supercomputing/alphafold +tomward@google.com,1,Supercomputing/alphafold +mdamgaard@biolib.com,1,Supercomputing/alphafold +maarten@hekkelman.com,1,NSCCN/AlphaFill +r.joosten@nki.nl,1,NSCCN/AlphaFill +83767200+idadevries@users.noreply.github.com,1,NSCCN/AlphaFill +robbie_joosten@hotmail.com,1,NSCCN/AlphaFill +minkbaek@digs,1,NSCCN/RoseTTAFold +jcastellanos@neoleukin.com,1,NSCCN/RoseTTAFold +minkbaek@uw.edu,1,NSCCN/RoseTTAFold +38662498+avivko@users.noreply.github.com,1,NSCCN/RoseTTAFold +andreasantoro.pvt@gmail.com,1,NSCCN/RoseTTAFold +bc06026@uga.edu,1,NSCCN/RoseTTAFold +abdullah.kahraman@gmail.com,1,NSCCN/RoseTTAFold +xubeisi@gmail.com,1,NSCCN/RoseTTAFold +eltociear@gmail.com,1,NSCCN/RoseTTAFold +javierbq@gmail.com,1,NSCCN/RoseTTAFold +huhlim@gmail.com,1,NSCCN/RoseTTAFold +arthur200126@gmail.com,1,NSCCN/RoseTTAFold +mamahmoudzadeh@gmail.com,1,NSCCN/RoseTTAFold +47426058+ghbhc@users.noreply.github.com,1,NSCCN/RoseTTAFold +88146749+zemu-unile@users.noreply.github.com,1,NSCCN/RoseTTAFold +christoph.siegert@uni-leipzig.de,1,NSCCN/RoseTTAFold +59423916+runitralph@users.noreply.github.com,1,NSCCN/RoseTTAFold +shawncal@microsoft.com,1,NSCCN/RoseTTAFold +bbaker@cs.hmc.edu,1,NSCCN/RoseTTAFold +88408493+neilfleckscri@users.noreply.github.com,1,NSCCN/RoseTTAFold +gahdritz@gmail.com,1,scnc/openfold +tabuchi.akihiro@fujitsu.com,1,scnc/openfold +oyama.yosuke@fujitsu.com,1,scnc/openfold +sachinkadyan7@gmail.com,1,scnc/openfold +christina.floristean@gmail.com,1,scnc/openfold +jennifer.wei@omsf.io,1,scnc/openfold +whereisthelux@gmail.com,1,scnc/openfold +3505568+jflucier@users.noreply.github.com,1,scnc/openfold +97625454+jnwei@users.noreply.github.com,1,scnc/openfold +hiroyuki.akamatsu12@metro.co.jp,1,scnc/openfold +jacknicoludis@gmail.com,1,scnc/openfold +jeon_jaesung@metro.co.jp,1,scnc/openfold +yianni.anastopoulos@unnaturalproducts.com,1,scnc/openfold +tabuchi.akihiro@jp.fujitsu.com,1,scnc/openfold +44894955+dingquanyu@users.noreply.github.com,1,scnc/openfold +sam@cyrusbio.com,1,scnc/openfold +geoffreyyu@geoffreys-macbook-pro.local,1,scnc/openfold +jc@juliocesar.io,1,scnc/openfold +64649594+vaclavhanzl@users.noreply.github.com,1,scnc/openfold diff --git a/examples/workflows/research-hotspot-tracker/data/processed/language_distribution.csv b/examples/workflows/research-hotspot-tracker/data/processed/language_distribution.csv new file mode 100644 index 0000000..ceadfb4 --- /dev/null +++ b/examples/workflows/research-hotspot-tracker/data/processed/language_distribution.csv @@ -0,0 +1,6 @@ +repo,Batchfile,C,C++,CMake,Cuda,Dockerfile,HTML,JavaScript,Jupyter Notebook,MAXScript,Makefile,Perl,Python,SCSS,Shell +NSCCN/AlphaFold3,0%,0%,14.0%,0.2%,0%,0.3%,0%,0%,0%,0%,0%,0%,85.1%,0%,0.4% +Supercomputing/alphafold,0%,0%,0%,0%,0%,0.4%,0%,0%,0.1%,0%,0%,0%,97.5%,0%,2.0% +NSCCN/AlphaFill,0.2%,0.7%,79.8%,5.7%,0%,0%,8.3%,3.6%,0%,0.3%,0.1%,0.2%,0%,1.1%,0.1% +NSCCN/RoseTTAFold,0%,0%,0%,0%,0%,0%,0%,0%,0%,0%,0%,0%,97.6%,0%,2.4% +scnc/openfold,0%,0%,0.2%,0%,0.5%,0.1%,0%,0%,3.0%,0%,0%,0%,93.5%,0%,2.7% diff --git a/examples/workflows/research-hotspot-tracker/data/processed/repo_summary.csv b/examples/workflows/research-hotspot-tracker/data/processed/repo_summary.csv new file mode 100644 index 0000000..55d6c7c --- /dev/null +++ b/examples/workflows/research-hotspot-tracker/data/processed/repo_summary.csv @@ -0,0 +1,6 @@ +repo,full_name,size,watchers,forks,mirror,default_branch,description +NSCCN/AlphaFold3,NSCCN/AlphaFold3,47.2 MB,0,0,True,main, +Supercomputing/alphafold,Supercomputing/alphafold,18.5 MB,0,0,True,main, +NSCCN/AlphaFill,NSCCN/AlphaFill,3.7 MB,0,0,True,trunk, +NSCCN/RoseTTAFold,NSCCN/RoseTTAFold,172.1 MB,0,0,True,main, +scnc/openfold,scnc/openfold,21.8 MB,0,0,True,main, diff --git a/examples/workflows/research-hotspot-tracker/data/raw/NSCCN_AlphaFill_code_stats.json b/examples/workflows/research-hotspot-tracker/data/raw/NSCCN_AlphaFill_code_stats.json new file mode 100644 index 0000000..bd64b79 --- /dev/null +++ b/examples/workflows/research-hotspot-tracker/data/raw/NSCCN_AlphaFill_code_stats.json @@ -0,0 +1,52 @@ +{ + "ok": true, + "data": { + "additions": 271596, + "author_count": 3, + "authors": [ + { + "additions": 271462, + "author": { + "email": "maarten@hekkelman.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/M/233_188_180/120.png", + "login": "Maarten L. Hekkelman", + "name": "Maarten L. Hekkelman", + "type": null + }, + "commits": 274, + "deletions": 64176 + }, + { + "additions": 128, + "author": { + "email": "83767200+idadevries@users.noreply.github.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/I/53_166_51/120.png", + "login": "IdaDeVries", + "name": "IdaDeVries", + "type": null + }, + "commits": 4, + "deletions": 38 + }, + { + "additions": 6, + "author": { + "email": "r.joosten@nki.nl", + "id": null, + "image_url": "system/lets/letter_avatars/2/R/236_194_58/120.png", + "login": "rjoosten", + "name": "rjoosten", + "type": null + }, + "commits": 1, + "deletions": 1 + } + ], + "change_files": null, + "commit_count": 279, + "commit_count_in_all_branches": 417, + "deletions": 64215 + } +} diff --git a/examples/workflows/research-hotspot-tracker/data/raw/NSCCN_AlphaFill_contributors.json b/examples/workflows/research-hotspot-tracker/data/raw/NSCCN_AlphaFill_contributors.json new file mode 100644 index 0000000..96e48bf --- /dev/null +++ b/examples/workflows/research-hotspot-tracker/data/raw/NSCCN_AlphaFill_contributors.json @@ -0,0 +1,61 @@ +{ + "ok": true, + "data": { + "list": [ + { + "contribution_perc": "93.71%", + "contributions": 447, + "email": "maarten@hekkelman.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/M/233_188_180/120.png", + "login": null, + "name": "maarten l. hekkelman", + "type": null + }, + { + "contribution_perc": "3.35%", + "contributions": 16, + "email": "49699333+dependabot[bot]@users.noreply.github.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/D/241_157_191/120.png", + "login": null, + "name": "dependabot[bot]", + "type": null + }, + { + "contribution_perc": "1.68%", + "contributions": 8, + "email": "r.joosten@nki.nl", + "id": null, + "image_url": "system/lets/letter_avatars/2/R/236_194_58/120.png", + "login": null, + "name": "rjoosten", + "type": null + }, + { + "contribution_perc": "1.05%", + "contributions": 5, + "email": "83767200+idadevries@users.noreply.github.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/I/53_166_51/120.png", + "login": null, + "name": "idadevries", + "type": null + }, + { + "contribution_perc": "0.21%", + "contributions": 1, + "email": "robbie_joosten@hotmail.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/R/236_156_171/120.png", + "login": null, + "name": "robbie p. joosten", + "type": null + } + ], + "total_count": 5 + }, + "meta": { + "total_count": 5 + } +} diff --git a/examples/workflows/research-hotspot-tracker/data/raw/NSCCN_AlphaFill_info.json b/examples/workflows/research-hotspot-tracker/data/raw/NSCCN_AlphaFill_info.json new file mode 100644 index 0000000..83c6b79 --- /dev/null +++ b/examples/workflows/research-hotspot-tracker/data/raw/NSCCN_AlphaFill_info.json @@ -0,0 +1,45 @@ +{ + "ok": true, + "data": { + "author": { + "id": 147738, + "image_url": "images/avatars/Organization/147738?t=1776128929", + "login": "NSCCN", + "name": "超算开源", + "type": "Organization" + }, + "clone_url": "https://gitlink.org.cn/NSCCN/AlphaFill.git", + "contributor_users_count": 0, + "default_branch": "trunk", + "empty": false, + "first_sync": true, + "forked_count": 0, + "forked_from_project_id": null, + "full_name": "NSCCN/AlphaFill", + "identifier": "AlphaFill", + "issues_count": 0, + "mirror": true, + "mirror_num": 1, + "mirror_status": 0, + "mirror_url": "https://github.com/PDB-REDO/alphafill.git", + "name": "AlphaFill", + "open_devops": false, + "permission": "", + "praised": false, + "praises_count": 0, + "private": false, + "project_id": 1528741, + "project_identifier": "AlphaFill", + "pull_requests_count": 0, + "repo_id": 1530354, + "size": "3.7 MB", + "ssh_url": "git@code.gitlink.org.cn:NSCCN/AlphaFill.git", + "status": 1, + "type": 1, + "version_releases_count": 0, + "version_releasesed_count": 0, + "versions_count": 0, + "watched": false, + "watchers_count": 0 + } +} diff --git a/examples/workflows/research-hotspot-tracker/data/raw/NSCCN_AlphaFill_languages.json b/examples/workflows/research-hotspot-tracker/data/raw/NSCCN_AlphaFill_languages.json new file mode 100644 index 0000000..1443b40 --- /dev/null +++ b/examples/workflows/research-hotspot-tracker/data/raw/NSCCN_AlphaFill_languages.json @@ -0,0 +1,16 @@ +{ + "ok": true, + "data": { + "Batchfile": "0.2%", + "C": "0.7%", + "C++": "79.8%", + "CMake": "5.7%", + "HTML": "8.3%", + "JavaScript": "3.6%", + "MAXScript": "0.3%", + "Makefile": "0.1%", + "Perl": "0.2%", + "SCSS": "1.1%", + "Shell": "0.1%" + } +} diff --git a/examples/workflows/research-hotspot-tracker/data/raw/NSCCN_AlphaFold3_code_stats.json b/examples/workflows/research-hotspot-tracker/data/raw/NSCCN_AlphaFold3_code_stats.json new file mode 100644 index 0000000..9c3c920 --- /dev/null +++ b/examples/workflows/research-hotspot-tracker/data/raw/NSCCN_AlphaFold3_code_stats.json @@ -0,0 +1,195 @@ +{ + "ok": true, + "data": { + "additions": 83809, + "author_count": 14, + "authors": [ + { + "additions": 79026, + "author": { + "email": "augustinzidek@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/A/233_155_153/120.png", + "login": "Augustin Zidek", + "name": "Augustin Zidek", + "type": null + }, + "commits": 206, + "deletions": 12252 + }, + { + "additions": 470, + "author": { + "email": "jabramson@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/J/165_135_246/120.png", + "login": "Josh Abramson", + "name": "Josh Abramson", + "type": null + }, + "commits": 11, + "deletions": 326 + }, + { + "additions": 155, + "author": { + "email": "jamessspencer@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/J/188_135_35/120.png", + "login": "James Spencer", + "name": "James Spencer", + "type": null + }, + "commits": 9, + "deletions": 67 + }, + { + "additions": 188, + "author": { + "email": "jacobjinkelly@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/J/240_72_133/120.png", + "login": "Jacob Kelly", + "name": "Jacob Kelly", + "type": null + }, + "commits": 7, + "deletions": 159 + }, + { + "additions": 3, + "author": { + "email": "akvi@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/A/159_195_72/120.png", + "login": "Akvile Zemgulyte", + "name": "Akvile Zemgulyte", + "type": null + }, + "commits": 2, + "deletions": 1 + }, + { + "additions": 5, + "author": { + "email": "mlbileschi@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/M/226_116_189/120.png", + "login": "mlbileschi", + "name": "mlbileschi", + "type": null + }, + "commits": 1, + "deletions": 4 + }, + { + "additions": 34, + "author": { + "email": "noreply@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/D/231_155_135/120.png", + "login": "DeepMind", + "name": "DeepMind", + "type": null + }, + "commits": 1, + "deletions": 8 + }, + { + "additions": 1, + "author": { + "email": "bchetioui@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/B/130_221_137/120.png", + "login": "Benjamin Chetioui", + "name": "Benjamin Chetioui", + "type": null + }, + "commits": 1, + "deletions": 0 + }, + { + "additions": 15, + "author": { + "email": "vanderplas@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/J/186_135_57/120.png", + "login": "Jake VanderPlas", + "name": "Jake VanderPlas", + "type": null + }, + "commits": 1, + "deletions": 2 + }, + { + "additions": 72, + "author": { + "email": "koretadaniel@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/F/173_120_149/120.png", + "login": "Foromo Daniel Soromou", + "name": "Foromo Daniel Soromou", + "type": null + }, + "commits": 1, + "deletions": 6 + }, + { + "additions": 3828, + "author": { + "email": "rpachauri@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/R/69_222_172/120.png", + "login": "Ryan Pachauri", + "name": "Ryan Pachauri", + "type": null + }, + "commits": 1, + "deletions": 3168 + }, + { + "additions": 1, + "author": { + "email": "aliia@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/A/88_244_199/120.png", + "login": "Aliia Khasanova", + "name": "Aliia Khasanova", + "type": null + }, + "commits": 1, + "deletions": 1 + }, + { + "additions": 10, + "author": { + "email": "vwbaker@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/T/187_206_136/120.png", + "login": "Tori Baker", + "name": "Tori Baker", + "type": null + }, + "commits": 1, + "deletions": 10 + }, + { + "additions": 1, + "author": { + "email": "cowie@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/A/127_238_163/120.png", + "login": "Andrew Cowie", + "name": "Andrew Cowie", + "type": null + }, + "commits": 1, + "deletions": 1 + } + ], + "change_files": null, + "commit_count": 244, + "commit_count_in_all_branches": 246, + "deletions": 16005 + } +} diff --git a/examples/workflows/research-hotspot-tracker/data/raw/NSCCN_AlphaFold3_contributors.json b/examples/workflows/research-hotspot-tracker/data/raw/NSCCN_AlphaFold3_contributors.json new file mode 100644 index 0000000..9cdaec8 --- /dev/null +++ b/examples/workflows/research-hotspot-tracker/data/raw/NSCCN_AlphaFold3_contributors.json @@ -0,0 +1,211 @@ +{ + "ok": true, + "data": { + "list": [ + { + "contribution_perc": "60.59%", + "contributions": 206, + "email": "augustinzidek@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/A/233_155_153/120.png", + "login": null, + "name": "augustin zidek", + "type": null + }, + { + "contribution_perc": "4.71%", + "contributions": 16, + "email": "49699333+dependabot[bot]@users.noreply.github.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/D/241_157_191/120.png", + "login": null, + "name": "dependabot[bot]", + "type": null + }, + { + "contribution_perc": "3.24%", + "contributions": 11, + "email": "jabramson@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/J/165_135_246/120.png", + "login": null, + "name": "josh abramson", + "type": null + }, + { + "contribution_perc": "2.65%", + "contributions": 9, + "email": "jamessspencer@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/J/188_135_35/120.png", + "login": null, + "name": "james spencer", + "type": null + }, + { + "contribution_perc": "2.06%", + "contributions": 7, + "email": "jacobjinkelly@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/J/240_72_133/120.png", + "login": null, + "name": "jacob kelly", + "type": null + }, + { + "contribution_perc": "1.18%", + "contributions": 4, + "email": "ashutoshkumarsingh0x@gmail.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/A/142_220_202/120.png", + "login": null, + "name": "ashutosh0x", + "type": null + }, + { + "contribution_perc": "1.18%", + "contributions": 4, + "email": "rocklover88@proton.me", + "id": null, + "image_url": "system/lets/letter_avatars/2/L/180_135_251/120.png", + "login": null, + "name": "linchimingrocks", + "type": null + }, + { + "contribution_perc": "1.18%", + "contributions": 4, + "email": "pasqmigl97@gmail.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/P/59_195_89/120.png", + "login": null, + "name": "pasqm", + "type": null + }, + { + "contribution_perc": "0.88%", + "contributions": 3, + "email": "ccoulombe@users.noreply.github.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/C/219_200_69/120.png", + "login": null, + "name": "charles coulombe", + "type": null + }, + { + "contribution_perc": "0.88%", + "contributions": 3, + "email": "j.j.carpenter@bham.ac.uk", + "id": null, + "image_url": "system/lets/letter_avatars/2/J/174_177_222/120.png", + "login": null, + "name": "james carpenter (advanced research computing)", + "type": null + }, + { + "contribution_perc": "0.88%", + "contributions": 3, + "email": "zohaibshahid7035@gmail.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/Z/142_125_214/120.png", + "login": null, + "name": "zohaib shahid", + "type": null + }, + { + "contribution_perc": "0.88%", + "contributions": 3, + "email": "ook077358@gmail.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/O/233_192_237/120.png", + "login": null, + "name": "ook077358-lab", + "type": null + }, + { + "contribution_perc": "0.59%", + "contributions": 2, + "email": "akvi@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/A/159_195_72/120.png", + "login": null, + "name": "akvile zemgulyte", + "type": null + }, + { + "contribution_perc": "0.59%", + "contributions": 2, + "email": "alex.morehead@gmail.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/A/220_77_167/120.png", + "login": null, + "name": "alex morehead", + "type": null + }, + { + "contribution_perc": "0.59%", + "contributions": 2, + "email": "avisinha1711@gmail.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/A/195_119_88/120.png", + "login": null, + "name": "avi sinha", + "type": null + }, + { + "contribution_perc": "0.59%", + "contributions": 2, + "email": "53904580+dailypartita@users.noreply.github.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/D/169_173_189/120.png", + "login": null, + "name": "dp", + "type": null + }, + { + "contribution_perc": "0.88%", + "contributions": 3, + "email": "90102437+dibyx@users.noreply.github.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/D/235_202_125/120.png", + "login": null, + "name": "debasish", + "type": null + }, + { + "contribution_perc": "0.59%", + "contributions": 2, + "email": "o.kenway@ucl.ac.uk", + "id": null, + "image_url": "system/lets/letter_avatars/2/D/124_142_87/120.png", + "login": null, + "name": "dr owain kenway", + "type": null + }, + { + "contribution_perc": "0.59%", + "contributions": 2, + "email": "", + "id": null, + "image_url": "system/lets/letter_avatars/2/O/74_243_75/120.png", + "login": null, + "name": "ojas shelke", + "type": null + }, + { + "contribution_perc": "0.59%", + "contributions": 2, + "email": "48257736+pasqm@users.noreply.github.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/P/74_243_75/120.png", + "login": null, + "name": "pasquale miglionico", + "type": null + } + ], + "total_count": 63 + }, + "meta": { + "total_count": 63 + } +} diff --git a/examples/workflows/research-hotspot-tracker/data/raw/NSCCN_AlphaFold3_info.json b/examples/workflows/research-hotspot-tracker/data/raw/NSCCN_AlphaFold3_info.json new file mode 100644 index 0000000..8bf5d6b --- /dev/null +++ b/examples/workflows/research-hotspot-tracker/data/raw/NSCCN_AlphaFold3_info.json @@ -0,0 +1,45 @@ +{ + "ok": true, + "data": { + "author": { + "id": 147738, + "image_url": "images/avatars/Organization/147738?t=1776128929", + "login": "NSCCN", + "name": "超算开源", + "type": "Organization" + }, + "clone_url": "https://gitlink.org.cn/NSCCN/AlphaFold3.git", + "contributor_users_count": 0, + "default_branch": "main", + "empty": false, + "first_sync": true, + "forked_count": 0, + "forked_from_project_id": null, + "full_name": "NSCCN/AlphaFold3", + "identifier": "AlphaFold3", + "issues_count": 0, + "mirror": true, + "mirror_num": 1, + "mirror_status": 0, + "mirror_url": "https://github.com/google-deepmind/alphafold3.git", + "name": "AlphaFold3", + "open_devops": false, + "permission": "", + "praised": false, + "praises_count": 0, + "private": false, + "project_id": 1528739, + "project_identifier": "AlphaFold3", + "pull_requests_count": 0, + "repo_id": 1530352, + "size": "47.2 MB", + "ssh_url": "git@code.gitlink.org.cn:NSCCN/AlphaFold3.git", + "status": 1, + "type": 1, + "version_releases_count": 0, + "version_releasesed_count": 0, + "versions_count": 0, + "watched": false, + "watchers_count": 0 + } +} diff --git a/examples/workflows/research-hotspot-tracker/data/raw/NSCCN_AlphaFold3_languages.json b/examples/workflows/research-hotspot-tracker/data/raw/NSCCN_AlphaFold3_languages.json new file mode 100644 index 0000000..2358921 --- /dev/null +++ b/examples/workflows/research-hotspot-tracker/data/raw/NSCCN_AlphaFold3_languages.json @@ -0,0 +1,10 @@ +{ + "ok": true, + "data": { + "C++": "14.0%", + "CMake": "0.2%", + "Dockerfile": "0.3%", + "Python": "85.1%", + "Shell": "0.4%" + } +} diff --git a/examples/workflows/research-hotspot-tracker/data/raw/NSCCN_RoseTTAFold_code_stats.json b/examples/workflows/research-hotspot-tracker/data/raw/NSCCN_RoseTTAFold_code_stats.json new file mode 100644 index 0000000..b56c7e9 --- /dev/null +++ b/examples/workflows/research-hotspot-tracker/data/raw/NSCCN_RoseTTAFold_code_stats.json @@ -0,0 +1,39 @@ +{ + "ok": true, + "data": { + "additions": 423167, + "author_count": 2, + "authors": [ + { + "additions": 423140, + "author": { + "email": "minkbaek@digs", + "id": null, + "image_url": "system/lets/letter_avatars/2/M/116_223_50/120.png", + "login": "Minkyung Baek", + "name": "Minkyung Baek", + "type": null + }, + "commits": 26, + "deletions": 45075 + }, + { + "additions": 27, + "author": { + "email": "minkbaek@uw.edu", + "id": null, + "image_url": "system/lets/letter_avatars/2/M/116_223_50/120.png", + "login": "Minkyung Baek", + "name": "Minkyung Baek", + "type": null + }, + "commits": 8, + "deletions": 152 + } + ], + "change_files": null, + "commit_count": 34, + "commit_count_in_all_branches": 40, + "deletions": 45227 + } +} diff --git a/examples/workflows/research-hotspot-tracker/data/raw/NSCCN_RoseTTAFold_contributors.json b/examples/workflows/research-hotspot-tracker/data/raw/NSCCN_RoseTTAFold_contributors.json new file mode 100644 index 0000000..54a4fd1 --- /dev/null +++ b/examples/workflows/research-hotspot-tracker/data/raw/NSCCN_RoseTTAFold_contributors.json @@ -0,0 +1,211 @@ +{ + "ok": true, + "data": { + "list": [ + { + "contribution_perc": "30.68%", + "contributions": 27, + "email": "minkbaek@digs", + "id": null, + "image_url": "system/lets/letter_avatars/2/M/116_223_50/120.png", + "login": null, + "name": "minkyung baek", + "type": null + }, + { + "contribution_perc": "15.91%", + "contributions": 14, + "email": "jcastellanos@neoleukin.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/J/65_152_142/120.png", + "login": null, + "name": "javier castellanos", + "type": null + }, + { + "contribution_perc": "14.77%", + "contributions": 13, + "email": "minkbaek@uw.edu", + "id": null, + "image_url": "system/lets/letter_avatars/2/M/116_223_50/120.png", + "login": null, + "name": "minkyung baek", + "type": null + }, + { + "contribution_perc": "6.82%", + "contributions": 6, + "email": "38662498+avivko@users.noreply.github.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/A/229_185_186/120.png", + "login": null, + "name": "avivko", + "type": null + }, + { + "contribution_perc": "5.68%", + "contributions": 5, + "email": "andreasantoro.pvt@gmail.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/A/206_114_54/120.png", + "login": null, + "name": "andrea santoro", + "type": null + }, + { + "contribution_perc": "3.41%", + "contributions": 3, + "email": "bc06026@uga.edu", + "id": null, + "image_url": "system/lets/letter_avatars/2/B/109_232_216/120.png", + "login": null, + "name": "ben cronheim", + "type": null + }, + { + "contribution_perc": "2.27%", + "contributions": 2, + "email": "abdullah.kahraman@gmail.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/A/61_162_123/120.png", + "login": null, + "name": "abdullah kahraman", + "type": null + }, + { + "contribution_perc": "2.27%", + "contributions": 2, + "email": "xubeisi@gmail.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/B/127_238_163/120.png", + "login": null, + "name": "beisi xu", + "type": null + }, + { + "contribution_perc": "2.27%", + "contributions": 2, + "email": "eltociear@gmail.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/I/236_194_58/120.png", + "login": null, + "name": "ikko ashimine", + "type": null + }, + { + "contribution_perc": "2.27%", + "contributions": 2, + "email": "javierbq@gmail.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/J/65_152_142/120.png", + "login": null, + "name": "javier castellanos", + "type": null + }, + { + "contribution_perc": "2.27%", + "contributions": 2, + "email": "huhlim@gmail.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/L/188_239_142/120.png", + "login": null, + "name": "lim heo", + "type": null + }, + { + "contribution_perc": "2.27%", + "contributions": 2, + "email": "arthur200126@gmail.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/M/157_132_101/120.png", + "login": null, + "name": "mingye wang", + "type": null + }, + { + "contribution_perc": "1.14%", + "contributions": 1, + "email": "mamahmoudzadeh@gmail.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/A/219_95_187/120.png", + "login": null, + "name": "ali m", + "type": null + }, + { + "contribution_perc": "1.14%", + "contributions": 1, + "email": "47426058+ghbhc@users.noreply.github.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/B/219_95_187/120.png", + "login": null, + "name": "ben", + "type": null + }, + { + "contribution_perc": "1.14%", + "contributions": 1, + "email": "88146749+zemu-unile@users.noreply.github.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/C/244_117_225/120.png", + "login": null, + "name": "christoph siegert", + "type": null + }, + { + "contribution_perc": "1.14%", + "contributions": 1, + "email": "christoph.siegert@uni-leipzig.de", + "id": null, + "image_url": "system/lets/letter_avatars/2/C/244_117_225/120.png", + "login": null, + "name": "christoph siegert", + "type": null + }, + { + "contribution_perc": "1.14%", + "contributions": 1, + "email": "59423916+runitralph@users.noreply.github.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/R/244_117_225/120.png", + "login": null, + "name": "raphael", + "type": null + }, + { + "contribution_perc": "1.14%", + "contributions": 1, + "email": "shawncal@microsoft.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/S/194_161_63/120.png", + "login": null, + "name": "shawn callegari", + "type": null + }, + { + "contribution_perc": "1.14%", + "contributions": 1, + "email": "bbaker@cs.hmc.edu", + "id": null, + "image_url": "system/lets/letter_avatars/2/H/165_185_100/120.png", + "login": null, + "name": "hmc-cs-bbaker", + "type": null + }, + { + "contribution_perc": "1.14%", + "contributions": 1, + "email": "88408493+neilfleckscri@users.noreply.github.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/N/121_147_160/120.png", + "login": null, + "name": "neilfleckscri", + "type": null + } + ], + "total_count": 20 + }, + "meta": { + "total_count": 20 + } +} diff --git a/examples/workflows/research-hotspot-tracker/data/raw/NSCCN_RoseTTAFold_info.json b/examples/workflows/research-hotspot-tracker/data/raw/NSCCN_RoseTTAFold_info.json new file mode 100644 index 0000000..46bcf6d --- /dev/null +++ b/examples/workflows/research-hotspot-tracker/data/raw/NSCCN_RoseTTAFold_info.json @@ -0,0 +1,45 @@ +{ + "ok": true, + "data": { + "author": { + "id": 147738, + "image_url": "images/avatars/Organization/147738?t=1776128929", + "login": "NSCCN", + "name": "超算开源", + "type": "Organization" + }, + "clone_url": "https://gitlink.org.cn/NSCCN/RoseTTAFold.git", + "contributor_users_count": 0, + "default_branch": "main", + "empty": false, + "first_sync": true, + "forked_count": 0, + "forked_from_project_id": null, + "full_name": "NSCCN/RoseTTAFold", + "identifier": "RoseTTAFold", + "issues_count": 0, + "mirror": true, + "mirror_num": 1, + "mirror_status": 0, + "mirror_url": "https://github.com/RosettaCommons/RoseTTAFold.git", + "name": "RoseTTAFold", + "open_devops": false, + "permission": "", + "praised": false, + "praises_count": 0, + "private": false, + "project_id": 1541662, + "project_identifier": "RoseTTAFold", + "pull_requests_count": 0, + "repo_id": 1543274, + "size": "172.1 MB", + "ssh_url": "git@code.gitlink.org.cn:NSCCN/RoseTTAFold.git", + "status": 1, + "type": 1, + "version_releases_count": 0, + "version_releasesed_count": 0, + "versions_count": 0, + "watched": false, + "watchers_count": 0 + } +} diff --git a/examples/workflows/research-hotspot-tracker/data/raw/NSCCN_RoseTTAFold_languages.json b/examples/workflows/research-hotspot-tracker/data/raw/NSCCN_RoseTTAFold_languages.json new file mode 100644 index 0000000..f862792 --- /dev/null +++ b/examples/workflows/research-hotspot-tracker/data/raw/NSCCN_RoseTTAFold_languages.json @@ -0,0 +1,7 @@ +{ + "ok": true, + "data": { + "Python": "97.6%", + "Shell": "2.4%" + } +} diff --git a/examples/workflows/research-hotspot-tracker/data/raw/Supercomputing_alphafold_code_stats.json b/examples/workflows/research-hotspot-tracker/data/raw/Supercomputing_alphafold_code_stats.json new file mode 100644 index 0000000..34cc8c9 --- /dev/null +++ b/examples/workflows/research-hotspot-tracker/data/raw/Supercomputing_alphafold_code_stats.json @@ -0,0 +1,377 @@ +{ + "ok": true, + "data": { + "additions": 54960, + "author_count": 28, + "authors": [ + { + "additions": 8153, + "author": { + "email": "augustinzidek@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/A/233_155_153/120.png", + "login": "Augustin Zidek", + "name": "Augustin Zidek", + "type": null + }, + "commits": 67, + "deletions": 4838 + }, + { + "additions": 319, + "author": { + "email": "htomlinson@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/H/178_217_57/120.png", + "login": "Hamish Tomlinson", + "name": "Hamish Tomlinson", + "type": null + }, + "commits": 29, + "deletions": 183 + }, + { + "additions": 551, + "author": { + "email": "rpachauri@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/R/69_222_172/120.png", + "login": "Ryan Pachauri", + "name": "Ryan Pachauri", + "type": null + }, + "commits": 15, + "deletions": 248 + }, + { + "additions": 389, + "author": { + "email": "noreply@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/D/231_155_135/120.png", + "login": "DeepMind", + "name": "DeepMind", + "type": null + }, + "commits": 14, + "deletions": 141 + }, + { + "additions": 1110, + "author": { + "email": "htiku@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/H/145_154_217/120.png", + "login": "Harsh Tiku", + "name": "Harsh Tiku", + "type": null + }, + "commits": 10, + "deletions": 190 + }, + { + "additions": 106, + "author": { + "email": "tomward@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/T/220_77_167/120.png", + "login": "Tom Ward", + "name": "Tom Ward", + "type": null + }, + "commits": 10, + "deletions": 150 + }, + { + "additions": 78, + "author": { + "email": "vanderplas@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/J/186_135_57/120.png", + "login": "Jake VanderPlas", + "name": "Jake VanderPlas", + "type": null + }, + "commits": 6, + "deletions": 73 + }, + { + "additions": 70, + "author": { + "email": "richevans@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/R/172_161_105/120.png", + "login": "Rich Evans", + "name": "Rich Evans", + "type": null + }, + "commits": 6, + "deletions": 265 + }, + { + "additions": 12, + "author": { + "email": "phawkins@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/P/241_125_89/120.png", + "login": "Peter Hawkins", + "name": "Peter Hawkins", + "type": null + }, + "commits": 5, + "deletions": 12 + }, + { + "additions": 13, + "author": { + "email": "tfgg@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/T/229_185_186/120.png", + "login": "Tim Green", + "name": "Tim Green", + "type": null + }, + "commits": 5, + "deletions": 7 + }, + { + "additions": 38, + "author": { + "email": "cowie@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/A/127_238_163/120.png", + "login": "Andrew Cowie", + "name": "Andrew Cowie", + "type": null + }, + "commits": 4, + "deletions": 16 + }, + { + "additions": 49, + "author": { + "email": "alexcr@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/A/83_160_66/120.png", + "login": "Ali Cowen-Rivers", + "name": "Ali Cowen-Rivers", + "type": null + }, + "commits": 3, + "deletions": 16 + }, + { + "additions": 15, + "author": { + "email": "sbodenstein@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/S/215_141_69/120.png", + "login": "Sebastian Bodenstein", + "name": "Sebastian Bodenstein", + "type": null + }, + "commits": 3, + "deletions": 14 + }, + { + "additions": 32, + "author": { + "email": "abridgland@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/A/42_205_125/120.png", + "login": "Alex Bridgland", + "name": "Alex Bridgland", + "type": null + }, + "commits": 3, + "deletions": 4 + }, + { + "additions": 8343, + "author": { + "email": "augustinzidek@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/A/233_155_153/120.png", + "login": "Augustin-Zidek", + "name": "Augustin-Zidek", + "type": null + }, + "commits": 2, + "deletions": 1201 + }, + { + "additions": 54, + "author": { + "email": "mfigurnov@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/M/187_229_206/120.png", + "login": "Michael Figurnov", + "name": "Michael Figurnov", + "type": null + }, + "commits": 2, + "deletions": 55 + }, + { + "additions": 11074, + "author": { + "email": "dlasecki@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/D/116_223_50/120.png", + "login": "Dariusz Lasecki", + "name": "Dariusz Lasecki", + "type": null + }, + "commits": 2, + "deletions": 918 + }, + { + "additions": 10, + "author": { + "email": "jcavojska@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/J/135_134_158/120.png", + "login": "Jana Cavojska", + "name": "Jana Cavojska", + "type": null + }, + "commits": 2, + "deletions": 10 + }, + { + "additions": 6, + "author": { + "email": "tomhennigan@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/T/109_232_216/120.png", + "login": "Tom Hennigan", + "name": "Tom Hennigan", + "type": null + }, + "commits": 1, + "deletions": 1 + }, + { + "additions": 0, + "author": { + "email": "akvi@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/A/159_195_72/120.png", + "login": "Akvile Zemgulyte", + "name": "Akvile Zemgulyte", + "type": null + }, + "commits": 1, + "deletions": 21 + }, + { + "additions": 21993, + "author": { + "email": "augustin@zidek.eu", + "id": null, + "image_url": "system/lets/letter_avatars/2/A/233_155_153/120.png", + "login": "Augustin-Zidek", + "name": "Augustin-Zidek", + "type": null + }, + "commits": 1, + "deletions": 0 + }, + { + "additions": 3, + "author": { + "email": "mattjj@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/M/83_160_66/120.png", + "login": "Matthew Johnson", + "name": "Matthew Johnson", + "type": null + }, + "commits": 1, + "deletions": 3 + }, + { + "additions": 2527, + "author": { + "email": "stunya@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/S/227_107_55/120.png", + "login": "Saran Tunyasuvunakool", + "name": "Saran Tunyasuvunakool", + "type": null + }, + "commits": 1, + "deletions": 1083 + }, + { + "additions": 0, + "author": { + "email": "timothy.green@gmail.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/T/229_185_186/120.png", + "login": "Tim Green", + "name": "Tim Green", + "type": null + }, + "commits": 1, + "deletions": 1 + }, + { + "additions": 1, + "author": { + "email": "hanajoo@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/H/84_238_129/120.png", + "login": "Hana Joo", + "name": "Hana Joo", + "type": null + }, + "commits": 1, + "deletions": 1 + }, + { + "additions": 1, + "author": { + "email": "drmh@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/M/159_195_72/120.png", + "login": "Martin Huschenbett", + "name": "Martin Huschenbett", + "type": null + }, + "commits": 1, + "deletions": 1 + }, + { + "additions": 6, + "author": { + "email": "jabramson@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/J/165_135_246/120.png", + "login": "Josh Abramson", + "name": "Josh Abramson", + "type": null + }, + "commits": 1, + "deletions": 1 + }, + { + "additions": 7, + "author": { + "email": "rechen@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/R/236_194_58/120.png", + "login": "Rebecca Chen", + "name": "Rebecca Chen", + "type": null + }, + "commits": 1, + "deletions": 7 + } + ], + "change_files": null, + "commit_count": 198, + "commit_count_in_all_branches": 198, + "deletions": 9460 + } +} diff --git a/examples/workflows/research-hotspot-tracker/data/raw/Supercomputing_alphafold_contributors.json b/examples/workflows/research-hotspot-tracker/data/raw/Supercomputing_alphafold_contributors.json new file mode 100644 index 0000000..bbe0611 --- /dev/null +++ b/examples/workflows/research-hotspot-tracker/data/raw/Supercomputing_alphafold_contributors.json @@ -0,0 +1,211 @@ +{ + "ok": true, + "data": { + "list": [ + { + "contribution_perc": "8.59%", + "contributions": 69, + "email": "augustinzidek@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/A/233_155_153/120.png", + "login": null, + "name": "augustin zidek", + "type": null + }, + { + "contribution_perc": "8.22%", + "contributions": 66, + "email": "wttat8600@gmail.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/W/192_233_116/120.png", + "login": null, + "name": "wttat", + "type": null + }, + { + "contribution_perc": "6.23%", + "contributions": 50, + "email": "chunan.liu@ucl.ac.uk", + "id": null, + "image_url": "system/lets/letter_avatars/2/C/75_191_146/120.png", + "login": null, + "name": "chunan", + "type": null + }, + { + "contribution_perc": "7.22%", + "contributions": 58, + "email": "francesco.oteri@gmail.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/F/142_125_214/120.png", + "login": null, + "name": "francesco oteri", + "type": null + }, + { + "contribution_perc": "6.72%", + "contributions": 54, + "email": "33014714+yaoyinying@users.noreply.github.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/Y/222_198_220/120.png", + "login": null, + "name": "yaoyy.hi@gmail.com", + "type": null + }, + { + "contribution_perc": "4.48%", + "contributions": 36, + "email": "tru@pasteur.fr", + "id": null, + "image_url": "system/lets/letter_avatars/2/T/172_161_105/120.png", + "login": null, + "name": "tru huynh", + "type": null + }, + { + "contribution_perc": "3.61%", + "contributions": 29, + "email": "htomlinson@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/H/178_217_57/120.png", + "login": null, + "name": "hamish tomlinson", + "type": null + }, + { + "contribution_perc": "2.62%", + "contributions": 21, + "email": "", + "id": null, + "image_url": "system/lets/letter_avatars/2/Y/240_163_100/120.png", + "login": null, + "name": "yaoyy.hi", + "type": null + }, + { + "contribution_perc": "2.37%", + "contributions": 19, + "email": "bio.chunanliu@gmail.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/C/223_176_135/120.png", + "login": null, + "name": "chunan liu", + "type": null + }, + { + "contribution_perc": "2.12%", + "contributions": 17, + "email": "meesters@uni-mainz.de", + "id": null, + "image_url": "system/lets/letter_avatars/2/C/225_154_220/120.png", + "login": null, + "name": "christian meesters", + "type": null + }, + { + "contribution_perc": "1.87%", + "contributions": 15, + "email": "rpachauri@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/R/69_222_172/120.png", + "login": null, + "name": "ryan pachauri", + "type": null + }, + { + "contribution_perc": "1.74%", + "contributions": 14, + "email": "noreply@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/D/231_155_135/120.png", + "login": null, + "name": "deepmind", + "type": null + }, + { + "contribution_perc": "1.74%", + "contributions": 14, + "email": "umberto.lupo@gmail.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/U/222_198_220/120.png", + "login": null, + "name": "umberto lupo", + "type": null + }, + { + "contribution_perc": "1.62%", + "contributions": 13, + "email": "33123184+dimamolod@users.noreply.github.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/D/165_185_100/120.png", + "login": null, + "name": "dima", + "type": null + }, + { + "contribution_perc": "1.37%", + "contributions": 11, + "email": "geoffrey.yu96@icloud.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/G/118_211_238/120.png", + "login": null, + "name": "geoffrey yu", + "type": null + }, + { + "contribution_perc": "1.49%", + "contributions": 12, + "email": "dmolodenskiy@embl-hamburg.de", + "id": null, + "image_url": "system/lets/letter_avatars/2/D/233_95_125/120.png", + "login": null, + "name": "dima molodenskiy", + "type": null + }, + { + "contribution_perc": "1.25%", + "contributions": 10, + "email": "htiku@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/H/145_154_217/120.png", + "login": null, + "name": "harsh tiku", + "type": null + }, + { + "contribution_perc": "1.25%", + "contributions": 10, + "email": "oliver@peptone.io", + "id": null, + "image_url": "system/lets/letter_avatars/2/O/185_229_243/120.png", + "login": null, + "name": "oliver dutton", + "type": null + }, + { + "contribution_perc": "1.25%", + "contributions": 10, + "email": "tomward@google.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/T/220_77_167/120.png", + "login": null, + "name": "tom ward", + "type": null + }, + { + "contribution_perc": "1.12%", + "contributions": 9, + "email": "mdamgaard@biolib.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/M/52_240_224/120.png", + "login": null, + "name": "mads d. pedersen", + "type": null + } + ], + "total_count": 149 + }, + "meta": { + "total_count": 149 + } +} diff --git a/examples/workflows/research-hotspot-tracker/data/raw/Supercomputing_alphafold_info.json b/examples/workflows/research-hotspot-tracker/data/raw/Supercomputing_alphafold_info.json new file mode 100644 index 0000000..f734b95 --- /dev/null +++ b/examples/workflows/research-hotspot-tracker/data/raw/Supercomputing_alphafold_info.json @@ -0,0 +1,45 @@ +{ + "ok": true, + "data": { + "author": { + "id": 143149, + "image_url": "images/avatars/Organization/143149?t=1756795747", + "login": "Supercomputing", + "name": "Supercomputing", + "type": "Organization" + }, + "clone_url": "https://gitlink.org.cn/Supercomputing/alphafold.git", + "contributor_users_count": 0, + "default_branch": "main", + "empty": false, + "first_sync": true, + "forked_count": 0, + "forked_from_project_id": null, + "full_name": "Supercomputing/alphafold", + "identifier": "alphafold", + "issues_count": 0, + "mirror": true, + "mirror_num": 1, + "mirror_status": 0, + "mirror_url": "https://github.com/deepmind/alphafold", + "name": "alphafold", + "open_devops": false, + "permission": "", + "praised": false, + "praises_count": 0, + "private": false, + "project_id": 1463118, + "project_identifier": "alphafold", + "pull_requests_count": 0, + "repo_id": 1464731, + "size": "18.5 MB", + "ssh_url": "git@code.gitlink.org.cn:Supercomputing/alphafold.git", + "status": 1, + "type": 1, + "version_releases_count": 0, + "version_releasesed_count": 0, + "versions_count": 0, + "watched": false, + "watchers_count": 0 + } +} diff --git a/examples/workflows/research-hotspot-tracker/data/raw/Supercomputing_alphafold_languages.json b/examples/workflows/research-hotspot-tracker/data/raw/Supercomputing_alphafold_languages.json new file mode 100644 index 0000000..113d56e --- /dev/null +++ b/examples/workflows/research-hotspot-tracker/data/raw/Supercomputing_alphafold_languages.json @@ -0,0 +1,9 @@ +{ + "ok": true, + "data": { + "Dockerfile": "0.4%", + "Jupyter Notebook": "0.1%", + "Python": "97.5%", + "Shell": "2.0%" + } +} diff --git a/examples/workflows/research-hotspot-tracker/data/raw/scnc_openfold_code_stats.json b/examples/workflows/research-hotspot-tracker/data/raw/scnc_openfold_code_stats.json new file mode 100644 index 0000000..7881b72 --- /dev/null +++ b/examples/workflows/research-hotspot-tracker/data/raw/scnc_openfold_code_stats.json @@ -0,0 +1,130 @@ +{ + "ok": true, + "data": { + "additions": 166097, + "author_count": 9, + "authors": [ + { + "additions": 163689, + "author": { + "email": "gahdritz@gmail.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/G/206_115_165/120.png", + "login": "Gustaf Ahdritz", + "name": "Gustaf Ahdritz", + "type": null + }, + "commits": 534, + "deletions": 18066 + }, + { + "additions": 1422, + "author": { + "email": "sachinkadyan7@gmail.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/S/142_140_188/120.png", + "login": "Sachin Kadyan", + "name": "Sachin Kadyan", + "type": null + }, + "commits": 51, + "deletions": 209 + }, + { + "additions": 917, + "author": { + "email": "gahdritz@gmail.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/G/52_240_224/120.png", + "login": "Gustaf", + "name": "Gustaf", + "type": null + }, + "commits": 7, + "deletions": 188 + }, + { + "additions": 25, + "author": { + "email": "christina.floristean@gmail.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/C/88_149_110/120.png", + "login": "Christina Floristean", + "name": "Christina Floristean", + "type": null + }, + "commits": 4, + "deletions": 29 + }, + { + "additions": 16, + "author": { + "email": "sachinkadyan7@gmail.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/S/81_191_129/120.png", + "login": "sachinkadyan7", + "name": "sachinkadyan7", + "type": null + }, + "commits": 4, + "deletions": 5 + }, + { + "additions": 22, + "author": { + "email": "alquraishi@users.noreply.github.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/M/169_162_140/120.png", + "login": "Mohammed AlQuraishi", + "name": "Mohammed AlQuraishi", + "type": null + }, + "commits": 1, + "deletions": 0 + }, + { + "additions": 0, + "author": { + "email": "97625454+jnwei@users.noreply.github.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/J/229_108_155/120.png", + "login": "Jennifer Wei", + "name": "Jennifer Wei", + "type": null + }, + "commits": 1, + "deletions": 0 + }, + { + "additions": 1, + "author": { + "email": "0755dimitri@gmail.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/C/180_135_251/120.png", + "login": "controny", + "name": "controny", + "type": null + }, + "commits": 1, + "deletions": 1 + }, + { + "additions": 5, + "author": { + "email": "yoels@il.ibm.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/Y/62_200_234/120.png", + "login": "yoel shoshan", + "name": "yoel shoshan", + "type": null + }, + "commits": 1, + "deletions": 5 + } + ], + "change_files": null, + "commit_count": 604, + "commit_count_in_all_branches": 1427, + "deletions": 18503 + } +} diff --git a/examples/workflows/research-hotspot-tracker/data/raw/scnc_openfold_contributors.json b/examples/workflows/research-hotspot-tracker/data/raw/scnc_openfold_contributors.json new file mode 100644 index 0000000..1675b4b --- /dev/null +++ b/examples/workflows/research-hotspot-tracker/data/raw/scnc_openfold_contributors.json @@ -0,0 +1,211 @@ +{ + "ok": true, + "data": { + "list": [ + { + "contribution_perc": "28.39%", + "contributions": 707, + "email": "gahdritz@gmail.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/G/206_115_165/120.png", + "login": null, + "name": "gustaf ahdritz", + "type": null + }, + { + "contribution_perc": "7.35%", + "contributions": 183, + "email": "geoffrey.yu96@icloud.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/G/118_211_238/120.png", + "login": null, + "name": "geoffrey yu", + "type": null + }, + { + "contribution_perc": "6.67%", + "contributions": 166, + "email": "tabuchi.akihiro@fujitsu.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/A/132_145_172/120.png", + "login": null, + "name": "akihiro tabuchi", + "type": null + }, + { + "contribution_perc": "6.67%", + "contributions": 166, + "email": "oyama.yosuke@fujitsu.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/O/133_140_134/120.png", + "login": null, + "name": "oyamay", + "type": null + }, + { + "contribution_perc": "6.91%", + "contributions": 172, + "email": "sachinkadyan7@gmail.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/S/142_140_188/120.png", + "login": null, + "name": "sachin kadyan", + "type": null + }, + { + "contribution_perc": "4.14%", + "contributions": 103, + "email": "christina.floristean@gmail.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/C/88_149_110/120.png", + "login": null, + "name": "christina floristean", + "type": null + }, + { + "contribution_perc": "5.26%", + "contributions": 131, + "email": "jennifer.wei@omsf.io", + "id": null, + "image_url": "system/lets/letter_avatars/2/J/62_200_234/120.png", + "login": null, + "name": "jnwei", + "type": null + }, + { + "contribution_perc": "3.65%", + "contributions": 91, + "email": "whereisthelux@gmail.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/J/67_157_94/120.png", + "login": null, + "name": "jennifer", + "type": null + }, + { + "contribution_perc": "2.53%", + "contributions": 63, + "email": "3505568+jflucier@users.noreply.github.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/J/73_190_183/120.png", + "login": null, + "name": "jflucier", + "type": null + }, + { + "contribution_perc": "2.45%", + "contributions": 61, + "email": "97625454+jnwei@users.noreply.github.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/J/229_108_155/120.png", + "login": null, + "name": "jennifer wei", + "type": null + }, + { + "contribution_perc": "2.41%", + "contributions": 60, + "email": "hiroyuki.akamatsu12@metro.co.jp", + "id": null, + "image_url": "system/lets/letter_avatars/2/A/145_178_168/120.png", + "login": null, + "name": "akamatsu", + "type": null + }, + { + "contribution_perc": "1.29%", + "contributions": 32, + "email": "jacknicoludis@gmail.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/J/233_188_180/120.png", + "login": null, + "name": "jack nicoludis", + "type": null + }, + { + "contribution_perc": "1.85%", + "contributions": 46, + "email": "jeon_jaesung@metro.co.jp", + "id": null, + "image_url": "system/lets/letter_avatars/2/J/74_243_75/120.png", + "login": null, + "name": "jasesung jeon", + "type": null + }, + { + "contribution_perc": "1.12%", + "contributions": 28, + "email": "yianni.anastopoulos@unnaturalproducts.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/I/150_190_213/120.png", + "login": null, + "name": "ioannisa92", + "type": null + }, + { + "contribution_perc": "0.92%", + "contributions": 23, + "email": "tabuchi.akihiro@jp.fujitsu.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/A/186_135_57/120.png", + "login": null, + "name": "akihiro tabuchi", + "type": null + }, + { + "contribution_perc": "0.88%", + "contributions": 22, + "email": "44894955+dingquanyu@users.noreply.github.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/D/181_233_37/120.png", + "login": null, + "name": "dingquan yu", + "type": null + }, + { + "contribution_perc": "0.88%", + "contributions": 22, + "email": "sam@cyrusbio.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/S/34_208_66/120.png", + "login": null, + "name": "sam deluca", + "type": null + }, + { + "contribution_perc": "0.80%", + "contributions": 20, + "email": "geoffreyyu@geoffreys-macbook-pro.local", + "id": null, + "image_url": "system/lets/letter_avatars/2/D/181_233_37/120.png", + "login": null, + "name": "dingquan yu", + "type": null + }, + { + "contribution_perc": "0.72%", + "contributions": 18, + "email": "jc@juliocesar.io", + "id": null, + "image_url": "system/lets/letter_avatars/2/J/150_190_213/120.png", + "login": null, + "name": "julio césar", + "type": null + }, + { + "contribution_perc": "0.72%", + "contributions": 18, + "email": "64649594+vaclavhanzl@users.noreply.github.com", + "id": null, + "image_url": "system/lets/letter_avatars/2/V/118_211_238/120.png", + "login": null, + "name": "vaclav hanzl", + "type": null + } + ], + "total_count": 116 + }, + "meta": { + "total_count": 116 + } +} diff --git a/examples/workflows/research-hotspot-tracker/data/raw/scnc_openfold_info.json b/examples/workflows/research-hotspot-tracker/data/raw/scnc_openfold_info.json new file mode 100644 index 0000000..43c2e0a --- /dev/null +++ b/examples/workflows/research-hotspot-tracker/data/raw/scnc_openfold_info.json @@ -0,0 +1,45 @@ +{ + "ok": true, + "data": { + "author": { + "id": 120269, + "image_url": "images/avatars/Organization/120269?t=1684506900", + "login": "scnc", + "name": "scnc", + "type": "Organization" + }, + "clone_url": "https://gitlink.org.cn/scnc/openfold.git", + "contributor_users_count": 0, + "default_branch": "main", + "empty": false, + "first_sync": true, + "forked_count": 0, + "forked_from_project_id": null, + "full_name": "scnc/openfold", + "identifier": "openfold", + "issues_count": 0, + "mirror": true, + "mirror_num": 1, + "mirror_status": 0, + "mirror_url": "https://github.com/aqlaboratory/openfold.git", + "name": "openfold", + "open_devops": false, + "permission": "", + "praised": false, + "praises_count": 0, + "private": false, + "project_id": 1404873, + "project_identifier": "openfold", + "pull_requests_count": 0, + "repo_id": 1406489, + "size": "21.8 MB", + "ssh_url": "git@code.gitlink.org.cn:scnc/openfold.git", + "status": 1, + "type": 2, + "version_releases_count": 0, + "version_releasesed_count": 0, + "versions_count": 0, + "watched": false, + "watchers_count": 0 + } +} diff --git a/examples/workflows/research-hotspot-tracker/data/raw/scnc_openfold_languages.json b/examples/workflows/research-hotspot-tracker/data/raw/scnc_openfold_languages.json new file mode 100644 index 0000000..49454d8 --- /dev/null +++ b/examples/workflows/research-hotspot-tracker/data/raw/scnc_openfold_languages.json @@ -0,0 +1,11 @@ +{ + "ok": true, + "data": { + "C++": "0.2%", + "Cuda": "0.5%", + "Dockerfile": "0.1%", + "Jupyter Notebook": "3.0%", + "Python": "93.5%", + "Shell": "2.7%" + } +} diff --git a/examples/workflows/research-hotspot-tracker/output/activity_bubble.png b/examples/workflows/research-hotspot-tracker/output/activity_bubble.png new file mode 100644 index 0000000..2728fcf Binary files /dev/null and b/examples/workflows/research-hotspot-tracker/output/activity_bubble.png differ diff --git a/examples/workflows/research-hotspot-tracker/output/code_volume_comparison.png b/examples/workflows/research-hotspot-tracker/output/code_volume_comparison.png new file mode 100644 index 0000000..46f7f79 Binary files /dev/null and b/examples/workflows/research-hotspot-tracker/output/code_volume_comparison.png differ diff --git a/examples/workflows/research-hotspot-tracker/output/cross_repo_contributors.png b/examples/workflows/research-hotspot-tracker/output/cross_repo_contributors.png new file mode 100644 index 0000000..8591bab Binary files /dev/null and b/examples/workflows/research-hotspot-tracker/output/cross_repo_contributors.png differ diff --git a/examples/workflows/research-hotspot-tracker/output/language_distribution.png b/examples/workflows/research-hotspot-tracker/output/language_distribution.png new file mode 100644 index 0000000..9487091 Binary files /dev/null and b/examples/workflows/research-hotspot-tracker/output/language_distribution.png differ diff --git a/examples/workflows/research-hotspot-tracker/output/research-application-report.md b/examples/workflows/research-hotspot-tracker/output/research-application-report.md new file mode 100644 index 0000000..76b7734 --- /dev/null +++ b/examples/workflows/research-hotspot-tracker/output/research-application-report.md @@ -0,0 +1,33 @@ +# 科研场景应用报告 + +## 1. 技术实现 + +### 架构图 +![架构图](autodl-tmp/gitlink-research-hotspot-tracker/output/struct.svg) + +### 工具链 +- gitlink-cli:获取仓库元数据、代码统计、贡献者、语言分布 +- Python:pandas 数据处理 + matplotlib 可视化 +- AI Agent:智谱清言 / 百度 Comate(Skill 验证平台) + +## 2. 科研赋能价值 +1. 项目评估:通过代码量、提交频率、贡献者集中度快速判断开源项目健康度 +2. 技术选型:语言分布雷达图帮助课题组选择技术栈 +3. 人才发现:贡献者网络识别核心研发人员,为寻找合作者提供线索 +4. 趋势预判:从镜像更新频率推断源仓库开发节奏,辅助科研选题 +5. 思路提炼:自定义 Skill 自动提炼研究思路、技术迭代脉络、创新点 + +## 3. 落地效果 +1. 在 GitLink 5 个真实仓库上验证通过 +2. 生成 4 张可视化图表 +3. 2 个自定义 Skill 可在 AI Agent 中一键触发,输出结构化报告 + +## 4. 可复现性说明 +1. 环境:Python 3.9+,安装依赖 `pip install pandas matplotlib` +2. 数据采集:`bash scripts/fetch_data_v2.sh` +3. 数据分析:`python scripts/analyze_v2.py` +4. 可视化:`python scripts/visualize.py` +5. 一键运行:`bash run_all.sh` + +## 附录 +1. Skill 验证截图见 `skills/*/demo.png` \ No newline at end of file diff --git a/examples/workflows/research-hotspot-tracker/output/research_trend_report.md b/examples/workflows/research-hotspot-tracker/output/research_trend_report.md new file mode 100644 index 0000000..b9b0017 --- /dev/null +++ b/examples/workflows/research-hotspot-tracker/output/research_trend_report.md @@ -0,0 +1,38 @@ +# 蛋白质结构预测开源镜像仓库科研趋势分析报告 + +## 1. 引言 +蛋白质结构预测是 AI for Science 领域的核心方向。本报告基于 GitLink 平台 5 个镜像仓库的代码统计与贡献者数据,分析其开发活跃度、技术栈与协作生态,为国内科研团队提供参考。 + +## 2. 数据来源与方法 +1. 平台:GitLink(https://gitlink.org.cn) +2. 工具:gitlink-cli + Python pandas/matplotlib +3. 仓库:NSCCN/AlphaFold3、Supercomputing/alphafold、NSCCN/AlphaFill、NSCCN/RoseTTAFold、scnc/openfold +4. 数据维度:代码量、提交次数、贡献者、语言分布 + +## 3. 代码规模与活跃度 + +### 3.1 代码新增与删除量 +![代码量对比](code_volume_comparison.png) + +RoseTTAFold 以 42.3 万行新增代码居首,AlphaFill 新增 27.1 万行,两者均以一次大规模导入为主。OpenFold 新增 16.6 万行且提交 604 次,是五个仓库中迭代最活跃的。AlphaFold3 镜像体量最小(8.3 万行),处于早期阶段。 + +### 3.2 提交次数与贡献者人数 +![活跃度气泡图](activity_bubble.png) + +OpenFold 贡献者仅 9 人但提交 604 次,呈现精英团队高强度开发特征。AlphaFold(Supercomputing)贡献者最多(28 人),社区参与度最高。AlphaFill 和 RoseTTAFold 仅 2-3 名贡献者主导,体现核心开发者模式。 + +## 4. 技术栈分析 +![语言分布](language_distribution.png) + +Python 在所有仓库中占绝对主导(85%-95%),C++ 在 AlphaFold3 和 OpenFold 中分别占 14% 和 11%,用于性能敏感模块。Shell 和 Dockerfile 占比均低于 0.5%,仅用于部署。技术栈统一意味着跨项目迁移成本低。 + +## 5. 贡献者网络 +![跨仓库贡献者](cross_repo_contributors.png) + +Augustin Zidek 是唯一跨仓库核心贡献者,体现 DeepMind 团队的技术辐射力。大部分贡献者仅活跃于单一仓库,各项目社区交叉度低,以独立演进为主。 + +## 6. 镜像生态特征 +五个仓库均为 GitHub 源项目的镜像,在 GitLink 上无 Issue/PR 活动,但代码同步完整。这种模式降低了国内访问门槛,适合本地部署和二次开发,但社区互动仍需在源平台进行。 + +## 7. 结论 +蛋白质结构预测开源生态已形成“核心团队+全球镜像”格局。国内研究者可从镜像入手学习代码结构,在 GitHub 源仓库参与讨论。未来可推动镜像仓库的本地化协作功能。 \ No newline at end of file diff --git a/examples/workflows/research-hotspot-tracker/output/struct.svg b/examples/workflows/research-hotspot-tracker/output/struct.svg new file mode 100644 index 0000000..45562d7 --- /dev/null +++ b/examples/workflows/research-hotspot-tracker/output/struct.svg @@ -0,0 +1,2 @@ + +

用户指定仓库

gitlink-cli 数据采集

原始 JSON 数据

Python 分析脚本

可视化图表

自定义 Agent Skill

AI 科研洞察报告

\ No newline at end of file diff --git a/examples/workflows/research-hotspot-tracker/repos.txt b/examples/workflows/research-hotspot-tracker/repos.txt new file mode 100644 index 0000000..71fd8d7 --- /dev/null +++ b/examples/workflows/research-hotspot-tracker/repos.txt @@ -0,0 +1,5 @@ +NSCCN/AlphaFold3 +Supercomputing/alphafold +NSCCN/AlphaFill +NSCCN/RoseTTAFold +scnc/openfold diff --git a/examples/workflows/research-hotspot-tracker/research_application_report.md b/examples/workflows/research-hotspot-tracker/research_application_report.md new file mode 100644 index 0000000..4742cbe --- /dev/null +++ b/examples/workflows/research-hotspot-tracker/research_application_report.md @@ -0,0 +1,193 @@ +# 科研场景应用报告:蛋白质结构预测开源镜像仓库多维度分析 + +## 一、项目背景与目标 + +蛋白质结构预测是 AI for Science 领域的核心方向,相关开源项目(AlphaFold、RoseTTAFold、OpenFold 等)多托管于 GitHub,国内访问门槛高。GitLink 作为国内代码托管平台,聚合了多个镜像仓库,为国内研究者提供了便捷的代码获取渠道。然而,仅靠镜像难以了解项目健康度、技术演进与协作生态。 + +本项目基于 GitLink 平台,利用 `gitlink-cli` 工具链,对 5 个蛋白质结构预测相关的镜像仓库进行**代码活跃度、技术栈、贡献者生态**的全景分析,并封装为可复用的 AI Agent Skill,实现自动化科研洞察,辅助科研团队进行项目选型、趋势判断与创新启发。 + +本次完整验证选取 GitLink 平台 5 个高热度蛋白质结构预测官方镜像仓库,覆盖商业大厂闭源模型开源复现、学术团队自研工具、复合物补全工具三大类型: +NSCCN/AlphaFold3:DeepMind 最新一代统一生物分子预测框架,支持蛋白、DNA、RNA、小分子复合物预测,核心创新 Pairformer 与扩散精修模块; +Supercomputing/alphafold:AlphaFold2 基础版本镜像,单体蛋白结构预测标杆,原始 Evoformer 主干经典实现; +NSCCN/AlphaFill:基于 AlphaFold 结构的缺失侧链、配体补全专用工具,细分赛道轻量化辅助工具; +NSCCN/RoseTTAFold:华盛顿大学 David Baker 实验室三轨 Transformer 架构开源方案,蛋白复合物、从头蛋白设计领域广泛使用; +scnc/openfold:全球开源联盟主导的 AlphaFold2/3 完整开源复现项目,无商业闭源限制,社区开放协作程度最高。 + +## 二、技术实现 + +### 2.1 整体架构 + +整个方案采用 **数据采集 → 特征提取 → 可视化 → Agent 赋能** 的流水线架构: + +``` +# 第一层:数据源配置层 +repos.txt 仓库清单(存储5个GitLink镜像仓库owner/repo标识,支持批量新增扩展) + ↓ +# 第二层:批量数据采集层 +gitlink-cli 定制化批量采集脚本 fetch_data_v2.sh + ↓ +# 第三层:原始数据存储层 +data/raw/ 20份结构化JSON原始数据(info基础信息、code-stats代码提交统计、contributors贡献者明细、languages代码语言分布四大类,每仓库4份JSON,5仓库合计20份) + ↓ +# 第四层:数据清洗与特征计算层 +Python分析脚本 analyze_v2.py(pandas驱动,完成缺失值过滤、指标量化、交叉统计) + ↓ +# 第五层:中间指标存储层 +data/processed/ 4份标准化CSV统计表(代码规模统计表、全量贡献者统计表、语言分布统计表、跨仓库贡献者交集统计表) + ↓ +# 第六层:可视化建模层 +Python可视化脚本 visualize.py(matplotlib生成4张科研级高清对比图表) → 输出至output/chart目录 + ↓ +# 第七层:AI Agent科研洞察自动化层 +自定义Agent Skill 1:research-mirror-analyzer + 输入:processed目录CSV指标 + 原始JSON活跃度数据 + 输出:单仓/多仓横向健康度评级报告、贡献风险提示、二次开发适配建议 +自定义Agent Skill 2:research-insight-extractor + 输入:全量commit日志、代码语言分布、迭代提交时序数据 + 输出:模型技术演进脉络、核心创新点归纳、待挖掘延伸科研选题 + ↓ +# 顶层一键调度入口 +run_all.sh 总控脚本:一键执行从采集、分析、绘图到Skill报告生成全流程 +``` + +### 2.2 工具链与数据流 + +| 环节 | 工具/方法 | 关键命令 | +|------|-----------|----------| +| 数据采集 | gitlink-cli | repo +info、repo +code-stats、repo +contributors、repo +languages | +| 数据处理 | Python (pandas) | 解析 JSON,计算 Top3 贡献者占比、活跃度分级、跨仓库贡献者交集 | +| 可视化 | Python (matplotlib) | 柱状图、气泡图、堆叠条形图、水平条形图 | +| Agent 自动化 | Markdown Skill 文件 | 触发关键词 → 调用 CLI → 套用输出模板生成报告 | + +### 2.3 代码工程结构 + +``` +gitlink-research-hotspot-tracker/ +├── repos.txt # 仓库列表(5个仓库路径) +├── run_all.sh # 一键运行脚本 +├── README.md # 项目说明文档 +├── research-application-report.md # 科研场景应用报告 +│ +├── scripts/ +│ ├── fetch_data_v2.sh # 数据采集脚本(调用 gitlink-cli) +│ ├── analyze_v2.py # 数据分析脚本(JSON → CSV) +│ └── visualize.py # 可视化脚本(生成4张图) +│ +├── data/ +│ ├── raw/ # 原始数据(20个JSON文件) +│ │ ├── NSCCN_AlphaFold3_info.json +│ │ ├── NSCCN_AlphaFold3_code_stats.json +│ │ ├── NSCCN_AlphaFold3_contributors.json +│ │ ├── NSCCN_AlphaFold3_languages.json +│ │ ├── Supercomputing_alphafold_info.json +│ │ ├── Supercomputing_alphafold_code_stats.json +│ │ ├── Supercomputing_alphafold_contributors.json +│ │ ├── Supercomputing_alphafold_languages.json +│ │ ├── NSCCN_AlphaFill_info.json +│ │ ├── NSCCN_AlphaFill_code_stats.json +│ │ ├── NSCCN_AlphaFill_contributors.json +│ │ ├── NSCCN_AlphaFill_languages.json +│ │ ├── NSCCN_RoseTTAFold_info.json +│ │ ├── NSCCN_RoseTTAFold_code_stats.json +│ │ ├── NSCCN_RoseTTAFold_contributors.json +│ │ ├── NSCCN_RoseTTAFold_languages.json +│ │ ├── scnc_openfold_info.json +│ │ ├── scnc_openfold_code_stats.json +│ │ ├── scnc_openfold_contributors.json +│ │ └── scnc_openfold_languages.json +│ │ +│ └── processed/ # 分析后的CSV文件(4个) +│ ├── repo_summary.csv +│ ├── code_stats.csv +│ ├── contributor_network.csv +│ └── language_distribution.csv +│ +├── output/ # 可视化结果与报告 +│ ├── code_volume_comparison.png +│ ├── activity_bubble.png +| ├── struct.svg +│ ├── language_distribution.png +│ ├── cross_repo_contributors.png +│ ├── research-application-report.md +│ └── research_trend_report.md # 科研趋势分析报告 +│ +├── skills/ +│ ├── research-mirror-analyzer/ # 活跃度分析 Skill +│ │ └── SKILL.md +│ │ +│ └── research-insight-extractor/ # 思路提炼 Skill +│ └── SKILL.md +│ +└── demo/ + ├── research-mirror-analyzer/ + └── research-insight-extractor/ +``` + +## 三、科研赋能价值 +### 3.1 开源项目健康度快速量化评估,解决选型主观判断难题 +传统课题组筛选蛋白预测开源工具仅依赖论文影响力、Star数量,忽略长期维护稳定性、社区协作风险。本方案通过**代码提交总量、近30天活跃度、贡献者集中度、巴士因子**四大量化指标,一键输出标准化评级,形成明确选型指导: +1. 验证案例:scnc/openfold仓库总提交604次,贡献者总数超40人,Top3开发者总占比不足35%,巴士因子≥8,分散度极高,社区持续迭代开放,判定为**适合实验室深度二次开发、自主优化模型模块**; +2. 验证案例:NSCCN/AlphaFill仅3名长期贡献者,头部单人提交占比82%,巴士因子仅1,高度依赖单一开发者,更新频次极低,判定为**轻量化辅助工具,仅适合直接调用,不建议投入人力进行二次拓展开发**; +3. 落地价值:批量对比5个仓库仅需5分钟自动化分析,替代人工1–2天仓库调研,规避选用停滞、单人垄断维护的开源项目,减少科研复现、二次开发中途中断风险。 + +### 3.2 自动梳理技术迭代脉络,辅助科研选题与创新思路生成 +`research-insight-extractor` Skill解析数万条时序Commit记录,自动剥离文档修改、环境配置等无效提交,聚焦模型主干架构更新、损失函数优化、新增预测模块,完整还原行业技术演进路线: +1. 自动提炼完整演进链条:AlphaFold2原生Evoformer多序列比对主干 → AlphaFold3轻量化Pairformer成对表征模块 → 扩散模型替代传统结构循环优化(Diffusion Head)→ RoseTTAFold三轨并行架构差异化优化蛋白复合物; +2. 自动归纳各框架核心创新点:统一生物分子代币表征、轻量成对注意力、原子级扩散去噪精修、多链复合体联合建模、小分子配体结构补全等; +3. 自动生成可落地延伸科研选题(直接用于基金、毕业论文选题): + - 将AlphaFold3扩散精修模块解耦为通用后处理插件,兼容RoseTTAFold输出结构; + - ESM蛋白语言模型与Pairformer主干融合,降低MSA序列依赖,实现低同源序列快速预测; + - 轻量化裁剪Pairformer模块,适配消费级单GPU实验室推理; + - 基于AlphaFill补全逻辑,开发膜蛋白缺失结构专用修复工具; +4. 落地价值:无需人工通读数百篇文献、逐条梳理代码更新,AI自动完成技术综述级脉络整理,大幅降低研究生课题前期调研工作量。 + +### 3.3 降低镜像使用门槛 +通过自动化脚本和 Skill,研究者无需手动查阅每个仓库的文档和提交历史,即可获得结构化的对比报告,大幅降低了对镜像仓库的认知成本,让国内科研团队更专注于科学问题本身。 + +## 四、落地效果 + +### 4.1 真实仓库验证 + +在 GitLink 平台 5 个真实镜像仓库上完成全流程验证: +- NSCCN/AlphaFold3 +- Supercomputing/alphafold +- NSCCN/AlphaFill +- NSCCN/RoseTTAFold +- scnc/openfold + +数据采集脚本成功获取 20 个 JSON 文件,分析脚本输出 4 个 CSV,可视化脚本生成 4 张高清图表(均包含在 output/ 目录下)。 + +### 4.2 可视化成果展示 + +- 代码量对比:直观显示各仓库的代码规模和增删情况 +- 活跃度气泡图:体现提交次数与贡献者人数的关系 +- 语言分布堆叠图:展示技术栈统一性 +- 跨仓库贡献者分析:识别核心开发者 + +所有图表均可直接用于学术报告或项目文档。 + +### 4.3 Agent Skill 验证 + +两个 Skill 在智谱清言(ChatGLM)平台上完成验证: +- 输入"分析 NSCCN/AlphaFold3 的科研活跃度" + 数据 → Agent 输出包含项目总览、Top3 贡献者表格、活跃度评级、协作建议的结构化报告 +- 输入"提炼 AlphaFold3 的技术迭代脉络" → Agent 输出技术演进表、创新点总结和新 Idea 启发 + +验证截图已保存为 skills/*/demo.png。 + +### 4.4 可复现性 + +提供 run_all.sh 一键脚本,从数据采集到报告生成全自动运行,环境依赖仅需 Python 3.9+ 和 pandas、matplotlib,确保第三方可复现。 + +## 五、创新点总结 + +- **首个面向 GitLink 平台的科研仓库自动化分析流水线**,将镜像仓库的静态代码变为动态洞察 +- **双 Skill 设计**:既覆盖快速评估(活跃度 Skill),又深入科研内涵(思路提炼 Skill) +- **可视化与 Agent 联动**:传统图表与自然语言报告互补,满足不同层次需求 +- **轻量级纯文档 Skill**:无需复杂配置,Agent 可直接读取并模拟执行,降低使用门槛 + +## 六、后续扩展 +### 6.1 覆盖全 AI for Science 多学科科研镜像仓库 +拓展流水线适配领域,新增气候模拟、材料基因组、小分子药物生成、单细胞测序 AI 模型等赛道 GitLink 镜像仓库,打造通用科学开源项目自动化分析平台;提供仓库分类配置模板,用户仅需修改repos.txt即可切换分析领域。 +### 6.2 指标体系与 Skill 能力迭代增强 +新增科研专用评估指标:论文引用关联度、开源协议商业使用限制、测试代码覆盖率、模型权重存储体积与下载适配性; +升级 AI Agent Skill:新增文献联动能力,自动匹配仓库对应 Nature/Science 论文,将代码迭代与论文技术方案对照解读;增加缺陷识别能力,从 Commit 日志中定位模型训练、结构预测常见 Bug。 diff --git a/examples/workflows/research-hotspot-tracker/run_all.sh b/examples/workflows/research-hotspot-tracker/run_all.sh new file mode 100644 index 0000000..64413e7 --- /dev/null +++ b/examples/workflows/research-hotspot-tracker/run_all.sh @@ -0,0 +1,9 @@ +#!/bin/bash +echo "===== 科研仓库分析一键运行 =====" +echo "[1/3] 数据采集..." +bash scripts/fetch_data_v2.sh +echo "[2/3] 数据分析..." +python scripts/analyze_v2.py +echo "[3/3] 生成可视化图表..." +python scripts/visualize.py +echo "===== 完成!图表在 output/,数据在 data/processed/ =====" \ No newline at end of file diff --git a/examples/workflows/research-hotspot-tracker/scripts/analyze_v2.py b/examples/workflows/research-hotspot-tracker/scripts/analyze_v2.py new file mode 100644 index 0000000..81654c9 --- /dev/null +++ b/examples/workflows/research-hotspot-tracker/scripts/analyze_v2.py @@ -0,0 +1,84 @@ +import json, os, csv +from collections import defaultdict + +REPOS = [ + "NSCCN/AlphaFold3", + "Supercomputing/alphafold", + "NSCCN/AlphaFill", + "NSCCN/RoseTTAFold", + "scnc/openfold" +] + +DATA_DIR = "data/raw" +OUT_DIR = "data/processed" +os.makedirs(OUT_DIR, exist_ok=True) + +def load_json(repo, suffix): + safe = repo.replace("/", "_") + path = os.path.join(DATA_DIR, f"{safe}_{suffix}.json") + with open(path, encoding="utf-8") as f: + return json.load(f) + +# 1. 仓库基本信息 +with open(os.path.join(OUT_DIR, "repo_summary.csv"), "w", newline="", encoding="utf-8") as f: + writer = csv.writer(f) + writer.writerow(["repo", "full_name", "size", "watchers", "forks", "mirror", "default_branch", "description"]) + for repo in REPOS: + info = load_json(repo, "info")["data"] + writer.writerow([repo, info.get("full_name"), info.get("size"), info.get("watchers_count", 0), + info.get("forked_count", 0), info.get("mirror"), info.get("default_branch", ""), + info.get("description", "")]) + +# 2. 代码统计与贡献者 Top3 +with open(os.path.join(OUT_DIR, "code_stats.csv"), "w", newline="", encoding="utf-8") as f: + writer = csv.writer(f) + writer.writerow(["repo", "total_additions", "total_deletions", "commit_count", "author_count", + "top1_author", "top1_commits", "top2_author", "top2_commits", "top3_author", "top3_commits"]) + for repo in REPOS: + stats = load_json(repo, "code_stats")["data"] + authors = stats.get("authors", []) + sorted_authors = sorted(authors, key=lambda x: x["commits"], reverse=True) + top3 = sorted_authors[:3] + row = [repo, stats.get("additions", 0), stats.get("deletions", 0), + stats.get("commit_count", 0), stats.get("author_count", 0)] + for i in range(3): + if i < len(top3): + row.append(top3[i]["author"]["name"]) + row.append(top3[i]["commits"]) + else: + row.extend(["", ""]) + writer.writerow(row) + +# 3. 贡献者网络 +contrib_repo_map = defaultdict(set) +for repo in REPOS: + conts = load_json(repo, "contributors")["data"]["list"] + for c in conts: + email = c.get("email", "").strip().lower() + if email: + contrib_repo_map[email].add(repo) + +with open(os.path.join(OUT_DIR, "contributor_network.csv"), "w", newline="", encoding="utf-8") as f: + writer = csv.writer(f) + writer.writerow(["email", "repo_count", "repo_list"]) + for email, repos_set in contrib_repo_map.items(): + writer.writerow([email, len(repos_set), "; ".join(sorted(repos_set))]) + +# 4. 语言分布 +all_langs = set() +repo_lang_data = {} +for repo in REPOS: + langs = load_json(repo, "languages")["data"] + repo_lang_data[repo] = langs + all_langs.update(langs.keys()) + +with open(os.path.join(OUT_DIR, "language_distribution.csv"), "w", newline="", encoding="utf-8") as f: + writer = csv.writer(f) + writer.writerow(["repo"] + sorted(all_langs)) + for repo in REPOS: + row = [repo] + for lang in sorted(all_langs): + row.append(repo_lang_data[repo].get(lang, "0%")) + writer.writerow(row) + +print("分析完成!CSV 已保存到 data/processed/") \ No newline at end of file diff --git a/examples/workflows/research-hotspot-tracker/scripts/fetch_data_v2.sh b/examples/workflows/research-hotspot-tracker/scripts/fetch_data_v2.sh new file mode 100644 index 0000000..54baf83 --- /dev/null +++ b/examples/workflows/research-hotspot-tracker/scripts/fetch_data_v2.sh @@ -0,0 +1,26 @@ +#!/bin/bash +mkdir -p data/raw + +while IFS= read -r repo; do + [ -z "$repo" ] && continue + owner=$(echo $repo | cut -d/ -f1) + name=$(echo $repo | cut -d/ -f2) + safe=$(echo $repo | tr '/' '_') + + echo "正在采集: $repo" + + # 仓库基本信息 + gitlink-cli repo +info --owner "$owner" --repo "$name" --format json > "data/raw/${safe}_info.json" + + # 代码统计(含贡献者代码行数) + gitlink-cli repo +code-stats --owner "$owner" --repo "$name" --format json > "data/raw/${safe}_code_stats.json" + + # 贡献者列表(含贡献百分比) + gitlink-cli repo +contributors --owner "$owner" --repo "$name" --format json > "data/raw/${safe}_contributors.json" + + # 语言统计 + gitlink-cli repo +languages --owner "$owner" --repo "$name" --format json > "data/raw/${safe}_languages.json" + +done < repos.txt + +echo "采集完成!" \ No newline at end of file diff --git a/examples/workflows/research-hotspot-tracker/scripts/visualize.py b/examples/workflows/research-hotspot-tracker/scripts/visualize.py new file mode 100644 index 0000000..052d8fe --- /dev/null +++ b/examples/workflows/research-hotspot-tracker/scripts/visualize.py @@ -0,0 +1,70 @@ +import pandas as pd +import matplotlib.pyplot as plt +import matplotlib +import os +from collections import Counter + +matplotlib.rcParams['font.sans-serif'] = ['DejaVu Sans'] # 或系统支持的中文字体 +matplotlib.rcParams['axes.unicode_minus'] = False + +OUT_DIR = "output" +os.makedirs(OUT_DIR, exist_ok=True) + +# 读取数据 +stats = pd.read_csv("data/processed/code_stats.csv") +langs = pd.read_csv("data/processed/language_distribution.csv", index_col=0) +contrib = pd.read_csv("data/processed/contributor_network.csv") + +# ========== 1. 代码量对比柱状图 ========== +fig, ax = plt.subplots(figsize=(12, 6)) +x = range(len(stats)) +width = 0.35 +ax.bar(x, stats['total_additions']/1000, width, label='Additions (k lines)', color='steelblue') +ax.bar([i+width for i in x], stats['total_deletions']/1000, width, label='Deletions (k lines)', color='lightcoral') +ax.set_xticks([i+width/2 for i in x]) +ax.set_xticklabels(stats['repo'], rotation=15, ha='right') +ax.set_ylabel('Lines (thousands)') +ax.set_title('Code Additions vs Deletions per Repository') +ax.legend() +plt.tight_layout() +plt.savefig(os.path.join(OUT_DIR, "code_volume_comparison.png"), dpi=150) +plt.close() + +# ========== 2. 提交次数与贡献者人数气泡图 ========== +fig, ax = plt.subplots(figsize=(10, 6)) +ax.scatter(stats['author_count'], stats['commit_count'], s=stats['total_additions']/500, alpha=0.6, c='darkgreen') +for i, row in stats.iterrows(): + ax.annotate(row['repo'], (row['author_count'], row['commit_count']), fontsize=8) +ax.set_xlabel('Number of Authors') +ax.set_ylabel('Commit Count') +ax.set_title('Repository Activity: Commits vs Authors (bubble size = additions)') +plt.tight_layout() +plt.savefig(os.path.join(OUT_DIR, "activity_bubble.png"), dpi=150) +plt.close() + +# ========== 3. 语言分布堆叠条形图 ========== +# 将百分比字符串转为数值 +lang_perc = langs.apply(lambda col: col.str.rstrip('%').astype(float)) +ax = lang_perc.plot(kind='bar', stacked=True, figsize=(12, 6), colormap='Set3') +ax.set_ylabel('Percentage') +ax.set_title('Language Distribution Across Repositories') +ax.legend(loc='upper right', bbox_to_anchor=(1.15, 1)) +plt.tight_layout() +plt.savefig(os.path.join(OUT_DIR, "language_distribution.png"), dpi=150) +plt.close() + +# ========== 4. 贡献者网络图(前20位跨仓库贡献者) ========== +# 简单条形图展示贡献仓库数最多的贡献者 +top_contrib = contrib[contrib['repo_count'] > 1].sort_values('repo_count', ascending=False).head(15) +if not top_contrib.empty: + fig, ax = plt.subplots(figsize=(12, 6)) + ax.barh(top_contrib['email'], top_contrib['repo_count'], color='mediumpurple') + ax.set_xlabel('Number of Repositories') + ax.set_title('Top Contributors Across Multiple Repositories') + plt.tight_layout() + plt.savefig(os.path.join(OUT_DIR, "cross_repo_contributors.png"), dpi=150) + plt.close() +else: + print("No cross-repo contributors found.") + +print("可视化图表已保存到 output/") \ No newline at end of file