#!/usr/bin/env bash # Reference: CAFE5 5.1.0+, treePL 1.0+, Python 3.10+, pandas 2.2+, statsmodels 0.14+, R 4.4+ | Verify API if version differs # CAFE5 birth-death analysis with annotation-error mode + FDR correction. set -euo pipefail ORTHOFINDER_OUT=${1:?usage: $0 ORTHOFINDER_OUT SPECIES_TREE_NWK OUTPUT_DIR} SPECIES_TREE_NWK=${2:?missing species tree (Newick with substitution branches)} OUTPUT_DIR=${3:?missing output dir} THREADS=${THREADS:-16} mkdir -p "$OUTPUT_DIR"/{cafe_input,tree,results} echo "[1/5] Build CAFE5 input from OrthoFinder HOGs" # v3 layout: Phylogenetic_Hierarchical_Orthogroups/N0.tsv HOG_FILE=$(find "$ORTHOFINDER_OUT" -name 'N0.tsv' | head -1) if [ -z "$HOG_FILE" ]; then echo "ERROR: HOG N0.tsv not found under $ORTHOFINDER_OUT" exit 1 fi python3 - <= 2) multi_copy = count_matrix[count_matrix.max(axis=1) >= 2] print(f'Multi-copy families: {len(multi_copy)} / {len(count_matrix)}') # CAFE5 format: Family ID + per-species counts multi_copy.reset_index(inplace=True) multi_copy.rename(columns={'index': 'family_id'}, inplace=True) multi_copy.insert(0, 'Description', '(null)') multi_copy.to_csv('$OUTPUT_DIR/cafe_input/family_counts.tsv', sep='\t', index=False) print('CAFE5 input: $OUTPUT_DIR/cafe_input/family_counts.tsv') PY echo "[2/5] Time-calibrate species tree (ultrametric required for CAFE5)" # Option 1: ape::chronos (R; default if no calibration) Rscript - <