# DC-MetaMG1 **Repository Path**: Tomhappy/dc-meta-mg1 ## Basic Information - **Project Name**: DC-MetaMG1 - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-09-02 - **Last Updated**: 2026-09-02 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Research Report: DC-MetaMG — Facts for README.md --- ## 1. Top-Level Directory Structure ``` DC-MetaMG/ ├── GetFeature/ # Stage 1: Feature Extraction │ ├── main.py # CLI entry point │ ├── trainer.py # Trainer class (train loop + export) │ ├── cbam.py (not yet inspected, used by DC_Prediction model.py via import) │ ├── model/ │ │ ├── model.py # MetaMG (main model), Channel │ │ ├── DrugMG.py # DrugMG, Mol, HGNN wrapper for drug SMILES → embedding │ │ ├── hgnn.py # HetConv / HGNN graph conv layers │ │ └── __pycache__/ │ ├── util/ │ │ └── util.py # set_seed, get_data, get_edge_index │ ├── data/ │ │ ├── MiRNA/ # Raw input data for MiRNA dataset │ │ │ ├── edges.txt │ │ │ ├── DrugSmile.csv │ │ │ ├── GIP_Topo_drug.txt │ │ │ ├── Gaussian_sim_MiRNA.txt │ │ │ ├── Feature_MiRNA_SQ.txt │ │ │ ├── splits.pt (generated by main.py on first run) │ │ │ └── DATA_DMP/ │ │ │ ├── MetaPath_drug_2a.txt │ │ │ ├── MetaPath_miRNA_2a.txt │ │ │ └── MetaPath_drug_2a_F.txt │ │ └── LncRNA/ # Raw input data for LncRNA dataset │ │ ├── edges.txt │ │ ├── DrugSmile.csv │ │ ├── GIP_Topo_drug.txt │ │ ├── Gaussian_sim_LncRNA.txt │ │ ├── Feature_LncRNA_Sq.txt │ │ ├── splits.pt (generated by main.py on first run) │ │ └── DATA_DMP/ │ │ ├── MetaPath_drug.txt │ │ └── MetaPath_lncRNA.txt │ ├── source/ # OUTPUT directory (created by trainer.py) │ │ └── MiRNA/ (and LncRNA/ when run with that dataset) │ │ ├── Drug_GT.txt │ │ ├── NcRNA_GS.txt │ │ ├── Drug_MG.txt │ │ ├── NcRNA_SQ.txt │ │ └── edge_splits.pt │ ├── GetSqFeature/ # Sequence k-mer feature preprocessing scripts │ │ ├── Kmer_MiRNA.py │ │ ├── Kmer_LncRNA.py │ │ ├── MiRNA_Sq.txt │ │ ├── LncRNA_Sq.fasta │ │ ├── LncRNA_ID.txt │ │ ├── MiRNA/ │ │ │ ├── mirna_kmer_matrix.csv │ │ │ ├── reduced_kmer_features.csv │ │ │ └── multi_kmer_matrix.csv │ │ └── LncRNA/ │ │ └── Feature_MiRNA_SQ (note: oddly named, appears under LncRNA folder) │ └── Dynamic Meta-path Selection/ # Separate preprocessing stage (run BEFORE main.py) │ ├── MiRNA/ │ │ ├── main.py │ │ ├── data/ (array_DD.txt, array_MD.txt, correlation_Drug.txt, correlation_MiRNA.txt, MetaPath__miRNA.txt) │ │ ├── GetMatrix_Drug/ (DDI.txt, drug.txt, Disease_drug.txt, Disease.txt, DD_ARR.txt, jaccard_similarity.py, source/, Get_PathMatrix/PRA/, Test/) │ │ └── GetMatrix_MiRNA/ (miRNA.txt, MDI.txt, Disease_miRNA.txt, Disease.txt, MD_ARR.txt, source/, Get_PathMatrix/PRA/, Test/) │ └── LncRNA/ │ ├── main.py │ ├── data/ (array_DD.txt, array_LD.txt) │ ├── GetMatrix_Drug/ (Drug_ID.txt, Disease_ID.txt, DD_ARR.txt, drug_embeddings.csv, jaccard? , source/Topo_drug.txt, Get_PathMatrix/PRA/, Test/) │ └── GetMatrix_LncRNA/ (LncRNA_ID.txt, Disease_ID.txt, LncD_ARR.txt, gaussian_similarity.py, jaccard_similarity.py, source/Gaussian_sim_LncRNA.txt, Get_PathMatrix/PRA/, Test/) │ ├── DC_Prediction/ # Stage 2: Association Prediction │ ├── main.py # Script entry point (config variables, not argparse) │ ├── util.py # load_embeddings, load_edge_splits, build_pairs, deal_embedding, kfold_split, calculate_metrics, EarlyStopping │ ├── model.py # MLP (dual-channel + CBAM), FocalLoss │ ├── cbam.py (imported by model.py — not yet inspected but referenced) │ ├── data/ │ │ └── MiRNA/ │ │ ├── Drug_GT.txt (copied/expected from GetFeature/source/MiRNA/Drug_GT.txt) │ │ ├── NcRNA_GS.txt │ │ ├── Drug_MG.txt │ │ ├── NcRNA_SQ.txt │ │ └── edge_splits.pt (expected; copied from GetFeature/source/MiRNA/edge_splits.pt) │ └── __pycache__/ │ └── (no top-level requirements.txt, environment.yml, setup.py, or README found anywhere under DC-MetaMG — confirmed via Glob) ``` **Note on file naming overlap:** Both GetFeature's `data//` input folder and DC_Prediction's `data//` folder use the same relative path pattern `data//`, but they live under different stage roots and serve different purposes (GetFeature's holds raw inputs; DC_Prediction's holds the embeddings/edge-splits produced by GetFeature). This must be called out clearly in the README to avoid confusion. --- ## 2. GetFeature Stage ### 2.1 `GetFeature/main.py` — Full CLI Arguments Run from inside `GetFeature/` directory (paths are relative, e.g. `data/LncRNA`, `source/`). ``` python main.py [args] ``` | Arg | Default | Meaning | |---|---|---| | `--dataset` | `LncRNA` | `'MiRNA'` or `'LncRNA'` | | `--data_path` | `data/LncRNA` | Path to dataset directory (must match `--dataset`, e.g. `data/MiRNA` for MiRNA) | | `--n_Drug` | `154` | Number of drug nodes (MiRNA: **60**, LncRNA: **154**) | | `--n_NcRNA` | `955` | Number of ncRNA nodes (MiRNA: **561**, LncRNA: **955**) | | `--embedding_size` | `396` | Embedding dim (MiRNA: **198**, LncRNA: **396**) | | `--seed` | `2026` | Random seed | | `--device` | `cuda:0` | Torch device | | `--start_epoch` | `0` | | | `--epochs` | `100` | | | `--train_batch_size` | `4096` | (declared but not directly observed in trainer loop — full-batch training is used in `_train_epoch`) | | `--eval_batch_size` | `4096000` | | | `--n_layers` | `2` | GCN layers per Channel | | `--hyper_layers` | `1` | | | `--num_clusters` | `3` | | | `--temperature` | `0.1` | InfoNCE temperature | | `--alpha` | `1` | | | `--proto_reg` | `1e-8` | | | `--reg_weight` | `1e-1` | | | `--delta` | `5` | | | `--m_step` | `1` | | | `--warm_up_step` | `20` | | | `--clip_max_norm` | `30` | Gradient clipping max norm | | `--clip_norm_type` | `2` | L2 norm | **Example commands (to put in README):** ```powershell # MiRNA dataset python main.py --dataset MiRNA --data_path data/MiRNA --n_Drug 60 --n_NcRNA 561 --embedding_size 198 # LncRNA dataset (uses argparse defaults) python main.py --dataset LncRNA --data_path data/LncRNA --n_Drug 154 --n_NcRNA 955 --embedding_size 396 ``` **Internal flow of main.py:** 1. `set_seed(args.seed)` 2. `smiles, splits = get_data(args)` — loads `edges.txt` + `DrugSmile.csv` from `data_path`, builds bipartite graph, runs `RandomLinkSplit` (80/20 train/test, undirected, negative sampling ratio 1.0), and **persists the split to `/splits.pt`** (note: the `if False and os.path.exists(...)` check in `util.get_data` means the cached splits.pt is currently never loaded — it always regenerates and overwrites `splits.pt`, even if one already exists). 3. `model = MetaMG(args, smiles, args.embedding_size, 1, splits['train'])` — builds the model, which in `InitFeature()` loads `GIP_Topo_drug.txt`, `Gaussian_sim_.txt`, `Feature__SQ.txt` from `data_path` as initial embeddings, and internally computes drug-molecule embeddings via RDKit/DGL from SMILES (`DrugMG`). 4. `trainer = Trainer(args, model, splits)`; `trainer.train(splits['train'])` runs the training loop for `args.epochs` epochs, then calls `_save_embeddings()` and `_save_edge_splits()`. **Output produced by running `main.py` (Stage 1 deliverables):** - Directory `GetFeature/source//` is created (relative to CWD, i.e. relative to wherever `main.py` is run from — must run from `GetFeature/` directory for paths to resolve as documented). - Files written: - `Drug_GT.txt` — coarse-grained drug embeddings (space-delimited via `np.savetxt`) - `NcRNA_GS.txt` — coarse-grained ncRNA embeddings - `Drug_MG.txt` — fine-grained drug embeddings - `NcRNA_SQ.txt` — fine-grained ncRNA embeddings - `edge_splits.pt` — a `dict` saved via `torch.save`, containing: - `train_pos_edge_index`, `train_neg_edge_index` (always present) - `test_pos_edge_index`, `test_neg_edge_index` (present if test split exists) - Each is a `torch.LongTensor` of shape `[2, E]` (row 0 = drug idx, row 1 = ncRNA idx, offset by `n_Drug`) - Also as a side effect: `/splits.pt` is (re)written by `get_data()` — this is the PyG train/test `Data` object split (different from `edge_splits.pt`; this one is GetFeature's own internal link-split cache, not consumed by DC_Prediction). ### 2.2 `GetFeature/trainer.py` — High-Level Flow - `Trainer(args, model, splits)` wraps the `MetaMG` model. - `.train(train_data)`: - Creates Adam optimizer (`lr=1e-3`, `weight_decay=5e-4`) over `model.parameters()`. - Loops `epochs` times calling `_train_epoch`, which does forward pass via `model.calculate_loss(train_data)`, backprop, gradient clipping (`clip_grad_norm_`), optimizer step. Prints loss every 10 epochs. - After training completes: calls `_save_embeddings()` (writes the 4 `.txt` embedding files into `source//`) and `_save_edge_splits()` (writes `edge_splits.pt` into the same folder). - Trains a **single model instance**, no k-fold/cross-validation in this stage — that happens later in DC_Prediction. ### 2.3 `GetFeature/data/` Contents (2 levels) — Raw Input Files Expected **`data/MiRNA/`:** - `edges.txt` — tab-separated drug–miRNA interaction pairs (positive edges), no header. Read via `pd.read_csv(..., header=None, sep='\t')`. Column 0 = drug index, column 1 = ncRNA index. - `DrugSmile.csv` — one SMILES string per line, in drug-index order (read via plain `readlines()`). - `GIP_Topo_drug.txt` — GIP+topology drug similarity/feature matrix, space-delimited, loaded with `np.loadtxt(..., delimiter=" ")`. - `Gaussian_sim_MiRNA.txt` — Gaussian interaction profile similarity matrix for miRNA, space-delimited. - `Feature_MiRNA_SQ.txt` — sequence-derived feature matrix for miRNA, loaded with `np.loadtxt(..., delimiter=None)` (whitespace-flexible). - `splits.pt` — PyG link-split cache (regenerated each run currently, due to the `if False and ...` short-circuit in `util.get_data`). - `DATA_DMP/` subfolder: - `MetaPath_drug_2a.txt`, `MetaPath_miRNA_2a.txt`, `MetaPath_drug_2a_F.txt` — meta-path adjacency files. Note: `get_edge_index(..., mode='MetaPath')` in `util.util.py` actually looks for `DATA_DMP/MetaPath_drug.txt` and `DATA_DMP/MetaPath_{args.dataset}.txt` (i.e. `MetaPath_MiRNA.txt`) — the files present on disk are named `..._2a.txt` / `..._2a_F.txt`, which is a **naming mismatch** worth flagging in the README as something the user must verify/rename before running (or the actual filenames used differ from what's on disk currently for the MiRNA dataset). **`data/LncRNA/`:** - `edges.txt`, `DrugSmile.csv`, `GIP_Topo_drug.txt` — same role as above, for LncRNA dataset. - `Gaussian_sim_LncRNA.txt` — Gaussian similarity matrix for LncRNA. - `Feature_LncRNA_Sq.txt` — sequence-derived feature matrix for LncRNA (note capitalization differs slightly from MiRNA's `Feature_MiRNA_SQ.txt` — code builds the name dynamically as `f'Feature_{args.dataset}_SQ.txt'`, so for `--dataset LncRNA` it would look for `Feature_LncRNA_SQ.txt`; the file present is `Feature_LncRNA_Sq.txt` — **case mismatch** to flag, since Windows filesystems are case-insensitive but Linux deployment would break). - `splits.pt` — same role as MiRNA's. - `DATA_DMP/`: - `MetaPath_drug.txt`, `MetaPath_lncRNA.txt` — these names DO match what `get_edge_index(mode='MetaPath')` expects (`MetaPath_drug.txt` and `MetaPath_{dataset}.txt` → `MetaPath_LncRNA.txt`... still a case difference: file is `MetaPath_lncRNA.txt` lowercase "l" vs dataset arg `LncRNA`). Flag this too. ### 2.4 Dynamic Meta-path Selection — Separate Preprocessing Step (Run BEFORE GetFeature/main.py) This is **not invoked by `GetFeature/main.py`**. It is a standalone preprocessing stage whose outputs (`MetaPath_drug*.txt`, `MetaPath_miRNA.txt` / `MetaPath_lncRNA.txt`, similarity matrices, etc.) feed into `GetFeature/data//DATA_DMP/` and other `data//` files. It must be run first, manually, before `GetFeature/main.py`. **`Dynamic Meta-path Selection/MiRNA/main.py`** (43 lines, full content read): - Imports `getValue` (unused directly in visible code) and `set_seed, getMetaPath` from local `util` package. - `set_seed(48)` — hardcoded seed, independent of GetFeature's seed arg. - Loads `data/array_DD.txt` (drug-disease matrix) and `data/array_MD.txt` (miRNA-disease matrix) — relative to this folder, i.e. `Dynamic Meta-path Selection/MiRNA/data/`. - Computes drug meta-path (`DDI`) via `getMetaPath(num=num_D, object_disease_matrix=drug_disease_matrix, correlation_file='data/correlation_Drug.txt', max_hops=3, alpha=2.0, beta=1.0)`, writes to `data/MetaPath_drug.txt` (relative to this folder). - Computes miRNA meta-path (`MMI`) similarly with `max_hops=2`, `correlation_file='data/correlation_MiRNA.txt'`, writes to `data/MetaPath_miRNA.txt`. - **Must be run from inside `Dynamic Meta-path Selection/MiRNA/` directory** (uses relative paths `data/...`). - Output paths are local to this subfolder (`data/MetaPath_drug.txt`, `data/MetaPath_miRNA.txt`) — these would then need to be manually copied/placed into `GetFeature/data/MiRNA/DATA_DMP/` for `main.py`'s `get_edge_index(mode='MetaPath')` to find them (matching the naming-mismatch issue noted in 2.3). **`Dynamic Meta-path Selection/LncRNA/main.py`** (43 lines, full content read): - Same structure, `set_seed(48)`. - Loads `data/array_DD.txt` and `data/array_LD.txt` (lncRNA-disease matrix) relative to this folder. - Drug meta-path: same params as MiRNA version, but writes directly to `../../data/LncRNA/DATA_DMP/MetaPath_drug.txt` — i.e. an **absolute-relative path that writes straight into `GetFeature/data/LncRNA/DATA_DMP/`** (two levels up from `Dynamic Meta-path Selection/LncRNA/`). This matches the LncRNA `DATA_DMP/MetaPath_drug.txt` file confirmed present in section 2.3. - lncRNA meta-path: `max_hops=2`, `correlation_file='data/correlation_lncRNA.txt'`, writes to `../../data/LncRNA/DATA_DMP/MetaPath_lncRNA.txt` — also matches confirmed file `MetaPath_lncRNA.txt`. - **Inconsistency to note in README:** the LncRNA version writes its outputs directly into `GetFeature/data/LncRNA/DATA_DMP/`, while the MiRNA version writes outputs locally into its own `data/` folder (requiring a manual copy step into `GetFeature/data/MiRNA/DATA_DMP/`). The README should explicitly call out this asymmetry as a manual step for the MiRNA pipeline. - Also contains larger `GetMatrix_Drug/` and `GetMatrix_LncRNA/` (or `GetMatrix_MiRNA/`) sibling subfolders with their own scripts (`jaccard_similarity.py`, `gaussian_similarity.py`, `Get_PathMatrix/PRA/PRA.py`, `Test/` scripts for `ClearCommon.py`/`CreateIndex.py`/`GetArr.py`) that appear to be earlier preprocessing steps generating the similarity/array files (`array_DD.txt`, `DD_ARR.txt`, `Jaccard_sim_Drug.txt`, `Gaussian_sim_Drug.txt`, `Topo_drug.txt`, `GIP_Topo_drug.txt`, `drug_embeddings.csv`, etc.) consumed by `Dynamic Meta-path Selection//main.py` and ultimately by `GetFeature/data//`. These were not read in detail (out of scope per the request, which only asked for `main.py` files), but should be mentioned as an even-earlier optional preprocessing layer if the user wants to regenerate similarity matrices from scratch rather than using the provided `.txt`/`.csv` files already present in the repo. ### 2.5 GetSqFeature — Sequence K-mer Feature Scripts **`GetFeature/GetSqFeature/Kmer_MiRNA.py`** (first 40 lines read): - Imports: `argparse`, `collections.defaultdict`, `itertools.product`, `numpy`, `pandas`, `sklearn.decomposition.PCA`, `sklearn.impute.SimpleImputer`, `sklearn.preprocessing.StandardScaler`. - `generate_all_kmers(k_values=(2,3,4,5))` — generates all k-mers over RNA alphabet `ACGU`. - `count_kmers(sequence, k_values=(2,3,4,5))` — counts k-mer occurrences in a sequence. - `create_multi_kmer_matrix(sequences: dict, k_values=(2,3,4,5), normalize=True)` — builds a k-mer frequency DataFrame from a `{name: sequence}` dict, filtering out too-short sequences. - Input: presumably raw miRNA sequences (likely from `MiRNA_Sq.txt` in the same folder, given its presence). Output (inferred from sibling files `mirna_kmer_matrix.csv`, `reduced_kmer_features.csv`, `multi_kmer_matrix.csv` already present in `GetSqFeature/MiRNA/`) — produces k-mer count/frequency matrices, likely PCA-reduced, eventually becoming `Feature_MiRNA_SQ.txt` consumed by `GetFeature/model/model.py`'s `InitFeature()`. Exact CLI args/argparse setup and file I/O code were beyond the 40-line read window — README should note this script needs to be run with its own arguments (not fully visible) before `GetFeature/main.py`, OR note that its output `Feature_MiRNA_SQ.txt` is already present in `data/MiRNA/` so re-running it is optional unless regenerating from raw sequences. **`GetFeature/GetSqFeature/Kmer_LncRNA.py`** (first 40 lines read): - Imports: `argparse`, `numpy`, `collections.defaultdict`, `itertools.product`, `sklearn.decomposition.PCA`, `sklearn.preprocessing.StandardScaler`, `sklearn.impute.SimpleImputer`. - `read_lncrna_ids(file_path)` — reads lncRNA IDs from a tab-separated file's 2nd column (likely `LncRNA_ID.txt`). - `process_fasta_file(fasta_file, lncrna_ids)` — parses a FASTA file (likely `LncRNA_Sq.fasta`, confirmed present in the same folder), where headers are formatted `>base_id:part_num`, concatenating multi-part sequences per ID. - Output (inferred): produces `Feature_LncRNA_Sq.txt` (already present in `data/LncRNA/`) consumed downstream, similar role to the MiRNA k-mer script. - Both scripts are **optional/already-executed preprocessing** — their outputs already exist as `.txt` files in `GetFeature/data//`, so for reproduction purposes the README can note: "these have already been run; their outputs (`Feature_MiRNA_SQ.txt`, `Feature_LncRNA_Sq.txt`) are included in `data//`. Only re-run if regenerating sequence features from scratch using `MiRNA_Sq.txt`/`LncRNA_Sq.fasta` + `LncRNA_ID.txt`." ### 2.6 GetFeature — All Python Imports (scanned) From `main.py`: `argparse`, local: `trainer.Trainer`, `model.model.MetaMG`, `util.util.get_data, set_seed` From `trainer.py`: `os`, `numpy as np`, `torch`, `torch.nn.utils.clip_grad.clip_grad_norm_` From `util/util.py`: `os`, `numpy as np`, `torch`, `torch_geometric.transforms as T`, `pandas as pd`, `random`, `torch_geometric.data.Data` From `model/model.py`: `os`, `numpy as np`, `torch`, `torch.nn as nn`, `torch.nn.functional as F`, `recbole.utils.InputType`, `torch_geometric.nn.GCNConv`, local: `model.DrugMG.*`, `util.util.*` From `model/DrugMG.py`: `numpy as np`, `torch`, `dgl`, `rdkit.Chem`, `dgllife.utils.mol_to_bigraph, PretrainAtomFeaturizer, PretrainBondFeaturizer`, `dgl.nn.pytorch.glob.AvgPooling, MaxPooling, WeightAndSum, SumPooling`, `sklearn.preprocessing.StandardScaler`, `scipy.spatial.distance.cdist`, `rdkit.Chem.AllChem`, `torch.nn as nn`, local: `model.hgnn.HGNN`, `util.util.*` From `model/hgnn.py`: `torch`, `torch.nn as nn`, `torch.nn.functional as F`, `dgl.function as fn`, `dgl.nn.pytorch.edge_softmax`, `torch.utils.checkpoint.checkpoint` From `GetSqFeature/Kmer_MiRNA.py` / `Kmer_LncRNA.py`: `argparse`, `numpy as np`, `collections.defaultdict`, `itertools.product`, `sklearn.decomposition.PCA`, `sklearn.preprocessing.StandardScaler`, `sklearn.impute.SimpleImputer`, `pandas as pd` (Kmer_MiRNA only) **Consolidated GetFeature dependency list:** `numpy`, `pandas`, `torch`, `torch_geometric`, `dgl`, `dgllife`, `rdkit`, `scipy`, `scikit-learn` (`sklearn`), `recbole` --- ## 3. DC_Prediction Stage ### 3.1 `DC_Prediction/main.py` — Current Full Content (script-style, not argparse) Run as a plain script from inside `DC_Prediction/` directory: ```powershell python main.py ``` **Configuration block (edit these constants directly in the file, no CLI args):** ```python DATASET = 'MiRNA' # 'MiRNA' or 'LncRNA' N_DRUG = 60 # MiRNA: 60 | LncRNA: 154 SEED = 2026 DEVICE = torch.device('cuda:0') N_FOLDS = 5 EPOCHS = 3000 WARMUP = 2000 PATIENCE = 100 LR = 0.001 WD = 5e-4 ``` To switch to LncRNA, the user must manually edit `DATASET = 'LncRNA'` and `N_DRUG = 154` in the file. **Flow:** 1. `set_seed(SEED)`. 2. `emb_coa, emb_fin = load_embeddings(DATASET)` and `edge_splits = load_edge_splits(DATASET)` — loads the 4 embedding `.txt` files and `edge_splits.pt` from `DC_Prediction/data//`. 3. Builds positive/negative train/test pairs via `build_pairs` + `deal_embedding` for both coarse (`emb_coa`) and fine (`emb_fin`) embedding channels. 4. Fixed test tensor/label built once (`test_data`, `test_label`). 5. `find_best_threshold()` helper defined (currently unused — commented out at lines 85–86 inside `evaluate()`). 6. `evaluate(model)` — runs inference on fixed test set with `0.5` threshold, computes AUC, ACC, PRE, SEN, F1, AUPR via `roc_auc_score`, `average_precision_score`, `f1_score`, and `calculate_metrics` (custom accuracy/sensitivity/precision/specificity from confusion matrix). 7. **5-fold CV loop** (`N_FOLDS=5`): for each fold, builds a fresh `MLP(feat_dim, feat_dim, 64, 1)` model + Adam optimizer + `BCEWithLogitsLoss`, trains up to `EPOCHS=3000` with early stopping (after `WARMUP=2000` epochs, `PATIENCE=100`) monitoring AUC on the fixed test set. Records final fold scores, prints per-fold metrics. 8. **Summary**: prints mean of the 6 metrics (AUC, ACC, PRE, SEN, F1, AUPR) across the 5 folds. 9. **False Negative Analysis section** (newly added, currently a stub — header printed but no body yet implemented: lines 138–144 only print a section banner "Analyzing False Negatives on Positive Test Set" with no actual analysis code following). This should be noted in the README as a section that exists as a placeholder/header only in the current file state, with no implemented logic yet (user may want to flag this as "to be completed" or simply not document it as a working feature yet). ### 3.2 `DC_Prediction/util.py` — load_embeddings() and load_edge_splits() ```python def load_embeddings(dataset: str = 'MiRNA'): base = os.path.join('data', dataset) embedding1 = np.loadtxt(os.path.join(base, 'Drug_GT.txt'), dtype=float, delimiter=" ") embedding2 = np.loadtxt(os.path.join(base, 'NcRNA_GS.txt'), dtype=float, delimiter=" ") embedding3 = np.loadtxt(os.path.join(base, 'Drug_MG.txt'), dtype=float, delimiter=" ") embedding4 = np.loadtxt(os.path.join(base, 'NcRNA_SQ.txt'), dtype=float, delimiter=" ") emb_coa = np.vstack((embedding1, embedding2)) # coarse: Drug_GT + NcRNA_GS stacked emb_fin = np.vstack((embedding3, embedding4)) # fine: Drug_MG + NcRNA_SQ stacked return emb_coa, emb_fin ``` - **Expected path:** `DC_Prediction/data//Drug_GT.txt`, `NcRNA_GS.txt`, `Drug_MG.txt`, `NcRNA_SQ.txt` (relative to CWD when running `main.py` from `DC_Prediction/`). - These are exactly the same 4 filenames produced by `GetFeature/trainer.py::_save_embeddings()` into `GetFeature/source//`. ```python def load_edge_splits(dataset: str = 'MiRNA'): split_path = os.path.join('data', dataset, 'edge_splits.pt') if not os.path.exists(split_path): raise FileNotFoundError( f"Edge splits file not found: {split_path}\n" "Please run GetFeature/main.py first to generate the splits." ) return torch.load(split_path) ``` - **Expected path:** `DC_Prediction/data//edge_splits.pt`. - **Format:** a `dict` (saved via `torch.save`) with keys `train_pos_edge_index`, `train_neg_edge_index`, `test_pos_edge_index`, `test_neg_edge_index`, each a `torch.LongTensor[2, E]` — identical structure to what `GetFeature/trainer.py::_save_edge_splits()` produces. - **Script that creates `edge_splits.pt`:** confirmed only `GetFeature/trainer.py::_save_edge_splits()` (line 76–96) creates this file — no other script in either `DC_Prediction` or `GetFeature` writes a file with this name (the directory listing already shows `edge_splits.pt` does NOT yet physically exist anywhere in the current GetSqFeature/Glob results — only `splits.pt` was found in `GetFeature/data/MiRNA/`, `GetFeature/data/LncRNA/`, and `GetFeature/source/MiRNA/`; `edge_splits.pt` was not listed in any Glob result so far, meaning it must be generated by running `GetFeature/main.py` before `DC_Prediction/main.py` can work — confirming the explicit error message in `load_edge_splits`). - The error message itself instructs the user correctly: "Please run GetFeature/main.py first to generate the splits." — this is exactly the dependency relationship to document in the README. ### 3.3 `DC_Prediction/model.py` — Class Names/Signatures ```python class MLP(torch.nn.Module): def __init__(self, num_in: int, num_hid1: int, num_hid2: int, num_out: int) def forward(self, x: torch.Tensor, x1: torch.Tensor) -> torch.Tensor ``` - Dual-channel MLP with CBAM attention (`from cbam import CBAM`) fusing coarse (`x`) and fine (`x1`) embedding channels, two parallel branches (`branch1_*`, `branch2_*`), final output = weighted sum of sigmoid(branch1) and sigmoid(branch2) using a learnable softmax-normalized `channel_weight`. ```python class FocalLoss(nn.Module): def __init__(self, alpha=0.25, gamma=2.0) def forward(self, logits, targets) ``` - Defined but not actually used as the loss in `main.py` (which uses `BCEWithLogitsLoss` instead — `model.criterion` line is commented out). ### 3.4 DC_Prediction — All Python Imports (scanned) From `main.py`: `numpy as np`, `torch`, `tqdm`, `sklearn.metrics.roc_auc_score, average_precision_score, f1_score, precision_score, accuracy_score`, local: `util.{set_seed, load_embeddings, load_edge_splits, build_pairs, deal_embedding, kfold_split, calculate_metrics, EarlyStopping}`, `model.MLP` From `util.py`: `os`, `numpy as np`, `random`, `torch`, `pandas as pd`, `sklearn.metrics.confusion_matrix` From `model.py`: `torch`, `cbam.CBAM` (local module, not yet inspected but present alongside model.py per import), `torch.nn as nn`, `torch.nn.functional as F` **Consolidated DC_Prediction dependency list:** `numpy`, `pandas`, `torch`, `tqdm`, `scikit-learn` (`sklearn`) --- ## 4. Connection Between GetFeature and DC_Prediction (Confirmed File Trace) **GetFeature produces (relative to `GetFeature/` working directory, via `trainer.py::_save_embeddings()` and `_save_edge_splits()`):** ``` GetFeature/source//Drug_GT.txt GetFeature/source//NcRNA_GS.txt GetFeature/source//Drug_MG.txt GetFeature/source//NcRNA_SQ.txt GetFeature/source//edge_splits.pt ``` Confirmed present on disk for MiRNA already (likely from a prior run): `GetFeature/source/MiRNA/Drug_GT.txt`, `NcRNA_GS.txt`, `Drug_MG.txt`, `splits.pt` (note: only `splits.pt` was confirmed via Glob in that exact folder, not `edge_splits.pt` — the Glob output showed `GetFeature\source\MiRNA\splits.pt` and `GetFeature\source\MiRNA\Drug_GT.txt`, `NcRNA_GS.txt`, `Drug_MG.txt`; `edge_splits.pt` specifically was not seen in the truncated Glob output but the corresponding `DC_Prediction/data/MiRNA/edge_splits.pt` mapping was cut off in the truncated listing — README should instruct the user to verify this file's presence after running `GetFeature/main.py`, since the code unconditionally writes it). **DC_Prediction expects to read (relative to `DC_Prediction/` working directory, via `util.py::load_embeddings()` and `load_edge_splits()`):** ``` DC_Prediction/data//Drug_GT.txt DC_Prediction/data//NcRNA_GS.txt DC_Prediction/data//Drug_MG.txt DC_Prediction/data//NcRNA_SQ.txt DC_Prediction/data//edge_splits.pt ``` Confirmed present on disk already for MiRNA (per Glob output): `DC_Prediction/data/MiRNA/Drug_GT.txt`, `NcRNA_GS.txt`, `Drug_MG.txt`, `NcRNA_SQ.txt` all confirmed mirrored from `GetFeature/source/MiRNA/*`. **Conclusion — the bridging step between the two stages is a manual file copy:** There is **no automated script** that copies files from `GetFeature/source//` to `DC_Prediction/data//`. The user must manually copy (or symlink) all 5 files: ```powershell # Example for MiRNA, run from the DC-MetaMG root Copy-Item "GetFeature\source\MiRNA\Drug_GT.txt" "DC_Prediction\data\MiRNA\Drug_GT.txt" Copy-Item "GetFeature\source\MiRNA\NcRNA_GS.txt" "DC_Prediction\data\MiRNA\NcRNA_GS.txt" Copy-Item "GetFeature\source\MiRNA\Drug_MG.txt" "DC_Prediction\data\MiRNA\Drug_MG.txt" Copy-Item "GetFeature\source\MiRNA\NcRNA_SQ.txt" "DC_Prediction\data\MiRNA\NcRNA_SQ.txt" Copy-Item "GetFeature\source\MiRNA\edge_splits.pt" "DC_Prediction\data\MiRNA\edge_splits.pt" ``` This exact copy step (with both dataset variants) is the critical link the README must document as **Step 3** between GetFeature and DC_Prediction. --- ## 5. Existing README / requirements / environment / setup files (Glob results) - `**/README*` under `DC-MetaMG` → **No files found** (confirmed empty result). - `**/requirements*.txt` → matches found only OUTSIDE `DC-MetaMG` (in sibling sample projects `RareDDIE-main\RareDDIE-main\requirements.txt` and `MPHGNN-main\DeepLDA-main\Codes\requirements.txt` — these are unrelated other projects in the parent `CircRNA-MiRNA` directory, NOT part of `DC-MetaMG`). - `**/environment*.yml` → match found only OUTSIDE `DC-MetaMG` (`SCAGE-master\SCAGE-master\environment.yml` — also an unrelated sibling project). - `**/setup.py` → not explicitly globbed yet, but no setup.py appeared in the full `**/*` directory listing for `DC-MetaMG` either. **Conclusion: `DC-MetaMG` currently has NO README.md, NO requirements.txt, NO environment.yml, and NO setup.py of its own.** The README being written will be the first one, and should include a "Dependencies / Environment Setup" section listing the consolidated package list manually (since no requirements file exists to point to): ``` torch, torch_geometric, dgl, dgllife, rdkit (rdkit-pypi or python-rdkit), scipy, scikit-learn, numpy, pandas, tqdm, recbole ``` (CUDA-enabled PyTorch is required since `device='cuda:0'` / `torch.device('cuda:0')` is hardcoded in multiple places — `DC_Prediction/main.py`'s `DEVICE`, `GetFeature/model/model.py`'s `self.device`, `GetFeature/model/DrugMG.py`'s `self.device`, etc. The README should note that a GPU is effectively required unless the user patches these hardcoded `cuda:0` references.) --- ## Outstanding minor gaps (not required to block README writing, but worth flagging to user) 1. `cbam.py` (used by `DC_Prediction/model.py` and presumably also `GetFeature` somewhere) was referenced but its contents not read — not necessary for README purposes since it's an internal implementation detail, not a CLI/config surface. 2. Exact full content of `Kmer_MiRNA.py` / `Kmer_LncRNA.py` beyond line 40 (e.g., their `argparse` CLI args, `main`/`__main__` block, exact output filenames) was not read — README can describe them as "preprocessing scripts whose outputs are already included in `data//`" without needing the exact CLI surface, since per-task scope only required first-40-line inspection. 3. The naming mismatches in section 2.3/2.4 (`MetaPath_drug_2a.txt` vs expected `MetaPath_drug.txt`; `Feature_LncRNA_Sq.txt` vs expected `Feature_LncRNA_SQ.txt`; `MetaPath_lncRNA.txt` vs expected `MetaPath_LncRNA.txt`) are case/naming discrepancies between what the code expects and what's on disk — worth a "Known Issues / Things to Verify" section in the README rather than silently assuming they work (Windows is case-insensitive so it may work as-is on this machine, but would break on Linux).