OSCR

Machine learning-based gait classification and genome-wide association identify a QTL for gait type in Colombian paso horses.

Code ↔ Paper

4 matches between paragraphs of the paper and lines of its authors' code, computed by the harvester (lexical-v1). Click a colored paragraph or line to see its counterpart.

The 4 matches
  1. [1] § STAR★Methods › Quantification and statistical analysis › Multi-model GWAS and robustness testing ↔ .opencode/gcta-mcp/server.py, lines 1292–1375 · score 0.80 · Principal Component, population structure, genome wide association, linear model, Mixed Model, Regression
  2. [2] § STAR★Methods › Quantification and statistical analysis › MLMA-LOCO and SAIGE analysis ↔ .opencode/gcta-mcp/server.py, lines 1292–1375 · score 0.73 · Mixed Linear Model, MLMA LOCO, relationship matrix, Chromosome, GCTA, binary
  3. [3] § STAR★Methods › Quantification and statistical analysis › Genotype quality control and filtering ↔ src/Main.cpp, lines 424–466 · score 0.53 · Quality control, allele frequency, QC, MAF
  4. [4] § STAR★Methods › Quantification and statistical analysis › Cross-validation: Comparative frequency analysis ↔ R/SAIGE_fitGLMM_fast.R, lines 240–314 · score 0.51 · Generalized Linear Mixed, fitted, coefficients, Variation, phenotypes, Model

Paper

Loaded from Europe PMC by your browser, not stored by OSCR: doi.org · Europe PMC

The paper is loaded when this pane is shown.

The authors' code

Python · 2,155 lines · 72 KB · GPL-3.0 · 2 matches

  1. #!/usr/bin/env python3
  2. """
  3. MCP Server for GCTA (Genome-wide Complex Trait Analysis).
  4. Exposes all GCTA functionality through MCP tools so that AI assistants
  5. like Claude, Codex, and opencode can run GCTA analyses via natural language.
  6. Usage:
  7. python server.py
  8. Configuration via environment variables:
  9. GCTA_BINARY_PATH Path to the GCTA binary
  10. (default: ../gcta relative to this script)
  11. GCTA_WORK_DIR Working directory for GCTA data files
  12. (default: parent directory of this script)
  13. GCTA_TIMEOUT Execution timeout in seconds (default: 3600)
  14. """
  15. import os
  16. import sys
  17. import json
  18. import subprocess
  19. import glob
  20. from mcp.server.fastmcp import FastMCP
  21. # ============================================================================
  22. # Configuration
  23. # ============================================================================
  24. _SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
  25. _PKG_ROOT = os.path.dirname(_SCRIPT_DIR)
  26. GCTA_BINARY_PATH = os.environ.get(
  27. "GCTA_BINARY_PATH",
  28. os.path.join(_PKG_ROOT, "gcta"),
  29. )
  30. GCTA_WORK_DIR = os.environ.get(
  31. "GCTA_WORK_DIR",
  32. _PKG_ROOT,
  33. )
  34. GCTA_TIMEOUT = int(os.environ.get("GCTA_TIMEOUT", "3600"))
  35. # ============================================================================
  36. # Execution wrapper
  37. # ============================================================================
  38. class GCTAExecutor:
  39. """Handles execution of GCTA binary via subprocess."""
  40. def __init__(self, binary_path, work_dir, timeout):
  41. self.binary_path = binary_path
  42. self.work_dir = work_dir
  43. self.timeout = timeout
  44. def execute(self, args: str, work_dir: str = None) -> dict:
  45. """Execute GCTA with the given command-line arguments."""
  46. wd = os.path.abspath(work_dir or self.work_dir)
  47. cmd = [self.binary_path] + args.split()
  48. try:
  49. result = subprocess.run(
  50. cmd,
  51. capture_output=True,
  52. text=True,
  53. cwd=wd,
  54. timeout=self.timeout,
  55. )
  56. return {
  57. "exit_code": result.returncode,
  58. "stdout": result.stdout,
  59. "stderr": result.stderr,
  60. "command": " ".join(cmd),
  61. "work_dir": wd,
  62. }
  63. except subprocess.TimeoutExpired:
  64. return {"error": f"GCTA execution timed out after {self.timeout}s"}
  65. except FileNotFoundError:
  66. return {"error": f"GCTA binary not found at {self.binary_path}"}
  67. except Exception as e:
  68. return {"error": str(e)}
  69. # ============================================================================
  70. # Helper functions
  71. # ============================================================================
  72. def _parse_out_prefix(args: str) -> str:
  73. """Parse the --out value from args; return default if absent."""
  74. tokens = args.split()
  75. for i, t in enumerate(tokens):
  76. if t == "--out" and i + 1 < len(tokens):
  77. return tokens[i + 1]
  78. return "gcta"
  79. def _read_log_file(work_dir: str, out_prefix: str) -> str:
  80. """Read the GCTA .log file if it exists."""
  81. log_path = os.path.join(work_dir, out_prefix + ".log")
  82. if os.path.exists(log_path):
  83. try:
  84. with open(log_path, "r", errors="replace") as f:
  85. return f.read()
  86. except Exception:
  87. return ""
  88. return ""
  89. def _list_output_files(work_dir: str, out_prefix: str) -> list:
  90. """List output files matching the out prefix."""
  91. files = []
  92. pattern = os.path.join(work_dir, out_prefix + "*")
  93. for f in sorted(glob.glob(pattern)):
  94. files.append({
  95. "file": os.path.relpath(f, work_dir),
  96. "size_bytes": os.path.getsize(f),
  97. })
  98. return files
  99. def _format_result(exec_result: dict, work_dir: str,
  100. out_prefix: str) -> str:
  101. """Format the execution result as a JSON string."""
  102. if "error" in exec_result:
  103. return json.dumps({"error": exec_result["error"]}, indent=2)
  104. log_content = _read_log_file(work_dir, out_prefix)
  105. output_files = _list_output_files(work_dir, out_prefix)
  106. result = {
  107. "exit_code": exec_result["exit_code"],
  108. "success": exec_result["exit_code"] == 0,
  109. "command": exec_result["command"],
  110. "work_dir": work_dir,
  111. "out_prefix": out_prefix,
  112. "stdout": exec_result["stdout"][-5000:] if exec_result["stdout"] else "",
  113. "stderr": exec_result["stderr"][-5000:] if exec_result["stderr"] else "",
  114. "log_content": log_content[-8000:] if log_content else "",
  115. "output_files": output_files,
  116. }
  117. return json.dumps(result, indent=2, ensure_ascii=False)
  118. def _build_args(base: list, **kwargs) -> str:
  119. """Build a GCTA argument string from a base list and keyword arguments.
  120. ``base`` is a list of required flags + values (e.g.
  121. ``["--bfile", bfile, "--make-grm", "--out", out]``).
  122. Keyword arguments whose value is:
  123. - ``None`` or ``""`` -> skipped
  124. - ``False`` -> skipped (boolean flags are added only when True)
  125. - ``True`` -> added as a bare flag (``--flag``)
  126. - any other value -> added as ``--flag value``
  127. """
  128. parts = list(base)
  129. for key, val in kwargs.items():
  130. if val is None or val == "" or val is False:
  131. continue
  132. flag = "--" + key.replace("_", "-")
  133. if val is True:
  134. parts.append(flag)
  135. else:
  136. parts.extend([flag, str(val)])
  137. return " ".join(parts)
  138. # ============================================================================
  139. # Create MCP server
  140. # ============================================================================
  141. mcp = FastMCP("gcta-mcp")
  142. _executor = GCTAExecutor(
  143. binary_path=GCTA_BINARY_PATH,
  144. work_dir=GCTA_WORK_DIR,
  145. timeout=GCTA_TIMEOUT,
  146. )
  147. # ============================================================================
  148. # Core tools
  149. # ============================================================================
  150. @mcp.tool()
  151. def gcta_run(args: str, work_dir: str = "") -> str:
  152. """Execute GCTA with arbitrary command-line arguments.
  153. This is the most flexible tool — it gives full access to every GCTA
  154. option. Pass everything that would appear after ``gcta64`` on the
  155. command line.
  156. Examples:
  157. args = "--bfile test --make-grm --out test_grm"
  158. args = "--grm test_grm --reml --pheno test.phen --out test_reml"
  159. args = "--bfile test --mlma-loco --pheno test.phen --out test_mlma"
  160. Args:
  161. args: Command-line arguments (everything after the binary name).
  162. work_dir: Working directory for GCTA. Defaults to GCTA_WORK_DIR.
  163. All input/output file paths are relative to this directory.
  164. Returns:
  165. JSON with exit_code, stdout, stderr, log_content, output_files.
  166. """
  167. wd = work_dir or GCTA_WORK_DIR
  168. out_prefix = _parse_out_prefix(args)
  169. result = _executor.execute(args, wd)
  170. return _format_result(result, os.path.abspath(wd), out_prefix)
  171. @mcp.tool()
  172. def gcta_help(topic: str = "all") -> str:
  173. """Get comprehensive documentation about GCTA analyses and options.
  174. Args:
  175. topic: One of:
  176. "all" - Overview of all analyses (default)
  177. "data" - Data input, management, and filtering
  178. "grm" - Genetic Relationship Matrix (GRM) construction
  179. "reml" - REML / GREML variance component estimation
  180. "bivariate_reml" - Bivariate REML analysis
  181. "hereg" - Haseman-Elston regression
  182. "pca" - Principal component analysis
  183. "mlma" - Mixed linear model association (MLMA / MLMA-LOCO)
  184. "cojo" - Conditional and joint analysis (COJO)
  185. "gsmr" - GSMR Mendelian randomization
  186. "mtcojo" - Multi-trait COJO
  187. "fastgwa" - fastGWA genome-wide association
  188. "fastbat" - fastBAT / mBAT gene-based test
  189. "simulation" - Phenotype simulation
  190. "ld" - LD pruning, LD score regression
  191. "fst" - Fst population differentiation
  192. "expression" - Expression data analysis (eRFile, ecojo, make-erm)
  193. "acat" - ACAT gene-based test
  194. "options" - Full list of all command-line options
  195. Returns:
  196. Documentation string for the requested topic.
  197. """
  198. docs = _get_help_docs()
  199. topic = topic.lower().strip()
  200. if topic in docs:
  201. return docs[topic]
  202. elif topic == "all":
  203. return docs["all"]
  204. else:
  205. available = ", ".join(sorted(docs.keys()))
  206. return f"Unknown topic '{topic}'. Available topics: {available}"
  207. @mcp.tool()
  208. def gcta_check() -> str:
  209. """Check if GCTA is properly configured and can be executed.
  210. Verifies:
  211. - GCTA binary exists at the configured path
  212. - Working directory exists and is writable
  213. - Test data files are present
  214. Returns:
  215. JSON with configuration details and check results.
  216. """
  217. info = {
  218. "binary_path": GCTA_BINARY_PATH,
  219. "binary_exists": os.path.exists(GCTA_BINARY_PATH),
  220. "work_dir": GCTA_WORK_DIR,
  221. "work_dir_exists": os.path.exists(GCTA_WORK_DIR),
  222. "work_dir_writable": os.access(GCTA_WORK_DIR, os.W_OK) if os.path.exists(GCTA_WORK_DIR) else False,
  223. "timeout_seconds": GCTA_TIMEOUT,
  224. }
  225. checks = []
  226. if not info["binary_exists"]:
  227. checks.append("FAIL: GCTA binary not found. Set GCTA_BINARY_PATH env var.")
  228. else:
  229. checks.append("OK: GCTA binary found.")
  230. if not info["work_dir_exists"]:
  231. checks.append("FAIL: Working directory not found. Set GCTA_WORK_DIR env var.")
  232. else:
  233. checks.append("OK: Working directory exists.")
  234. if info["work_dir_writable"]:
  235. checks.append("OK: Working directory is writable.")
  236. else:
  237. checks.append("WARN: Working directory is not writable.")
  238. test_data_dir = GCTA_WORK_DIR
  239. test_files = ["test.bed", "test.bim", "test.fam", "test.phen"]
  240. missing = [f for f in test_files if not os.path.exists(os.path.join(test_data_dir, f))]
  241. if not missing:
  242. checks.append("OK: Test data files found in working directory.")
  243. else:
  244. checks.append(f"WARN: Missing test data files: {', '.join(missing)}")
  245. info["checks"] = checks
  246. return json.dumps(info, indent=2, ensure_ascii=False)
  247. # ============================================================================
  248. # GRM construction tools
  249. # ============================================================================
  250. @mcp.tool()
  251. def gcta_make_grm(
  252. bfile: str,
  253. out: str = "gcta_grm",
  254. maf: float = 0.0,
  255. thread_num: int = 1,
  256. autosome_num: int = 22,
  257. chr_filter: int = 0,
  258. autosome: bool = False,
  259. make_grm_alg: int = 0,
  260. grm_adj: float = -1.0,
  261. grm_cutoff: float = -1.0,
  262. dosage_compen: int = -1,
  263. dominance: bool = False,
  264. make_grm_xchr: bool = False,
  265. make_grm_inbred: bool = False,
  266. save_ram: bool = False,
  267. extract: str = "",
  268. exclude: str = "",
  269. work_dir: str = "",
  270. ) -> str:
  271. """Construct a Genetic Relationship Matrix (GRM) from PLINK bed data.
  272. The GRM estimates pairwise genomic relatedness between individuals
  273. based on genome-wide SNPs. This is the foundational step for most
  274. downstream GCTA analyses (REML, PCA, MLMA, etc.).
  275. Args:
  276. bfile: PLINK binary file prefix (e.g. "test" for test.bed/.bim/.fam).
  277. out: Output file prefix. Produces {out}.grm.bin, {out}.grm.N.bin,
  278. {out}.grm.id.
  279. maf: Minor allele frequency filter (0 = no filter, typical: 0.01).
  280. thread_num: Number of CPU threads.
  281. autosome_num: Number of autosomes (default 22 for human).
  282. chr_filter: Restrict to a specific chromosome (0 = no restriction).
  283. autosome: If True, restrict to autosomes 1..autosome_num.
  284. make_grm_alg: Algorithm: 0 = VanRaden (default), 1 = alternative.
  285. grm_adj: GRM adjustment factor (-1 = not used).
  286. grm_cutoff: Remove pairs with GRM > cutoff (-1 = no cutoff).
  287. dosage_compen: Dosage compensation: 0 = none, 1 = X chromosome.
  288. dominance: If True, calculate dominance GRM.
  289. make_grm_xchr: If True, calculate X-chromosome GRM.
  290. make_grm_inbred: If True, calculate inbreeding GRM.
  291. save_ram: If True, use memory-saving mode.
  292. extract: File of SNP IDs to include.
  293. exclude: File of SNP IDs to exclude.
  294. work_dir: Working directory for GCTA.
  295. Returns:
  296. JSON with execution results, log content, and output file list.
  297. """
  298. base = ["--bfile", bfile, "--autosome-num", str(autosome_num),
  299. "--thread-num", str(thread_num)]
  300. if dominance:
  301. base.append("--make-grm-d")
  302. elif make_grm_xchr:
  303. base.append("--make-grm-xchr")
  304. elif make_grm_inbred:
  305. base.append("--make-grm-inbred")
  306. else:
  307. base.append("--make-grm")
  308. base.extend(["--out", out])
  309. args = _build_args(base, maf=maf, chr=chr_filter if chr_filter > 0 else None,
  310. autosome=autosome, make_grm_alg=make_grm_alg,
  311. grm_adj=grm_adj if grm_adj >= 0 else None,
  312. grm_cutoff=grm_cutoff if grm_cutoff > 0 else None,
  313. dc=dosage_compen if dosage_compen >= 0 else None,
  314. save_ram=save_ram, extract=extract or None,
  315. exclude=exclude or None)
  316. return gcta_run(args, work_dir)
  317. # ============================================================================
  318. # REML / GREML tools
  319. # ============================================================================
  320. @mcp.tool()
  321. def gcta_reml(
  322. grm: str,
  323. pheno: str,
  324. out: str = "gcta_reml",
  325. qcovar: str = "",
  326. covar: str = "",
  327. mpheno: int = 0,
  328. thread_num: int = 1,
  329. reml_priors: str = "",
  330. reml_priors_var: str = "",
  331. reml_maxit: int = 100,
  332. prevalence: float = -1.0,
  333. reml_no_constrain: bool = False,
  334. reml_no_lrt: bool = False,
  335. reml_pred_rand: bool = False,
  336. reml_est_fix: bool = False,
  337. grm_cutoff: float = -1.0,
  338. gxe: str = "",
  339. work_dir: str = "",
  340. ) -> str:
  341. """Run REML analysis to estimate variance components (GREML).
  342. Estimates the proportion of phenotypic variance explained by all
  343. genome-wide SNPs (SNP-based heritability, h2_SNP) using Restricted
  344. Maximum Likelihood (REML).
  345. Args:
  346. grm: GRM file prefix (from gcta_make_grm).
  347. pheno: Phenotype file path.
  348. out: Output file prefix. Produces {out}.hsq.
  349. qcovar: Quantitative covariate file.
  350. covar: Categorical covariate file.
  351. mpheno: Phenotype column number (0 = first column).
  352. thread_num: Number of CPU threads.
  353. reml_priors: Prior values of variance explained (space-separated).
  354. reml_priors_var: Prior values of variance components (space-separated).
  355. reml_maxit: Maximum REML iterations (default 100).
  356. prevalence: Disease prevalence for liability conversion (-1 = not used).
  357. reml_no_constrain: If True, do not constrain variance components.
  358. reml_no_lrt: If True, skip likelihood ratio test.
  359. reml_pred_rand: If True, predict random effects (BLUP).
  360. reml_est_fix: If True, estimate fixed effects.
  361. grm_cutoff: GRM cutoff for related pairs (-1 = no cutoff).
  362. gxe: GxE interaction file.
  363. work_dir: Working directory for GCTA.
  364. Returns:
  365. JSON with execution results, log content, and output file list.
  366. """
  367. base = ["--grm", grm, "--pheno", pheno,
  368. "--thread-num", str(thread_num), "--reml",
  369. "--reml-maxit", str(reml_maxit), "--out", out]
  370. args = _build_args(base, qcovar=qcovar or None, covar=covar or None,
  371. mpheno=mpheno or None,
  372. reml_priors=reml_priors or None,
  373. reml_priors_var=reml_priors_var or None,
  374. prevalence=prevalence if prevalence > 0 else None,
  375. reml_no_constrain=reml_no_constrain,
  376. reml_no_lrt=reml_no_lrt,
  377. reml_pred_rand=reml_pred_rand,
  378. reml_est_fix=reml_est_fix,
  379. grm_cutoff=grm_cutoff if grm_cutoff > 0 else None,
  380. gxe=gxe or None)
  381. return gcta_run(args, work_dir)
  382. @mcp.tool()
  383. def gcta_bivariate_reml(
  384. grm: str,
  385. pheno: str,
  386. out: str = "gcta_bireml",
  387. qcovar: str = "",
  388. covar: str = "",
  389. mphen: int = 1,
  390. mphen2: int = 2,
  391. thread_num: int = 1,
  392. reml_maxit: int = 100,
  393. reml_bivar_prevalence: str = "",
  394. reml_bivar_nocove: bool = False,
  395. reml_bivar_no_constrain: bool = False,
  396. grm_cutoff: float = -1.0,
  397. work_dir: str = "",
  398. ) -> str:
  399. """Run bivariate REML analysis to estimate genetic correlation (rg).
  400. Estimates the genetic correlation between two traits using bivariate
  401. GREML. Requires a phenotype file with at least two columns.
  402. Args:
  403. grm: GRM file prefix.
  404. pheno: Phenotype file (with at least 2 trait columns).
  405. out: Output prefix. Produces {out}.hsq.
  406. qcovar: Quantitative covariate file.
  407. covar: Categorical covariate file.
  408. mphen: First phenotype column number (default 1).
  409. mphen2: Second phenotype column number (default 2).
  410. thread_num: Number of CPU threads.
  411. reml_maxit: Maximum REML iterations.
  412. reml_bivar_prevalence: Two prevalence values (space-separated).
  413. reml_bivar_nocove: If True, ignore residual covariance.
  414. reml_bivar_no_constrain: If True, no constrain on variance components.
  415. grm_cutoff: GRM cutoff (-1 = no cutoff).
  416. work_dir: Working directory for GCTA.
  417. Returns:
  418. JSON with execution results, log content, and output file list.
  419. """
  420. base = ["--grm", grm, "--pheno", pheno,
  421. "--thread-num", str(thread_num),
  422. "--reml-bivar", str(mphen), str(mphen2),
  423. "--reml-maxit", str(reml_maxit), "--out", out]
  424. args = _build_args(base, qcovar=qcovar or None, covar=covar or None,
  425. reml_bivar_prevalence=reml_bivar_prevalence or None,
  426. reml_bivar_nocove=reml_bivar_nocove,
  427. reml_bivar_no_constrain=reml_bivar_no_constrain,
  428. grm_cutoff=grm_cutoff if grm_cutoff > 0 else None)
  429. return gcta_run(args, work_dir)
  430. @mcp.tool()
  431. def gcta_hereg(
  432. grm: str,
  433. pheno: str,
  434. out: str = "gcta_hereg",
  435. qcovar: str = "",
  436. covar: str = "",
  437. mpheno: int = 0,
  438. thread_num: int = 1,
  439. grm_cutoff: float = -1.0,
  440. work_dir: str = "",
  441. ) -> str:
  442. """Run Haseman-Elston regression to estimate variance components.
  443. HE regression is a method-of-moments estimator that is faster but
  444. less precise than REML. Useful as a sanity check or when REML
  445. fails to converge.
  446. Args:
  447. grm: GRM file prefix.
  448. pheno: Phenotype file path.
  449. out: Output prefix.
  450. qcovar: Quantitative covariate file.
  451. covar: Categorical covariate file.
  452. mpheno: Phenotype column number (0 = first).
  453. thread_num: Number of CPU threads.
  454. grm_cutoff: GRM cutoff (-1 = no cutoff).
  455. work_dir: Working directory for GCTA.
  456. Returns:
  457. JSON with execution results, log content, and output file list.
  458. """
  459. base = ["--grm", grm, "--pheno", pheno,
  460. "--thread-num", str(thread_num), "--HEreg",
  461. "--out", out]
  462. args = _build_args(base, qcovar=qcovar or None, covar=covar or None,
  463. mpheno=mpheno or None,
  464. grm_cutoff=grm_cutoff if grm_cutoff > 0 else None)
  465. return gcta_run(args, work_dir)
  466. # ============================================================================
  467. # PCA tools
  468. # ============================================================================
  469. @mcp.tool()
  470. def gcta_pca(
  471. grm: str,
  472. out: str = "gcta_pca",
  473. pc_num: int = 20,
  474. thread_num: int = 1,
  475. work_dir: str = "",
  476. ) -> str:
  477. """Perform Principal Component Analysis (PCA) from a GRM.
  478. Computes principal components (PCs) from the genetic relationship
  479. matrix to capture population structure. Output eigenvalues and
  480. eigenvectors are saved in {out}.eigenval and {out}.eigenvec.
  481. Args:
  482. grm: GRM file prefix (from gcta_make_grm).
  483. out: Output file prefix.
  484. pc_num: Number of principal components to output (default 20).
  485. thread_num: Number of CPU threads.
  486. work_dir: Working directory for GCTA.
  487. Returns:
  488. JSON with execution results, log content, and output file list.
  489. """
  490. args = (f"--grm {grm} --pca {pc_num} "
  491. f"--thread-num {thread_num} --out {out}")
  492. return gcta_run(args, work_dir)
  493. # ============================================================================
  494. # Association analysis tools
  495. # ============================================================================
  496. @mcp.tool()
  497. def gcta_mlma(
  498. bfile: str,
  499. grm: str,
  500. pheno: str,
  501. out: str = "gcta_mlma",
  502. qcovar: str = "",
  503. covar: str = "",
  504. mpheno: int = 0,
  505. thread_num: int = 1,
  506. reml_maxit: int = 100,
  507. loco: bool = False,
  508. maf: float = 0.0,
  509. autosome_num: int = 22,
  510. work_dir: str = "",
  511. ) -> str:
  512. """Run Mixed Linear Model Association (MLMA) analysis.
  513. Performs genome-wide association analysis using a linear mixed model
  514. that accounts for population structure via the GRM.
  515. Set ``loco=True`` to use the Leave-One-Chromosome-Out (LOCO) method,
  516. which is more computationally efficient for large datasets.
  517. Args:
  518. bfile: PLINK binary file prefix.
  519. grm: GRM file prefix.
  520. pheno: Phenotype file path.
  521. out: Output file prefix. Produces {out}.mlma (or .loco.mlma).
  522. qcovar: Quantitative covariate file.
  523. covar: Categorical covariate file.
  524. mpheno: Phenotype column number (0 = first).
  525. thread_num: Number of CPU threads.
  526. reml_maxit: Maximum REML iterations.
  527. loco: If True, use MLMA-LOCO method.
  528. maf: Minor allele frequency filter (0 = no filter).
  529. autosome_num: Number of autosomes.
  530. work_dir: Working directory for GCTA.
  531. Returns:
  532. JSON with execution results, log content, and output file list.
  533. """
  534. if loco:
  535. mlma_flag = "--mlma-loco"
  536. else:
  537. mlma_flag = "--mlma"
  538. base = ["--bfile", bfile, "--grm", grm, "--pheno", pheno,
  539. "--autosome-num", str(autosome_num),
  540. "--thread-num", str(thread_num),
  541. mlma_flag, "--reml-maxit", str(reml_maxit), "--out", out]
  542. args = _build_args(base, qcovar=qcovar or None, covar=covar or None,
  543. mpheno=mpheno or None, maf=maf if maf > 0 else None)
  544. return gcta_run(args, work_dir)
  545. @mcp.tool()
  546. def gcta_cojo(
  547. bfile: str,
  548. cojo_file: str,
  549. out: str = "gcta_cojo",
  550. method: str = "slct",
  551. cojo_p: float = 5e-8,
  552. cojo_wind: int = 10000,
  553. cojo_collinear: float = 0.9,
  554. cojo_cond_snplist: str = "",
  555. cojo_gc: float = -1.0,
  556. cojo_sblup_fac: float = -1.0,
  557. cojo_top_snps: int = -1,
  558. thread_num: int = 1,
  559. maf: float = 0.0,
  560. work_dir: str = "",
  561. ) -> str:
  562. """Run Conditional and Joint (COJO) analysis of GWAS summary data.
  563. COJO performs stepwise selection, conditional analysis, or joint
  564. analysis of GWAS summary statistics, using an LD reference panel
  565. from PLINK bed data.
  566. Methods:
  567. "slct" - Stepwise selection (backward + forward)
  568. "forward" - Forward-only selection
  569. "backward" - Backward-only selection
  570. "cond" - Conditional analysis (condition on given SNPs)
  571. "joint" - Joint analysis (all SNPs in one model)
  572. "sblup" - SBLUP (summary-data BLUP)
  573. Args:
  574. bfile: PLINK binary file prefix (LD reference panel).
  575. cojo_file: GWAS summary data file (.ma format).
  576. out: Output file prefix.
  577. method: COJO method (see above).
  578. cojo_p: P-value threshold for selection (default 5e-8).
  579. cojo_wind: Window size in Kb for LD calculation (default 10000).
  580. cojo_collinear: Collinearity threshold (default 0.9).
  581. cojo_cond_snplist: SNP list file for conditional analysis.
  582. cojo_gc: Genomic control inflation factor (-1 = not used).
  583. cojo_sblup_fac: SBLUP factor (for sblup method).
  584. cojo_top_snps: Number of top SNPs to select (-1 = no limit).
  585. thread_num: Number of CPU threads.
  586. maf: Minor allele frequency filter.
  587. work_dir: Working directory for GCTA.
  588. Returns:
  589. JSON with execution results, log content, and output file list.
  590. """
  591. method = method.lower().strip()
  592. method_map = {
  593. "slct": "--cojo-slct",
  594. "stepwise": "--cojo-slct",
  595. "forward": "--cojo-forward",
  596. "backward": "--cojo-backward",
  597. "joint": "--cojo-joint",
  598. "sblup": "--cojo-sblup",
  599. }
  600. if method not in method_map and method != "cond":
  601. return json.dumps({
  602. "error": f"Unknown method '{method}'. Use: slct, forward, backward, cond, joint, sblup"
  603. }, indent=2)
  604. base = ["--bfile", bfile, "--cojo-file", cojo_file,
  605. "--thread-num", str(thread_num), "--out", out]
  606. if method == "cond":
  607. base.extend(["--cojo-cond", cojo_cond_snplist])
  608. elif method == "sblup":
  609. base.extend([method_map[method], str(cojo_sblup_fac)])
  610. else:
  611. base.append(method_map[method])
  612. args = _build_args(base, cojo_p=cojo_p, cojo_wind=cojo_wind,
  613. cojo_collinear=cojo_collinear,
  614. cojo_gc=cojo_gc if cojo_gc > 0 else None,
  615. cojo_top_snps=cojo_top_snps if cojo_top_snps > 0 else None,
  616. maf=maf if maf > 0 else None)
  617. return gcta_run(args, work_dir)
  618. @mcp.tool()
  619. def gcta_gsmr(
  620. bfile: str,
  621. gsmr_file: str,
  622. out: str = "gcta_gsmr",
  623. gsmr_direction: int = 0,
  624. gsmr2_beta: bool = False,
  625. thread_num: int = 1,
  626. maf: float = 0.0,
  627. work_dir: str = "",
  628. ) -> str:
  629. """Run GSMR (Generalized Summary-data Mendelian Randomization) analysis.
  630. GSMR estimates the causal effect of an exposure on an outcome using
  631. GWAS summary data and an LD reference panel.
  632. Args:
  633. bfile: PLINK binary file prefix (LD reference).
  634. gsmr_file: File listing exposure and outcome GWAS summary files.
  635. out: Output file prefix.
  636. gsmr_direction: 0 = forward-GSMR, 1 = reverse-GSMR, 2 = bi-GSMR.
  637. gsmr2_beta: If True, use GSMR2-beta version (multi-SNP HEIDI).
  638. thread_num: Number of CPU threads.
  639. maf: Minor allele frequency filter.
  640. work_dir: Working directory for GCTA.
  641. Returns:
  642. JSON with execution results, log content, and output file list.
  643. """
  644. base = ["--bfile", bfile, "--gsmr-file", gsmr_file,
  645. "--gsmr-direction", str(gsmr_direction),
  646. "--thread-num", str(thread_num), "--out", out]
  647. args = _build_args(base, gsmr2_beta=gsmr2_beta,
  648. maf=maf if maf > 0 else None)
  649. return gcta_run(args, work_dir)
  650. @mcp.tool()
  651. def gcta_mtcojo(
  652. bfile: str,
  653. mtcojo_file: str,
  654. mtcojo_bxy: str,
  655. out: str = "gcta_mtcojo",
  656. thread_num: int = 1,
  657. maf: float = 0.0,
  658. work_dir: str = "",
  659. ) -> str:
  660. """Run mtCOJO (Multi-trait COJO) analysis.
  661. mtCOJO performs conditional analysis across multiple traits using
  662. GWAS summary data, adjusting for the genetic correlation between
  663. traits.
  664. Args:
  665. bfile: PLINK binary file prefix (LD reference).
  666. mtcojo_file: File listing trait GWAS summary files.
  667. mtcojo_bxy: File with causal effect estimates between traits.
  668. out: Output file prefix.
  669. thread_num: Number of CPU threads.
  670. maf: Minor allele frequency filter.
  671. work_dir: Working directory for GCTA.
  672. Returns:
  673. JSON with execution results, log content, and output file list.
  674. """
  675. base = ["--bfile", bfile, "--mtcojo-file", mtcojo_file,
  676. "--mtcojo-bxy", mtcojo_bxy,
  677. "--thread-num", str(thread_num), "--out", out]
  678. args = _build_args(base, maf=maf if maf > 0 else None)
  679. return gcta_run(args, work_dir)
  680. @mcp.tool()
  681. def gcta_fastgwa(
  682. bfile: str,
  683. pheno: str,
  684. out: str = "gcta_fastgwa",
  685. qcovar: str = "",
  686. covar: str = "",
  687. grm: str = "",
  688. method: str = "fastGWA-mlm",
  689. thread_num: int = 1,
  690. maf: float = 0.0,
  691. autosome_num: int = 22,
  692. work_dir: str = "",
  693. ) -> str:
  694. """Run fastGWA genome-wide association analysis.
  695. fastGWA is an efficient mixed-model association method that uses
  696. sparse GRM techniques for improved speed on large datasets.
  697. Methods:
  698. "fastGWA" - fastGWA (requires --grm)
  699. "fastGWA-mlm" - fastGWA-MLM (linear mixed model)
  700. "fastGWA-mlm-exact" - fastGWA-MLM exact mode
  701. "fastGWA-lr" - fastGWA linear regression (no GRM)
  702. Args:
  703. bfile: PLINK binary file prefix.
  704. pheno: Phenotype file path.
  705. out: Output file prefix.
  706. qcovar: Quantitative covariate file.
  707. covar: Categorical covariate file.
  708. grm: GRM file prefix (for fastGWA with GRM).
  709. method: fastGWA method (see above).
  710. thread_num: Number of CPU threads.
  711. maf: Minor allele frequency filter.
  712. autosome_num: Number of autosomes.
  713. work_dir: Working directory for GCTA.
  714. Returns:
  715. JSON with execution results, log content, and output file list.
  716. """
  717. method = method.lower().strip()
  718. method_map = {
  719. "fastgwa": "--fastGWA",
  720. "fastgwa-mlm": "--fastGWA-mlm",
  721. "fastgwa-mlm-exact": "--fastGWA-mlm-exact",
  722. "fastgwa-lr": "--fastGWA-lr",
  723. }
  724. if method not in method_map:
  725. return json.dumps({
  726. "error": f"Unknown method '{method}'. Use: fastGWA, fastGWA-mlm, fastGWA-mlm-exact, fastGWA-lr"
  727. }, indent=2)
  728. base = ["--bfile", bfile, "--pheno", pheno,
  729. "--autosome-num", str(autosome_num),
  730. "--thread-num", str(thread_num),
  731. method_map[method], "--out", out]
  732. args = _build_args(base, qcovar=qcovar or None, covar=covar or None,
  733. grm=grm or None, maf=maf if maf > 0 else None)
  734. return gcta_run(args, work_dir)
  735. @mcp.tool()
  736. def gcta_fastbat(
  737. bfile: str,
  738. fastbat_file: str,
  739. out: str = "gcta_fastbat",
  740. fastbat_gene_list: str = "",
  741. fastbat_set_list: str = "",
  742. fastbat_wind: int = 50,
  743. fastbat_ld_cutoff: float = 0.9,
  744. thread_num: int = 1,
  745. maf: float = 0.0,
  746. work_dir: str = "",
  747. ) -> str:
  748. """Run fastBAT gene-based association test.
  749. fastBAT performs gene-based association tests by combining
  750. SNP-level p-values within genes, accounting for LD structure.
  751. Args:
  752. bfile: PLINK binary file prefix (LD reference).
  753. fastbat_file: GWAS summary data file (.ma format).
  754. out: Output file prefix.
  755. fastbat_gene_list: Gene annotation file (gene -> SNPs mapping).
  756. fastbat_set_list: SNP set file (predefined sets).
  757. fastbat_wind: Window size in Kb for gene boundaries (default 50).
  758. fastbat_ld_cutoff: LD r2 cutoff for removing correlated SNPs (default 0.9).
  759. thread_num: Number of CPU threads.
  760. maf: Minor allele frequency filter.
  761. work_dir: Working directory for GCTA.
  762. Returns:
  763. JSON with execution results, log content, and output file list.
  764. """
  765. base = ["--bfile", bfile, "--fastBAT", fastbat_file,
  766. "--thread-num", str(thread_num), "--out", out]
  767. args = _build_args(base, fastBAT_gene_list=fastbat_gene_list or None,
  768. fastBAT_set_list=fastbat_set_list or None,
  769. fastBAT_wind=fastbat_wind,
  770. fastBAT_ld_cutoff=fastbat_ld_cutoff,
  771. maf=maf if maf > 0 else None)
  772. return gcta_run(args, work_dir)
  773. # ============================================================================
  774. # Simulation tools
  775. # ============================================================================
  776. @mcp.tool()
  777. def gcta_simu_qt(
  778. bfile: str,
  779. out: str = "gcta_simu_qt",
  780. simu_hsq: float = 0.1,
  781. simu_rep: int = 1,
  782. simu_causal_loci: str = "",
  783. simu_seed: float = -1.0,
  784. thread_num: int = 1,
  785. maf: float = 0.0,
  786. work_dir: str = "",
  787. ) -> str:
  788. """Simulate quantitative trait phenotypes based on real genotype data.
  789. Uses the genotype data from PLINK bed files to simulate quantitative
  790. traits with a specified heritability. Useful for power analysis and
  791. method evaluation.
  792. Args:
  793. bfile: PLINK binary file prefix.
  794. out: Output file prefix.
  795. simu_hsq: Simulated heritability (default 0.1).
  796. simu_rep: Number of simulation repetitions (default 1).
  797. simu_causal_loci: File listing causal loci.
  798. simu_seed: Random seed for simulation (-1 = auto).
  799. thread_num: Number of CPU threads.
  800. maf: Minor allele frequency filter.
  801. work_dir: Working directory for GCTA.
  802. Returns:
  803. JSON with execution results, log content, and output file list.
  804. """
  805. base = ["--bfile", bfile, "--simu-qt",
  806. "--simu-hsq", str(simu_hsq),
  807. "--simu-rep", str(simu_rep),
  808. "--thread-num", str(thread_num), "--out", out]
  809. args = _build_args(base, simu_causal_loci=simu_causal_loci or None,
  810. simu_seed=simu_seed if simu_seed > 0 else None,
  811. maf=maf if maf > 0 else None)
  812. return gcta_run(args, work_dir)
  813. @mcp.tool()
  814. def gcta_simu_cc(
  815. bfile: str,
  816. simu_case_num: int,
  817. simu_control_num: int,
  818. out: str = "gcta_simu_cc",
  819. simu_hsq: float = 0.1,
  820. simu_k: float = 0.1,
  821. simu_rep: int = 1,
  822. simu_causal_loci: str = "",
  823. simu_seed: float = -1.0,
  824. thread_num: int = 1,
  825. maf: float = 0.0,
  826. work_dir: str = "",
  827. ) -> str:
  828. """Simulate case-control phenotypes based on real genotype data.
  829. Uses genotype data from PLINK bed files to simulate case-control
  830. phenotypes with specified heritability and disease prevalence.
  831. Args:
  832. bfile: PLINK binary file prefix.
  833. simu_case_num: Number of cases to simulate.
  834. simu_control_num: Number of controls to simulate.
  835. out: Output file prefix.
  836. simu_hsq: Simulated heritability (default 0.1).
  837. simu_k: Simulated disease prevalence (default 0.1).
  838. simu_rep: Number of simulation repetitions (default 1).
  839. simu_causal_loci: File listing causal loci.
  840. simu_seed: Random seed (-1 = auto).
  841. thread_num: Number of CPU threads.
  842. maf: Minor allele frequency filter.
  843. work_dir: Working directory for GCTA.
  844. Returns:
  845. JSON with execution results, log content, and output file list.
  846. """
  847. base = ["--bfile", bfile, "--simu-cc",
  848. str(simu_case_num), str(simu_control_num),
  849. "--simu-hsq", str(simu_hsq),
  850. "--simu-k", str(simu_k),
  851. "--simu-rep", str(simu_rep),
  852. "--thread-num", str(thread_num), "--out", out]
  853. args = _build_args(base, simu_causal_loci=simu_causal_loci or None,
  854. simu_seed=simu_seed if simu_seed > 0 else None,
  855. maf=maf if maf > 0 else None)
  856. return gcta_run(args, work_dir)
  857. # ============================================================================
  858. # Population genetics tools
  859. # ============================================================================
  860. @mcp.tool()
  861. def gcta_fst(
  862. bfile: str,
  863. sub_popu: str,
  864. out: str = "gcta_fst",
  865. thread_num: int = 1,
  866. maf: float = 0.0,
  867. work_dir: str = "",
  868. ) -> str:
  869. """Calculate Fst (fixation index) for population differentiation analysis.
  870. Computes pairwise Fst between subpopulations defined in the
  871. sub-population file.
  872. Args:
  873. bfile: PLINK binary file prefix.
  874. sub_popu: Subpopulation assignment file (FID, IID, pop ID).
  875. out: Output file prefix.
  876. thread_num: Number of CPU threads.
  877. maf: Minor allele frequency filter.
  878. work_dir: Working directory for GCTA.
  879. Returns:
  880. JSON with execution results, log content, and output file list.
  881. """
  882. args = (f"--bfile {bfile} --fst --sub-popu {sub_popu} "
  883. f"--thread-num {thread_num} --out {out}")
  884. if maf > 0:
  885. args += f" --maf {maf}"
  886. return gcta_run(args, work_dir)
  887. # ============================================================================
  888. # Data management tools
  889. # ============================================================================
  890. @mcp.tool()
  891. def gcta_make_bed(
  892. bfile: str,
  893. out: str = "gcta_bed",
  894. maf: float = 0.0,
  895. thread_num: int = 1,
  896. extract: str = "",
  897. exclude: str = "",
  898. chr_filter: int = 0,
  899. autosome: bool = False,
  900. autosome_num: int = 22,
  901. work_dir: str = "",
  902. ) -> str:
  903. """Convert / filter genotype data and output PLINK bed format.
  904. Performs data management operations: SNP/individual filtering,
  905. chromosome extraction, and output in PLINK binary format.
  906. Args:
  907. bfile: PLINK binary file prefix (input).
  908. out: Output file prefix.
  909. maf: Minor allele frequency filter (0 = no filter).
  910. thread_num: Number of CPU threads.
  911. extract: File of SNP IDs to include.
  912. exclude: File of SNP IDs to exclude.
  913. chr_filter: Restrict to a specific chromosome (0 = no restriction).
  914. autosome: If True, restrict to autosomes.
  915. autosome_num: Number of autosomes.
  916. work_dir: Working directory for GCTA.
  917. Returns:
  918. JSON with execution results, log content, and output file list.
  919. """
  920. base = ["--bfile", bfile, "--make-bed",
  921. "--autosome-num", str(autosome_num),
  922. "--thread-num", str(thread_num), "--out", out]
  923. args = _build_args(base, maf=maf if maf > 0 else None,
  924. extract=extract or None, exclude=exclude or None,
  925. chr=chr_filter if chr_filter > 0 else None,
  926. autosome=autosome)
  927. return gcta_run(args, work_dir)
  928. @mcp.tool()
  929. def gcta_ld_pruning(
  930. bfile: str,
  931. ld_pruning_rsq: float = 0.1,
  932. out: str = "gcta_ld_prune",
  933. ld_wind: float = 10000.0,
  934. thread_num: int = 1,
  935. maf: float = 0.0,
  936. work_dir: str = "",
  937. ) -> str:
  938. """Perform LD pruning on genotype data.
  939. Removes SNPs in high LD with each other, retaining a set of
  940. approximately independent SNPs. Useful for reducing redundancy
  941. before downstream analyses.
  942. Args:
  943. bfile: PLINK binary file prefix.
  944. ld_pruning_rsq: LD r2 threshold for pruning (default 0.1).
  945. out: Output file prefix.
  946. ld_wind: LD window size in Kb (default 10000).
  947. thread_num: Number of CPU threads.
  948. maf: Minor allele frequency filter.
  949. work_dir: Working directory for GCTA.
  950. Returns:
  951. JSON with execution results, log content, and output file list.
  952. """
  953. args = (f"--bfile {bfile} --ld-pruning {ld_pruning_rsq} "
  954. f"--ld-wind {ld_wind} "
  955. f"--thread-num {thread_num} --out {out}")
  956. if maf > 0:
  957. args += f" --maf {maf}"
  958. return gcta_run(args, work_dir)
  959. @mcp.tool()
  960. def gcta_ld_score(
  961. bfile: str,
  962. out: str = "gcta_ld_score",
  963. ld_wind: float = 10000.0,
  964. thread_num: int = 1,
  965. maf: float = 0.0,
  966. work_dir: str = "",
  967. ) -> str:
  968. """Calculate LD scores for SNPs in genotype data.
  969. Computes LD scores (sum of LD r2 with neighboring SNPs) for each
  970. SNP. Used as input for LD score regression analyses.
  971. Args:
  972. bfile: PLINK binary file prefix.
  973. out: Output file prefix.
  974. ld_wind: LD window size in Kb (default 10000).
  975. thread_num: Number of CPU threads.
  976. maf: Minor allele frequency filter.
  977. work_dir: Working directory for GCTA.
  978. Returns:
  979. JSON with execution results, log content, and output file list.
  980. """
  981. args = (f"--bfile {bfile} --ld-score --ld-wind {ld_wind} "
  982. f"--thread-num {thread_num} --out {out}")
  983. if maf > 0:
  984. args += f" --maf {maf}"
  985. return gcta_run(args, work_dir)
  986. # ============================================================================
  987. # ACAT tools
  988. # ============================================================================
  989. @mcp.tool()
  990. def gcta_acat(
  991. gene_list: str,
  992. snp_list: str,
  993. out: str = "acat_res.csv",
  994. max_maf: float = 0.01,
  995. min_mac: int = 20,
  996. wind: int = 0,
  997. work_dir: str = "",
  998. ) -> str:
  999. """Run ACAT (Aggregated Cauchy Association Test) gene-based test.
  1000. ACAT combines p-values from multiple SNPs within a gene using a
  1001. Cauchy combination method, providing a gene-level association test.
  1002. Args:
  1003. gene_list: Gene list file (gene -> chromosome, start, end).
  1004. snp_list: SNP list file with p-values.
  1005. out: Output file (default acat_res.csv).
  1006. max_maf: Maximum MAF for included SNPs (default 0.01).
  1007. min_mac: Minimum minor allele count (default 20).
  1008. wind: Extension length for gene boundaries (default 0).
  1009. work_dir: Working directory for GCTA.
  1010. Returns:
  1011. JSON with execution results, log content, and output file list.
  1012. """
  1013. args = (f"--acat --gene-list {gene_list} --snp-list {snp_list} "
  1014. f"--max-maf {max_maf} --min-mac {min_mac} "
  1015. f"--wind {wind} --out {out}")
  1016. return gcta_run(args, work_dir)
  1017. # ============================================================================
  1018. # File management tools
  1019. # ============================================================================
  1020. @mcp.tool()
  1021. def gcta_list_files(directory: str = ".", pattern: str = "*") -> str:
  1022. """List files in a directory, optionally filtered by pattern.
  1023. Args:
  1024. directory: Directory path (default: current directory).
  1025. pattern: Glob pattern (default: "*" = all files).
  1026. Examples: "*.log", "*.hsq", "*.grm.*", "test*"
  1027. Returns:
  1028. JSON with list of files and their sizes.
  1029. """
  1030. if not os.path.exists(directory):
  1031. return json.dumps({"error": f"Directory not found: {directory}"}, indent=2)
  1032. files = []
  1033. search_pattern = os.path.join(directory, pattern)
  1034. for f in sorted(glob.glob(search_pattern)):
  1035. if os.path.isfile(f):
  1036. files.append({
  1037. "file": os.path.basename(f),
  1038. "path": os.path.abspath(f),
  1039. "size_bytes": os.path.getsize(f),
  1040. })
  1041. return json.dumps({
  1042. "directory": os.path.abspath(directory),
  1043. "pattern": pattern,
  1044. "file_count": len(files),
  1045. "files": files,
  1046. }, indent=2, ensure_ascii=False)
  1047. @mcp.tool()
  1048. def gcta_read_file(filepath: str, max_lines: int = 200) -> str:
  1049. """Read and return the content of a text file.
  1050. Useful for inspecting GCTA output files such as .log, .hsq, .mlma,
  1051. .ma, etc.
  1052. Args:
  1053. filepath: Path to the file to read.
  1054. max_lines: Maximum number of lines to return (default 200).
  1055. Returns:
  1056. JSON with file content (truncated to max_lines).
  1057. """
  1058. if not os.path.exists(filepath):
  1059. return json.dumps({"error": f"File not found: {filepath}"}, indent=2)
  1060. try:
  1061. with open(filepath, "r", errors="replace") as f:
  1062. lines = []
  1063. for i, line in enumerate(f):
  1064. if i >= max_lines:
  1065. lines.append(f"... (truncated at {max_lines} lines)")
  1066. break
  1067. lines.append(line.rstrip("\n\r"))
  1068. return json.dumps({
  1069. "file": os.path.abspath(filepath),
  1070. "lines_shown": len(lines),
  1071. "content": "\n".join(lines),
  1072. }, indent=2, ensure_ascii=False)
  1073. except Exception as e:
  1074. return json.dumps({"error": str(e)}, indent=2)
  1075. # ============================================================================
  1076. # Help documentation
  1077. # ============================================================================
  1078. def _get_help_docs() -> dict:
  1079. """Return a dictionary of help documentation by topic."""
  1080. return {
  1081. "all": _help_all(),
  1082. "data": _help_data(),
  1083. "grm": _help_grm(),
  1084. "reml": _help_reml(),
  1085. "bivariate_reml": _help_bivariate_reml(),
  1086. "hereg": _help_hereg(),
  1087. "pca": _help_pca(),
  1088. "mlma": _help_mlma(),
  1089. "cojo": _help_cojo(),
  1090. "gsmr": _help_gsmr(),
  1091. "mtcojo": _help_mtcojo(),
  1092. "fastgwa": _help_fastgwa(),
  1093. "fastbat": _help_fastbat(),
  1094. "simulation": _help_simulation(),
  1095. "ld": _help_ld(),
  1096. "fst": _help_fst(),
  1097. "expression": _help_expression(),
  1098. "acat": _help_acat(),
  1099. "options": _help_options(),
  1100. }
  1101. def _help_all():
  1102. return """GCTA (Genome-wide Complex Trait Analysis) - Available Analyses
  1103. GCTA is a tool for genome-wide association study (GWAS) analyses. It supports:
  1104. 1. DATA MANAGEMENT (gcta_make_bed, gcta_run)
  1105. - Read PLINK binary PED format (.bed/.bim/.fam)
  1106. - Filter SNPs and individuals
  1107. - Output filtered data in PLINK bed format
  1108. - Calculate allele frequencies, recode genotypes
  1109. 2. GRM CONSTRUCTION (gcta_make_grm)
  1110. - Calculate Genetic Relationship Matrix (GRM) from genotype data
  1111. - Support for additive, dominance, X-chromosome, and inbreeding GRMs
  1112. - Multi-component GRM analysis
  1113. 3. REML / GREML (gcta_reml)
  1114. - Estimate SNP-based heritability (h2_SNP) using REML
  1115. - Support for covariates, prevalence, and prior specification
  1116. - BLUP prediction of random effects
  1117. 4. BIVARIATE REML (gcta_bivariate_reml)
  1118. - Estimate genetic correlation (rg) between two traits
  1119. - Bivariate GREML analysis
  1120. 5. HE REGRESSION (gcta_hereg)
  1121. - Haseman-Elston regression for variance component estimation
  1122. - Faster but less precise than REML
  1123. 6. PCA (gcta_pca)
  1124. - Principal component analysis from GRM
  1125. - Population structure analysis
  1126. 7. MLMA (gcta_mlma)
  1127. - Mixed Linear Model Association analysis
  1128. - MLMA-LOCO (Leave-One-Chromosome-Out) for efficiency
  1129. - Genome-wide association testing
  1130. 8. COJO (gcta_cojo)
  1131. - Conditional and joint analysis of GWAS summary data
  1132. - Stepwise selection, conditional analysis, joint analysis
  1133. - SBLUP (summary-data BLUP)
  1134. 9. GSMR (gcta_gsmr)
  1135. - Generalized Summary-data Mendelian Randomization
  1136. - Causal effect estimation using GWAS summary data
  1137. 10. mtCOJO (gcta_mtcojo)
  1138. - Multi-trait COJO analysis
  1139. - Conditional analysis across multiple traits
  1140. 11. fastGWA (gcta_fastgwa)
  1141. - Efficient mixed-model association analysis
  1142. - fastGWA-MLM, fastGWA-MLM-exact, fastGWA-LR methods
  1143. - Sparse GRM for improved speed
  1144. 12. fastBAT (gcta_fastbat)
  1145. - Gene-based association test
  1146. - Combines SNP-level p-values within genes
  1147. 13. SIMULATION (gcta_simu_qt, gcta_simu_cc)
  1148. - Simulate quantitative trait phenotypes
  1149. - Simulate case-control phenotypes
  1150. - Based on real genotype data
  1151. 14. LD ANALYSIS (gcta_ld_pruning, gcta_ld_score)
  1152. - LD pruning to identify independent SNPs
  1153. - LD score calculation
  1154. 15. FST (gcta_fst)
  1155. - Fixation index for population differentiation analysis
  1156. 16. ACAT (gcta_acat)
  1157. - Aggregated Cauchy Association Test
  1158. - Gene-based test combining SNP p-values
  1159. 17. EXPRESSION DATA (gcta_run)
  1160. - Expression-based relationship matrix (ERM)
  1161. - ecojo analysis
  1162. - make-erm, make-erm-gz
  1163. Use gcta_help(topic) for detailed documentation on any analysis type.
  1164. Use gcta_run(args) for full command-line access to all GCTA options.
  1165. """
  1166. def _help_data():
  1167. return """GCTA Data Management
  1168. INPUT FORMAT:
  1169. --bfile <prefix> PLINK binary PED format (.bed/.bim/.fam)
  1170. --mbfile <file> List of multiple bfile prefixes
  1171. --bfile2 <prefix> Second dataset for comparison
  1172. --dosage-mach <dose> <info> Mach dosage format
  1173. --dosage-mach-gz <dose> <info> Mach dosage (gzipped)
  1174. --dosage-beagle <dose> <info> Beagle dosage format
  1175. FILTERING:
  1176. --maf <val> Minor allele frequency filter (0-0.5)
  1177. --max-maf <val> Maximum MAF filter
  1178. --chr <num> Restrict to chromosome
  1179. --autosome Restrict to autosomes
  1180. --autosome-num <num> Number of autosomes (default 22)
  1181. --extract <file> Include only SNPs in file
  1182. --exclude <file> Exclude SNPs in file
  1183. --keep <file> Keep only individuals in file
  1184. --remove <file> Remove individuals in file
  1185. OUTPUT:
  1186. --make-bed Output in PLINK bed format
  1187. --freq Calculate and output allele frequencies
  1188. --recode Recode genotypes
  1189. --recode-nomiss Recode without missing data
  1190. --recode-std Recode with standardization
  1191. --out <prefix> Output file prefix
  1192. EXAMPLES:
  1193. # Filter SNPs by MAF and output PLINK bed
  1194. gcta_run("--bfile test --make-bed --maf 0.05 --out filtered")
  1195. # Extract chromosome 1 only
  1196. gcta_run("--bfile test --make-bed --chr 1 --out chr1")
  1197. # Calculate allele frequencies
  1198. gcta_run("--bfile test --freq --out freq")
  1199. """
  1200. def _help_grm():
  1201. return """GCTA GRM (Genetic Relationship Matrix) Construction
  1202. The GRM estimates pairwise genomic relatedness between individuals based
  1203. on genome-wide SNPs. It is the foundational step for most downstream
  1204. analyses (REML, PCA, MLMA).
  1205. BASIC COMMAND:
  1206. --bfile <prefix> --make-grm --out <output_prefix>
  1207. OUTPUT FILES:
  1208. {prefix}.grm.bin - GRM binary data (lower triangle, column-major)
  1209. {prefix}.grm.N.bin - Number of SNPs used (same format)
  1210. {prefix}.grm.id - Individual IDs (FID, IID)
  1211. OPTIONS:
  1212. --make-grm-alg <0|1> Algorithm: 0 = VanRaden (default), 1 = alternative
  1213. --grm-adj <val> GRM adjustment factor (0-1)
  1214. --grm-cutoff <val> Remove pairs with GRM > cutoff
  1215. --dc <0|1> Dosage compensation (0=none, 1=X chr)
  1216. --dominance Calculate dominance GRM
  1217. --make-grm-xchr Calculate X-chromosome GRM
  1218. --make-grm-inbred Calculate inbreeding GRM
  1219. --save-ram Use memory-saving mode
  1220. --autosome-num <num> Number of autosomes
  1221. --autosome Restrict to autosomes
  1222. --chr <num> Restrict to specific chromosome
  1223. --maf <val> MAF filter
  1224. --thread-num <num> Number of CPU threads
  1225. MULTI-GRM:
  1226. --mgrm <file> Multiple GRM file list
  1227. --mgrm-bin <file> Multiple GRM binary file list
  1228. --mgrm-gz <file> Multiple GRM gzipped file list
  1229. EXAMPLES:
  1230. # Basic GRM
  1231. gcta_make_grm(bfile="test", out="test_grm")
  1232. # GRM with MAF filter and 4 threads
  1233. gcta_make_grm(bfile="test", out="test_grm", maf=0.01, thread_num=4)
  1234. # Dominance GRM
  1235. gcta_make_grm(bfile="test", out="test_dgrm", dominance=True)
  1236. """
  1237. def _help_reml():
  1238. return """GCTA REML / GREML Analysis
  1239. REML (Restricted Maximum Likelihood) estimates the proportion of
  1240. phenotypic variance explained by all genome-wide SNPs (SNP-based
  1241. heritability, h2_SNP).
  1242. BASIC COMMAND:
  1243. --grm <prefix> --pheno <file> --reml --out <output_prefix>
  1244. REQUIRED INPUT:
  1245. --grm <prefix> GRM file prefix (from gcta_make_grm)
  1246. --pheno <file> Phenotype file (FID, IID, phenotype)
  1247. --reml Perform REML analysis
  1248. --out <prefix> Output file prefix
  1249. OUTPUT FILES:
  1250. {prefix}.hsq - Heritability estimates and SE
  1251. {prefix}.log - Analysis log
  1252. COVARIATES:
  1253. --qcovar <file> Quantitative covariate file
  1254. --covar <file> Categorical covariate file
  1255. REML OPTIONS:
  1256. --reml-maxit <num> Maximum iterations (default 100)
  1257. --reml-priors <vals> Prior values of variance explained
  1258. --reml-priors-var <vals> Prior values of variance components
  1259. --reml-no-constrain Do not constrain variance components
  1260. --reml-no-lrt Skip likelihood ratio test
  1261. --reml-pred-rand Predict random effects (BLUP)
  1262. --reml-est-fix Estimate fixed effects
  1263. OTHER OPTIONS:
  1264. --prevalence <val> Disease prevalence for liability conversion
  1265. --grm-cutoff <val> GRM cutoff for related pairs
  1266. --gxe <file> GxE interaction file
  1267. --mpheno <num> Phenotype column number
  1268. --thread-num <num> Number of CPU threads
  1269. EXAMPLES:
  1270. # Basic REML
  1271. gcta_reml(grm="test_grm", pheno="test.phen", out="test_reml")
  1272. # REML with covariates
  1273. gcta_reml(grm="test_grm", pheno="test.phen", out="test_reml",
  1274. qcovar="covariates.txt", covar="sex.txt")
  1275. """
  1276. def _help_bivariate_reml():
  1277. return """GCTA Bivariate REML Analysis
  1278. Bivariate REML estimates the genetic correlation (rg) between two traits
  1279. using bivariate GREML.
  1280. BASIC COMMAND:
  1281. --grm <prefix> --pheno <file> --reml-bivar <mphen> <mphen2> --out <prefix>
  1282. REQUIRED INPUT:
  1283. --grm <prefix> GRM file prefix
  1284. --pheno <file> Phenotype file (with 2+ trait columns)
  1285. --reml-bivar <p1> <p2> Bivariate REML with trait columns p1 and p2
  1286. --out <prefix> Output file prefix
  1287. OUTPUT FILES:
  1288. {prefix}.hsq - Variance components and genetic correlation
  1289. OPTIONS:
  1290. --reml-maxit <num> Maximum iterations
  1291. --reml-bivar-prevalence <k1> <k2> Prevalence for both traits
  1292. --reml-bivar-nocove Ignore residual covariance
  1293. --reml-bivar-no-constrain No constrain on variance components
  1294. --qcovar <file> Quantitative covariate file
  1295. --covar <file> Categorical covariate file
  1296. --grm-cutoff <val> GRM cutoff
  1297. --thread-num <num> Number of CPU threads
  1298. EXAMPLE:
  1299. gcta_bivariate_reml(grm="test_grm", pheno="traits.phen",
  1300. out="bireml", mphen=1, mphen2=2)
  1301. """
  1302. def _help_hereg():
  1303. return """GCTA Haseman-Elston (HE) Regression
  1304. HE regression is a method-of-moments estimator for variance components.
  1305. It is faster but less precise than REML. Useful as a sanity check or
  1306. when REML fails to converge.
  1307. BASIC COMMAND:
  1308. --grm <prefix> --pheno <file> --HEreg --out <prefix>
  1309. OUTPUT FILES:
  1310. {prefix}.hsq - HE regression estimates
  1311. OPTIONS:
  1312. --qcovar <file> Quantitative covariate file
  1313. --covar <file> Categorical covariate file
  1314. --mpheno <num> Phenotype column number
  1315. --grm-cutoff <val> GRM cutoff
  1316. --thread-num <num> Number of CPU threads
  1317. EXAMPLE:
  1318. gcta_hereg(grm="test_grm", pheno="test.phen", out="test_he")
  1319. """
  1320. def _help_pca():
  1321. return """GCTA Principal Component Analysis (PCA)
  1322. PCA from the GRM captures population structure. Output eigenvalues
  1323. and eigenvectors are saved.
  1324. BASIC COMMAND:
  1325. --grm <prefix> --pca <num_pcs> --out <prefix>
  1326. OUTPUT FILES:
  1327. {prefix}.eigenval - Eigenvalues (one per line)
  1328. {prefix}.eigenvec - Eigenvectors (FID, IID, PC1, PC2, ...)
  1329. OPTIONS:
  1330. --pca <num> Number of PCs (default 20)
  1331. --thread-num <num> Number of CPU threads
  1332. EXAMPLE:
  1333. gcta_pca(grm="test_grm", out="test_pca", pc_num=10)
  1334. """
  1335. def _help_mlma():
  1336. return """GCTA Mixed Linear Model Association (MLMA)
  1337. MLMA performs genome-wide association analysis using a linear mixed
  1338. model that accounts for population structure via the GRM.
  1339. METHODS:
  1340. --mlma Standard MLMA (uses full GRM)
  1341. --mlma-loco MLMA with Leave-One-Chromosome-Out (faster, recommended)
  1342. BASIC COMMAND:
  1343. --bfile <prefix> --grm <prefix> --pheno <file> --mlma-loco --out <prefix>
  1344. REQUIRED INPUT:
  1345. --bfile <prefix> PLINK binary file prefix (genotype data)
  1346. --grm <prefix> GRM file prefix
  1347. --pheno <file> Phenotype file
  1348. --out <prefix> Output file prefix
  1349. OUTPUT FILES:
  1350. {prefix}.mlma - Association results (Chr, SNP, BP, A1, F, BETA, SE, P)
  1351. COVARIATES:
  1352. --qcovar <file> Quantitative covariate file
  1353. --covar <file> Categorical covariate file
  1354. OPTIONS:
  1355. --mpheno <num> Phenotype column number
  1356. --reml-maxit <num> Maximum REML iterations
  1357. --maf <val> Minor allele frequency filter
  1358. --autosome-num <num> Number of autosomes
  1359. --thread-num <num> Number of CPU threads
  1360. EXAMPLES:
  1361. # MLMA-LOCO (recommended)
  1362. gcta_mlma(bfile="test", grm="test_grm", pheno="test.phen",
  1363. out="test_mlma", loco=True)
  1364. # Standard MLMA
  1365. gcta_mlma(bfile="test", grm="test_grm", pheno="test.phen",
  1366. out="test_mlma", loco=False)
  1367. """
  1368. def _help_cojo():
  1369. return """GCTA Conditional and Joint (COJO) Analysis
  1370. COJO performs stepwise selection, conditional analysis, or joint analysis
  1371. of GWAS summary statistics, using an LD reference panel from PLINK bed
  1372. data.
  1373. BASIC COMMAND:
  1374. --bfile <prefix> --cojo-file <file> --cojo-slct --out <prefix>
  1375. REQUIRED INPUT:
  1376. --bfile <prefix> PLINK binary file prefix (LD reference panel)
  1377. --cojo-file <file> GWAS summary data file (.ma format)
  1378. --out <prefix> Output file prefix
  1379. GWAS SUMMARY FILE FORMAT (.ma):
  1380. Columns: SNP A1 A2 freq b se p n
  1381. (Header line required)
  1382. METHODS:
  1383. --cojo-slct Stepwise selection (backward + forward)
  1384. --cojo-forward Forward-only selection
  1385. --cojo-backward Backward-only selection
  1386. --cojo-cond <file> Conditional analysis (condition on given SNPs)
  1387. --cojo-joint Joint analysis (all SNPs in one model)
  1388. --cojo-sblup <factor> SBLUP (summary-data BLUP)
  1389. OPTIONS:
  1390. --cojo-p <val> P-value threshold (default 5e-8)
  1391. --cojo-wind <kb> Window size in Kb (default 10000)
  1392. --cojo-collinear <val> Collinearity threshold (default 0.9)
  1393. --cojo-gc <val> Genomic control inflation factor
  1394. --cojo-top-SNPs <num> Number of top SNPs to select
  1395. --maf <val> Minor allele frequency filter
  1396. --thread-num <num> Number of CPU threads
  1397. OUTPUT FILES:
  1398. {prefix}.jma.cojo - Joint analysis results
  1399. {prefix}.cma.cojo - Conditional analysis results
  1400. {prefix}.log - Analysis log
  1401. EXAMPLES:
  1402. # Stepwise selection
  1403. gcta_cojo(bfile="test", cojo_file="gwas.ma", out="cojo_res",
  1404. method="slct")
  1405. # Conditional analysis
  1406. gcta_cojo(bfile="test", cojo_file="gwas.ma", out="cojo_res",
  1407. method="cond", cojo_cond_snplist="cond_snps.txt")
  1408. """
  1409. def _help_gsmr():
  1410. return """GCTA GSMR (Generalized Summary-data Mendelian Randomization)
  1411. GSMR estimates the causal effect of an exposure on an outcome using
  1412. GWAS summary data and an LD reference panel.
  1413. BASIC COMMAND:
  1414. --bfile <prefix> --gsmr-file <file> --gsmr-direction <0|1|2> --out <prefix>
  1415. REQUIRED INPUT:
  1416. --bfile <prefix> PLINK binary file prefix (LD reference)
  1417. --gsmr-file <file> File listing exposure and outcome GWAS files
  1418. --gsmr-direction <num> 0 = forward, 1 = reverse, 2 = bi-directional
  1419. --out <prefix> Output file prefix
  1420. GSMR FILE FORMAT:
  1421. Exposure_GWAS_filename Outcome_GWAS_filename n_exp n_out
  1422. OPTIONS:
  1423. --gsmr2-beta Use GSMR2-beta version (multi-SNP HEIDI)
  1424. --gsmr-snp-min <num> Minimum number of SNP instruments
  1425. --gwas-thresh <val> GWAS p-value threshold
  1426. --clump-kb <val> Clumping window size
  1427. --clump-r2 <val> Clumping r2 threshold
  1428. --heidi-thresh <val> HEIDI-outlier p-value threshold
  1429. --diff-freq <val> Frequency difference threshold
  1430. --thread-num <num> Number of CPU threads
  1431. OUTPUT FILES:
  1432. {prefix}.gsmr - GSMR results
  1433. {prefix}.log - Analysis log
  1434. EXAMPLE:
  1435. gcta_gsmr(bfile="test", gsmr_file="gsmr_data.txt",
  1436. out="gsmr_res", gsmr_direction=0)
  1437. """
  1438. def _help_mtcojo():
  1439. return """GCTA mtCOJO (Multi-trait COJO) Analysis
  1440. mtCOJO performs conditional analysis across multiple traits using GWAS
  1441. summary data, adjusting for the genetic correlation between traits.
  1442. BASIC COMMAND:
  1443. --bfile <prefix> --mtcojo-file <file> --mtcojo-bxy <file> --out <prefix>
  1444. REQUIRED INPUT:
  1445. --bfile <prefix> PLINK binary file prefix (LD reference)
  1446. --mtcojo-file <file> File listing trait GWAS summary files
  1447. --mtcojo-bxy <file> File with causal effect estimates between traits
  1448. --out <prefix> Output file prefix
  1449. OPTIONS:
  1450. --gwas-thresh <val> GWAS p-value threshold
  1451. --clump-kb <val> Clumping window size
  1452. --clump-r2 <val> Clumping r2 threshold
  1453. --diff-freq <val> Frequency difference threshold
  1454. --heidi-thresh <val> HEIDI-outlier threshold
  1455. --thread-num <num> Number of CPU threads
  1456. EXAMPLE:
  1457. gcta_mtcojo(bfile="test", mtcojo_file="traits.txt",
  1458. mtcojo_bxy="bxy.txt", out="mtcojo_res")
  1459. """
  1460. def _help_fastgwa():
  1461. return """GCTA fastGWA Analysis
  1462. fastGWA is an efficient mixed-model association method that uses sparse
  1463. GRM techniques for improved speed on large datasets.
  1464. METHODS:
  1465. --fastGWA fastGWA (requires --grm sparse GRM)
  1466. --fastGWA-mlm fastGWA-MLM (linear mixed model, recommended)
  1467. --fastGWA-mlm-exact fastGWA-MLM exact mode
  1468. --fastGWA-lr fastGWA linear regression (no GRM)
  1469. BASIC COMMAND:
  1470. --bfile <prefix> --pheno <file> --fastGWA-mlm --out <prefix>
  1471. REQUIRED INPUT:
  1472. --bfile <prefix> PLINK binary file prefix
  1473. --pheno <file> Phenotype file
  1474. --out <prefix> Output file prefix
  1475. COVARIATES:
  1476. --qcovar <file> Quantitative covariate file
  1477. --covar <file> Categorical covariate file
  1478. OPTIONS:
  1479. --grm <prefix> GRM file prefix (for fastGWA with GRM)
  1480. --maf <val> Minor allele frequency filter
  1481. --autosome-num <num> Number of autosomes
  1482. --thread-num <num> Number of CPU threads
  1483. OUTPUT FILES:
  1484. {prefix}.fastGWA - Association results
  1485. {prefix}.log - Analysis log
  1486. EXAMPLES:
  1487. # fastGWA-MLM (recommended)
  1488. gcta_fastgwa(bfile="test", pheno="test.phen", out="fastgwa_res",
  1489. method="fastGWA-mlm")
  1490. # fastGWA-LR (no GRM, fastest)
  1491. gcta_fastgwa(bfile="test", pheno="test.phen", out="fastgwa_res",
  1492. method="fastGWA-lr")
  1493. """
  1494. def _help_fastbat():
  1495. return """GCTA fastBAT Gene-based Association Test
  1496. fastBAT performs gene-based association tests by combining SNP-level
  1497. p-values within genes, accounting for LD structure.
  1498. BASIC COMMAND:
  1499. --bfile <prefix> --fastBAT <gwas_summary> --out <prefix>
  1500. REQUIRED INPUT:
  1501. --bfile <prefix> PLINK binary file prefix (LD reference)
  1502. --fastBAT <file> GWAS summary data file (.ma format)
  1503. --fastBAT-gene-list <file> Gene annotation file
  1504. --fastBAT-set-list <file> SNP set file (predefined sets)
  1505. --out <prefix> Output file prefix
  1506. GWAS SUMMARY FILE FORMAT (.ma):
  1507. Columns: SNP A1 A2 freq b se p n
  1508. OPTIONS:
  1509. --fastBAT-wind <kb> Window size in Kb (default 50)
  1510. --fastBAT-ld-cutoff <val> LD r2 cutoff (default 0.9)
  1511. --fastBAT-write-snpset Write SNP set file
  1512. --maf <val> Minor allele frequency filter
  1513. --thread-num <num> Number of CPU threads
  1514. OUTPUT FILES:
  1515. {prefix}.fastBAT - Gene-based test results
  1516. {prefix}.log - Analysis log
  1517. EXAMPLE:
  1518. gcta_fastbat(bfile="test", fastbat_file="gwas.ma",
  1519. out="fastbat_res", fastbat_gene_list="genes.txt")
  1520. """
  1521. def _help_simulation():
  1522. return """GCTA Phenotype Simulation
  1523. GCTA can simulate phenotypes based on real genotype data, useful for
  1524. power analysis and method evaluation.
  1525. QUANTITATIVE TRAIT SIMULATION:
  1526. --bfile <prefix> --simu-qt --simu-hsq <h2> --out <prefix>
  1527. CASE-CONTROL SIMULATION:
  1528. --bfile <prefix> --simu-cc <cases> <controls> --simu-hsq <h2>
  1529. --simu-k <prevalence> --out <prefix>
  1530. OPTIONS:
  1531. --simu-hsq <val> Simulated heritability (default 0.1)
  1532. --simu-k <val> Disease prevalence (default 0.1)
  1533. --simu-rep <num> Number of repetitions (default 1)
  1534. --simu-causal-loci <file> File of causal loci
  1535. --simu-seed <val> Random seed
  1536. --simu-eff-mod <0|1> Effect model: 0 = additive, 1 = non-additive
  1537. --thread-num <num> Number of CPU threads
  1538. EXAMPLES:
  1539. # Simulate QT with h2=0.5
  1540. gcta_simu_qt(bfile="test", out="simu_qt", simu_hsq=0.5)
  1541. # Simulate CC with 1000 cases, 1000 controls
  1542. gcta_simu_cc(bfile="test", simu_case_num=1000, simu_control_num=1000,
  1543. out="simu_cc", simu_hsq=0.3, simu_k=0.05)
  1544. """
  1545. def _help_ld():
  1546. return """GCTA LD Analysis
  1547. GCTA provides several LD analysis tools:
  1548. LD PRUNING:
  1549. --bfile <prefix> --ld-pruning <r2> --ld-wind <kb> --out <prefix>
  1550. Removes SNPs in high LD, retaining approximately independent SNPs.
  1551. LD SCORE CALCULATION:
  1552. --bfile <prefix> --ld-score --ld-wind <kb> --out <prefix>
  1553. Computes LD scores (sum of LD r2 with neighboring SNPs).
  1554. LD SCORE REGRESSION:
  1555. --bfile <prefix> --ld-score-region --ld-wind <kb> --out <prefix>
  1556. Performs LD score regression to estimate heritability and confounding.
  1557. OPTIONS:
  1558. --ld-pruning <r2> LD r2 threshold for pruning
  1559. --ld-wind <kb> LD window size in Kb
  1560. --ld-score Calculate LD scores
  1561. --ld-score-region LD score regression
  1562. --ld-score-multi <f> Multi-set LD score
  1563. --ld-rsq-cutoff <val> LD r2 cutoff
  1564. --ld-max-rsq Maximum LD r2
  1565. --ld-step <num> LD step size
  1566. --thread-num <num> Number of CPU threads
  1567. EXAMPLES:
  1568. # LD pruning with r2=0.1
  1569. gcta_ld_pruning(bfile="test", ld_pruning_rsq=0.1, out="pruned")
  1570. # LD score calculation
  1571. gcta_ld_score(bfile="test", out="ldscores")
  1572. """
  1573. def _help_fst():
  1574. return """GCTA Fst (Fixation Index) Analysis
  1575. Fst measures population differentiation. GCTA computes pairwise Fst
  1576. between subpopulations.
  1577. BASIC COMMAND:
  1578. --bfile <prefix> --fst --sub-popu <file> --out <prefix>
  1579. REQUIRED INPUT:
  1580. --bfile <prefix> PLINK binary file prefix
  1581. --sub-popu <file> Subpopulation file (FID, IID, pop ID)
  1582. --out <prefix> Output file prefix
  1583. OPTIONS:
  1584. --maf <val> Minor allele frequency filter
  1585. --thread-num <num> Number of CPU threads
  1586. OUTPUT FILES:
  1587. {prefix}.Fst - Fst results
  1588. {prefix}.log - Analysis log
  1589. EXAMPLE:
  1590. gcta_fst(bfile="test", sub_popu="pops.txt", out="fst_res")
  1591. """
  1592. def _help_expression():
  1593. return """GCTA Expression Data Analysis
  1594. GCTA supports analysis of gene expression data:
  1595. EXPRESSION FILE INPUT:
  1596. --efile <file> Expression data file
  1597. EXPRESSION RELATIONSHIP MATRIX (ERM):
  1598. --make-erm Make ERM (binary output)
  1599. --make-erm-gz Make ERM (gzipped text output)
  1600. --make-erm-alg <1|2|3> Algorithm for ERM calculation
  1601. ECOJO ANALYSIS:
  1602. --ecojo <file> ecojo analysis with MA file
  1603. --ecojo-slct ecojo stepwise selection
  1604. --ecojo-p <val> ecojo p-value threshold
  1605. --ecojo-collinear <v> ecojo collinearity threshold
  1606. --ecojo-blup <lambda> ecojo BLUP with lambda
  1607. E-COR (Expression Correlation):
  1608. --e-cor <file> Expression correlation file
  1609. EXAMPLE:
  1610. gcta_run("--efile expr.txt --make-erm --out expr_erm")
  1611. """
  1612. def _help_acat():
  1613. return """GCTA ACAT (Aggregated Cauchy Association Test)
  1614. ACAT combines p-values from multiple SNPs within a gene using a Cauchy
  1615. combination method, providing a gene-level association test.
  1616. BASIC COMMAND:
  1617. --acat --gene-list <file> --snp-list <file> --out <file>
  1618. REQUIRED INPUT:
  1619. --gene-list <file> Gene list file (gene, chr, start, end)
  1620. --snp-list <file> SNP list file with p-values
  1621. --out <file> Output file (default acat_res.csv)
  1622. OPTIONS:
  1623. --max-maf <val> Maximum MAF for included SNPs (default 0.01)
  1624. --min-mac <num> Minimum minor allele count (default 20)
  1625. --wind <num> Extension length for gene boundaries
  1626. OUTPUT FILE:
  1627. {out} - ACAT gene-based test results
  1628. EXAMPLE:
  1629. gcta_acat(gene_list="genes.txt", snp_list="snps.txt",
  1630. out="acat_results.csv")
  1631. """
  1632. def _help_options():
  1633. return """GCTA Complete Command-Line Options Reference
  1634. DATA INPUT:
  1635. --bfile <prefix> PLINK binary PED format
  1636. --mbfile <file> Multiple bfile list
  1637. --bfile2 <prefix> Second bfile
  1638. --dosage-mach <d> <i> Mach dosage
  1639. --dosage-mach-gz <d> <i> Mach dosage (gzipped)
  1640. --dosage-beagle <d> <i> Beagle dosage
  1641. DATA MANAGEMENT:
  1642. --make-bed Output PLINK bed format
  1643. --freq / --freqx Calculate allele frequencies
  1644. --recode / --recode-nomiss / --recode-std Recode genotypes
  1645. --keep <file> Keep individuals
  1646. --remove <file> Remove individuals
  1647. --extract <file> Include SNPs
  1648. --exclude <file> Exclude SNPs
  1649. --chr <num> Chromosome filter
  1650. --autosome Autosome filter
  1651. --autosome-num <num> Number of autosomes
  1652. --maf <val> MAF filter
  1653. --max-maf <val> Max MAF filter
  1654. --update-sex <file> Update sex
  1655. --update-freq <file> Update allele frequencies
  1656. --update-ref-allele <f> Update reference allele
  1657. --save-ram Memory-saving mode
  1658. GRM:
  1659. --make-grm Make GRM (binary output)
  1660. --make-grm-gz Make GRM (text output)
  1661. --make-grm-alg <0|1> GRM algorithm
  1662. --make-grm-d Dominance GRM
  1663. --make-grm-xchr X-chromosome GRM
  1664. --make-grm-inbred Inbreeding GRM
  1665. --grm <prefix> Read GRM
  1666. --grm-gz <prefix> Read GRM (gzipped)
  1667. --mgrm <file> Multiple GRMs
  1668. --mgrm-gz <file> Multiple GRMs (gzipped)
  1669. --grm-cutoff <val> GRM cutoff
  1670. --grm-adj <val> GRM adjustment
  1671. --dc <0|1> Dosage compensation
  1672. PCA:
  1673. --pca <num> PCA with num PCs
  1674. --pc-loading <file> PC loading
  1675. --project-loading <f> <n> Project loading
  1676. REML:
  1677. --reml REML analysis
  1678. --reml-bivar <p1> <p2> Bivariate REML
  1679. --reml-maxit <num> Max iterations
  1680. --reml-priors <vals> Prior variance explained
  1681. --reml-priors-var <vals> Prior variance components
  1682. --reml-no-constrain No constrain
  1683. --reml-no-lrt No LRT
  1684. --reml-pred-rand Predict random effects
  1685. --reml-est-fix Estimate fixed effects
  1686. --prevalence <val> Disease prevalence
  1687. HE REGRESSION:
  1688. --HEreg HE regression
  1689. --HEreg-bivar <p1> <p2> Bivariate HE regression
  1690. MLMA:
  1691. --mlma MLMA association
  1692. --mlma-loco MLMA-LOCO
  1693. --mlma-no-adj-covar No adj covar
  1694. COJO:
  1695. --cojo-file <file> GWAS summary data
  1696. --cojo-slct Stepwise selection
  1697. --cojo-forward Forward selection
  1698. --cojo-backward Backward selection
  1699. --cojo-joint Joint analysis
  1700. --cojo-cond <file> Conditional analysis
  1701. --cojo-sblup <factor> SBLUP
  1702. --cojo-p <val> P-value threshold
  1703. --cojo-wind <kb> Window size
  1704. --cojo-collinear <val> Collinearity threshold
  1705. --cojo-gc <val> Genomic control
  1706. --cojo-top-SNPs <num> Top SNPs
  1707. GSMR:
  1708. --gsmr-file <file> GSMR data file
  1709. --gsmr-direction <0|1|2> Direction
  1710. --gsmr2-beta GSMR2-beta
  1711. --gsmr-snp-min <num> Min SNP instruments
  1712. --gwas-thresh <val> GWAS threshold
  1713. --heidi-thresh <val> HEIDI threshold
  1714. mtCOJO:
  1715. --mtcojo-file <file> mtCOJO data file
  1716. --mtcojo-bxy <file> Bxy file
  1717. fastGWA:
  1718. --fastGWA fastGWA
  1719. --fastGWA-mlm fastGWA-MLM
  1720. --fastGWA-mlm-exact fastGWA-MLM exact
  1721. --fastGWA-lr fastGWA-LR
  1722. fastBAT:
  1723. --fastBAT <file> fastBAT GWAS summary
  1724. --fastBAT-gene-list <f> Gene list
  1725. --fastBAT-set-list <f> SNP set list
  1726. --fastBAT-wind <kb> Window size
  1727. --fastBAT-ld-cutoff <v> LD cutoff
  1728. SIMULATION:
  1729. --simu-qt Simulate QT
  1730. --simu-cc <cases> <ctrl> Simulate CC
  1731. --simu-hsq <val> Heritability
  1732. --simu-k <val> Prevalence
  1733. --simu-rep <num> Repetitions
  1734. --simu-causal-loci <file> Causal loci
  1735. --simu-seed <val> Seed
  1736. LD:
  1737. --ld <file> LD analysis
  1738. --ld-pruning <r2> LD pruning
  1739. --ld-score LD score
  1740. --ld-score-region LD score regression
  1741. --ld-wind <kb> LD window
  1742. --ld-rsq-cutoff <val> LD r2 cutoff
  1743. FST:
  1744. --fst Fst analysis
  1745. --sub-popu <file> Subpopulation file
  1746. EXPRESSION:
  1747. --efile <file> Expression file
  1748. --e-cor <file> Expression correlation
  1749. --make-erm Make ERM
  1750. --ecojo <file> ecojo analysis
  1751. ACAT:
  1752. --acat ACAT analysis
  1753. --gene-list <file> Gene list
  1754. --snp-list <file> SNP list
  1755. --max-maf <val> Max MAF
  1756. --min-mac <num> Min MAC
  1757. THREADING:
  1758. --thread-num <num> Number of threads
  1759. --threads <num> Alias for --thread-num
  1760. OUTPUT:
  1761. --out <prefix> Output prefix
  1762. """
  1763. # ============================================================================
  1764. # Main entry point
  1765. # ============================================================================
  1766. if __name__ == "__main__":
  1767. print(f"GCTA MCP Server starting...", file=sys.stderr)
  1768. print(f" Binary path: {GCTA_BINARY_PATH}", file=sys.stderr)
  1769. print(f" Work directory: {GCTA_WORK_DIR}", file=sys.stderr)
  1770. print(f" Timeout: {GCTA_TIMEOUT}s", file=sys.stderr)
  1771. mcp.run()

server.py at commit 2ff095c, under GPL-3.0 · at the source

Overview

Authors: Miguel Novoa-Bravo1, Jennifer RS Meadows2,3, Filipe Serra-Bragança4, Britt van de Vall5, Klas Kullander6, Marie Rhodin5, Gabriella Lindgren5
  1. Genética Animal de Colombia SAS, Bogotá, Colombia
  2. Department of Medical Biochemistry and Microbiology, Uppsala University, 75123 Uppsala, Sweden
  3. SciLifeLab, Uppsala University, 75123 Uppsala, Sweden
  4. Department of Clinical Sciences, Faculty of Veterinary Medicine, Utrecht University, Utrecht 3584CM, the Netherlands
  5. Department of Animal Biosciences, Swedish University of Agricultural Sciences, P.O. Box 7023, 75007 Uppsala, Sweden
  6. Department of Immunology, Genetics and Pathology, Uppsala University, Uppsala, Sweden
Journal: iScience, volume 29, issue 7, article 116320
Dates: received 17 December 2025; accepted 25 May 2026; published online 11 June 2026
Type: Research article · Language: English
License: CC BY
Identifiers: DOI 10.1016/j.isci.2026.116320 · PMID 42325571 · PMCID PMC13276308 · OpenAlex W7164341170
Open access: gold, a free copy (OpenAlex)
Status: code verified
Categories: genetics / omics (modality), other (organism), developmental (subfield)
Methods: Statistics, Smoothing, state filtering, decompositions, Machine learning, fMRI & imaging, Physiology & signal measures
Keywords: genetics, developmental neuroscience, machine learning
Topic: Genetic Mapping and Diversity in Plants and Animals (Genetics, Biochemistry, Genetics and Molecular Biology), according to OpenAlex
Funding: Hjärnfonden (FO2022-0018); Vetenskapsrådet (2022-01245); Svenska Forskningsrådet Formas; Formas
Citations: not cited yet (Europe PMC); 86 references in the paper

Abstract

Coordinated mammalian locomotion relies on spinal circuits where DMRT3 regulates strides and alternative gaits. However, DMRT3 does not explain differences between the Colombian paso horse breed’s specialized gaits, Colombian trocha and Colombian trot. We used inertial sensors and machine learning to develop accurate phenotyping (n = 225 horses), before performing genome-wide association analysis (n = 85 horses, 670K array). We identified a 2.43 Mb quantitative trait locus (QTL) on ECA16, where haplotypes featuring lead variants (rs1147402472, p = 1.95 × 10−8; rs1136628503, p = 8.52 × 10−8) explained 48.6% of gait variance (p < 0.001). The QTL contained 11 genes linked to neurodevelopment and muscle regulation, including LHFPL4, SRGAP3, and ATP2B2. Interaction analyses suggested a functional link between the latter genes. rs1147402472-C was common across diverse gaited horse breeds, but the Colombian trot-specific haplotype (rs1147402472-C/rs1136628503-T) was absent elsewhere. These findings demonstrate that fine-scale genetic differentiation at ECA16 underlies neural adaptations distinguishing complex locomotor traits and highlight the power of AI-assisted phenotyping in genomics.

Reproduced under the paper's license (CC BY), from the paper cited above.

Repositories

Its files are read in the Code ↔ Paper reader above, with 4 matches between paragraphs and lines of code.

JianYang-Lab/GCTA

License: GPL-3.0
State: the link answers, verified on 27 September 2026
Evidence: files inventoried
Commit: 2ff095cad2ea5ca213c1b008401382aa7b05715e, 21 July 2026
Languages: C++ (43), C/C++ (26), Shell (3), Python (1), C (1)
Size: 106 files, 74 scripts
Software Heritage: not archived
Found in: the resources table
Holds: README, license file, environment (.opencode/gcta-mcp/pyproject.toml, .opencode/gcta-mcp/requirements.txt), documentation
Not found: CITATION.cff, tests, continuous integration
Availability: 1 check, the latest on 27 September 2026: the link answers
  • 27 September 2026: the link answers
76 files

saigegit/SAIGE

License: GPL-3.0
State: the link answers, verified on 27 September 2026
Evidence: files inventoried
Commit: 365deeff9149fc2b5a66da8fa3799637bcb30af3, 25 June 2026
Languages: C++ (26), R (24), Shell (4), C/C++ (2)
Size: 481 files, 56 scripts
Software Heritage: not archived
Found in: the resources table
Holds: README, license file, environment (DESCRIPTION, pixi.toml, docker/Dockerfile, src/SAIGE/DESCRIPTION), documentation
Not found: CITATION.cff, tests, continuous integration
Tools: data.table (16 files), tidyverse (1 file)
Availability: 1 check, the latest on 27 September 2026: the link answers
  • 27 September 2026: the link answers
58 files

The paper's code and data availability statement is in the Data section.

Tracing map

Proposed by the machine: these links were found in the paper and verified at the source, without human review. The map will receive a Zenodo DOI once one of the paper's authors has validated it with their ORCID.

What the map holds:

  • 2 repositories of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
  • 130 scripts, each with its path and the digest of its content;
  • 4 matches between paragraphs of the paper and lines of the code (method lexical-v1);
  • neither the text of the paper nor the code itself.

Its JSON (tracing-map.json) is deposited on Zenodo with its DOI once the map is validated.

Data

Datasets cited

Data and code availability

Genotyping array data and metadata have been deposited at European Variation Archive (EVA): PRJEB105194, and are publicly available as of the date of publication.

Phenotype data have been deposited in Mendeley Dataset: https://doi.org/10.17632/52rzdhx297.1

This paper does not report original code.

Any additional information required to reanalyze the data reported in this paper is available from the lead contact upon request.

Reproduced under the paper's license (CC BY), from the paper cited above.

Versions

The history of this record: each version stored by the harvester or made by a correction of its authors or of the maintainers of its code, and what changed in its facts. The texts of the paper (its abstract, its availability statements) are not part of it; versions that changed only those are not listed.

Version 2, 28 September 2026

  • Authors: added Miguel Novoa-Bravo (0000-0002-9950-2590); removed Miguel Novoa-Bravo

Version 1, 27 September 2026: the first record

Recorded: type, language, journal, volume, issue, pages, dates, 7 authors, 3 keywords, 4 funders, 86 references.

Cite

This paper

Novoa-Bravo, M., Meadows, J. R., Serra-Bragança, F., van de Vall, B., Kullander, K., Rhodin, M., & Lindgren, G. (2026). Machine learning-based gait classification and genome-wide association identify a QTL for gait type in Colombian paso horses. iScience, 29(7), 116320. https://doi.org/10.1016/j.isci.2026.116320

BibTeX

@article{novoabravo2026machine,
author = {Novoa-Bravo, Miguel and Meadows, Jennifer RS and Serra-Bragança, Filipe and van de Vall, Britt and Kullander, Klas and Rhodin, Marie and Lindgren, Gabriella},
title = {{Machine learning-based gait classification and genome-wide association identify a QTL for gait type in Colombian paso horses}},
journal = {iScience},
year = {2026},
month = jun,
volume = {29},
number = {7},
pages = {116320},
publisher = {Elsevier},
issn = {2589-0042},
doi = {10.1016/j.isci.2026.116320},
url = {https://doi.org/10.1016/j.isci.2026.116320},
pmid = {42325571},
pmcid = {PMC13276308}
}

RIS

TY - JOUR
AU - Novoa-Bravo, Miguel
AU - Meadows, Jennifer RS
AU - Serra-Bragança, Filipe
AU - van de Vall, Britt
AU - Kullander, Klas
AU - Rhodin, Marie
AU - Lindgren, Gabriella
TI - Machine learning-based gait classification and genome-wide association identify a QTL for gait type in Colombian paso horses
T2 - iScience
J2 - iScience
PY - 2026
DA - 2026/06/11
VL - 29
IS - 7
SP - 116320
SN - 2589-0042
PB - Elsevier
DO - 10.1016/j.isci.2026.116320
UR - https://doi.org/10.1016/j.isci.2026.116320
LA - en
ER -

CSL-JSON

{
"id": "10.1016/j.isci.2026.116320",
"type": "article-journal",
"title": "Machine learning-based gait classification and genome-wide association identify a QTL for gait type in Colombian paso horses",
"container-title": "iScience",
"author": [
{
"family": "Novoa-Bravo",
"given": "Miguel"
},
{
"family": "Meadows",
"given": "Jennifer RS"
},
{
"family": "Serra-Bragança",
"given": "Filipe"
},
{
"family": "van de Vall",
"given": "Britt"
},
{
"family": "Kullander",
"given": "Klas"
},
{
"family": "Rhodin",
"given": "Marie"
},
{
"family": "Lindgren",
"given": "Gabriella"
}
],
"container-title-short": "iScience",
"volume": "29",
"issue": "7",
"page": "116320",
"DOI": "10.1016/j.isci.2026.116320",
"PMID": "42325571",
"PMCID": "PMC13276308",
"ISSN": "2589-0042",
"publisher": "Elsevier",
"URL": "https://doi.org/10.1016/j.isci.2026.116320",
"language": "en",
"issued": {
"date-parts": [
[
2026,
6,
11
]
]
}
}

The tracing map gets a citation of its own once an author has validated it and it has a DOI.

Similar papers

The papers with a page that share the most with this one: the tools found in their code, their categories, datasets, cited references and authors, the rarest counting most.

[1] doi:10.1038/s41467-026-72164-7 [code]
Multivariate genetic analysis reveals three distinct pathological dimensions in musculoskeletal disorders.
Journal: Nature communications
In common: data.table, tidyverse, genetics / omics, 2 references
[2] doi:10.1038/s41562-026-02486-5 [code]
Genome-wide association studies of infant and toddler temperament in European and multi-ancestry populations.
Journal: Nature human behaviour
In common: data.table, tidyverse, developmental, genetics / omics, 1 reference
[3] doi:10.1093/molbev/msag149 [code]
Multiple modes of selection underlie repeated and human-mediated adaptation in a formerly migratory fish.
Journal: Molecular biology and evolution
In common: data.table, tidyverse, other, 1 reference
[4] doi:10.1038/s42003-026-10131-0 [code]
Shared genetic architecture between the topology of brain white matter structural connectome and fluid intelligence.
Journal: Communications biology
In common: data.table, genetics / omics, 2 references
[5] doi:10.1038/s41514-026-00397-3 [code]
Nasal administration of Protollin enhances monocyte phagocytosis and decreases CD8&lt;sup&gt;+&lt;/sup&gt; T cell cytotoxicity in subjects with early Alzheimer's disease: a Phase 1 clinical trial.
Journal: npj aging
In common: data.table, tidyverse, 1 reference
[6] doi:10.3390/biomedicines14081677 [code]
Exploratory Genome and Transcriptome-Wide Association Analyses of Addiction-Related Phenotypes in a Twin Cohort.
Journal: Biomedicines
In common: data.table, tidyverse, genetics / omics, 1 reference
[7] doi:10.1038/s41588-026-02646-3 [code]
Co-expression-based models improve eQTL predictions for transcriptome-wide association studies and highlight new schizophrenia-associated genes.
Journal: Nature genetics
In common: data.table, tidyverse, genetics / omics, 1 reference
[8] doi:10.1038/s41467-026-73902-7 [code]
GWAS on short tandem repeats identifies genetic mechanisms in Alzheimer's disease.
Journal: Nature communications
In common: data.table, tidyverse, genetics / omics, 1 reference
[9] doi:10.1038/s41467-026-73428-y [code]
Regional heterogeneity in phenotypic and genetic associations between bone and brain in humans.
Journal: Nature communications
In common: data.table, tidyverse, genetics / omics, 1 reference
[10] doi:10.1186/s12967-026-08266-z [code]
Single-cell multi-omic integration analysis prioritizes druggable genes and reveals cell-type-specific causal effects in glioblastomagenesis.
Journal: Journal of translational medicine
In common: data.table, tidyverse, genetics / omics, 1 reference

Contribute

The authors of this paper can claim it, correct its record and validate its tracing map, and the maintainers of its code (its owner, or a public member of its organization) correct what it says of their repository; anyone signed in can ask for its removal. Every request goes to OSCR's own machine, which answers it; your account page follows them.

Sign in with ORCID to claim this paper as one of its authors, correct its record or validate its tracing map: when the paper's metadata lists your ORCID iD, you are recognized at once. Maintainers of its code: sign in with GitHub, then claim the repository on your account page.

Request its removal

To ask OSCR to remove this record, the copies of its authors' scripts or its tracing map, use the removal request page: signed in, you say who you are, what to remove and why, then review and confirm the request. Published rules decide every request (how).

Discussion, reproductions, activity

Discussion: questions and error reports about this paper and its code, from signed-in readers and its authors. It opens with sign-in.

Reproductions: reports from readers who ran the authors' code: what they reproduced, with which environment, commit and data. It opens with sign-in.

Activity: what happens around this paper: new versions of its record, its map's validation, discussions and reproductions. It opens with sign-in.