File size: 4,371 Bytes
7f316fe
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12fea4a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
"""Repo-root path helpers. All scripts should import this instead of hardcoding hosts."""
from __future__ import annotations

import os
import shutil
import sys
from pathlib import Path

REPO_ROOT = Path(__file__).resolve().parent


def add_repo_to_sys_path() -> Path:
    root = str(REPO_ROOT)
    if root not in sys.path:
        sys.path.insert(0, root)
    return REPO_ROOT


def resolve_path(path: str | Path) -> Path:
    p = Path(path).expanduser()
    if p.is_absolute():
        return p
    return (REPO_ROOT / p).resolve()


def peptiverse_root() -> Path:
    env = os.environ.get("PEPTIVERSE_ROOT")
    if env:
        root = Path(env).expanduser().resolve()
    else:
        root = (REPO_ROOT.parent / "PeptiVerse").resolve()
    if not root.is_dir():
        raise FileNotFoundError(
            "PeptiVerse was not found. Clone it first and either place it next "
            f"to this repo ({REPO_ROOT.parent / 'PeptiVerse'}) or set PEPTIVERSE_ROOT.\n"
            "  git clone https://huggingface.co/ChatterjeeLab/PeptiVerse"
        )
    return root


def mafft_path() -> str:
    env = os.environ.get("MAFFT_PATH")
    if env:
        if Path(env).is_file() and os.access(env, os.X_OK):
            return env
        raise FileNotFoundError(f"MAFFT_PATH is set but not an executable: {env}")
    found = shutil.which("mafft")
    if found:
        return found
    raise FileNotFoundError(
        "MAFFT was not found on PATH. Install it and make sure `mafft` is "
        "executable, or set MAFFT_PATH to the binary. GFP FPredX oracles require MAFFT."
    )


def smiles_vocab_files() -> tuple[Path, Path]:
    return (
        REPO_ROOT / "smiles_tokenizer" / "new_vocab.txt",
        REPO_ROOT / "smiles_tokenizer" / "new_splits.txt",
    )


def selfies_vocab_path() -> Path:
    return REPO_ROOT / "smiles_tokenizer" / "selfies_vocab.json"


# --- Cas9 ---------------------------------------------------------------

def protein2pam_root() -> Path:
    """Root of the protein2pam package (provides the custom ESM loader).

    Weights come from the Hub ("Profluent-Bio/protein2pam-cas9_full"); this is
    only the Python package that defines the model class.
    """
    env = os.environ.get("PROTEIN2PAM_ROOT")
    root = Path(env).expanduser().resolve() if env else (REPO_ROOT / "cas9" / "protein2pam")
    if not root.is_dir():
        raise FileNotFoundError(
            "protein2pam was not found. Install it next to the Cas9 code at "
            f"{REPO_ROOT / 'cas9' / 'protein2pam'} or set PROTEIN2PAM_ROOT.\n"
            "  pip install protein2pam==0.2.0"
        )
    return root


def cas_predictor_root() -> Path:
    """Root of the cas_predictor package (model.py + lightning_module.py)."""
    env = os.environ.get("CAS_PREDICTOR_ROOT")
    root = Path(env).expanduser().resolve() if env else (REPO_ROOT / "cas9" / "cas_predictor")
    if not root.is_dir():
        raise FileNotFoundError(
            "cas_predictor was not found. Place it at "
            f"{REPO_ROOT / 'cas9' / 'cas_predictor'} or set CAS_PREDICTOR_ROOT."
        )
    return root


def cas9_classifier_ckpt() -> Path:
    """Cas9-likeness classifier checkpoint (hard constraint + objective)."""
    env = os.environ.get("CAS9_CLASSIFIER_CKPT")
    p = resolve_path(env) if env else (REPO_ROOT / "cas9" / "classifier_ckpt" / "last.ckpt")
    if not p.is_file():
        raise FileNotFoundError(
            f"Cas9 classifier checkpoint not found at {p}. Download it into "
            "cas9/classifier_ckpt/ or set CAS9_CLASSIFIER_CKPT."
        )
    return p


def cas9_classifier_config() -> Path | None:
    """Optional classifier config; None falls back to the ckpt hyper_parameters."""
    env = os.environ.get("CAS9_CLASSIFIER_CONFIG")
    if env:
        return resolve_path(env)
    default = REPO_ROOT / "cas9" / "classifier_ckpt" / "config.yaml"
    return default if default.is_file() else None


def cas9_hmm_db(name: str) -> Path:
    """HMM database under cas9/hmm/ (e.g. 'cas9_domain_detector_RuvCmix.hmm')."""
    env = os.environ.get("CAS9_HMM_DIR")
    root = Path(env).expanduser().resolve() if env else (REPO_ROOT / "cas9" / "hmm")
    p = root / name
    if not p.is_file():
        raise FileNotFoundError(
            f"HMM database {name} not found at {p}. Place it in cas9/hmm/ or set CAS9_HMM_DIR."
        )
    return p