Publish revised BERTose and BERToseBind release
Browse filesAdd the verified versioned scientific release and reader-facing documentation; preserve legacy files and history.
This view is limited to 50 files because it contains too many changes. See raw diff
- .gitattributes +2 -0
- README.md +14 -88
- releases/2026-10-02/iar_completion/requirements.txt +5 -0
- releases/2026-10-02/iar_completion/runtime_dependencies.json +280 -0
- releases/2026-10-02/iar_completion/runtime_snapshot/java/review_A5WurcsArrayTreeAudit.java +467 -0
- releases/2026-10-02/iar_completion/runtime_snapshot/java/review_MolWURCS.jar +3 -0
- releases/2026-10-02/iar_completion/runtime_snapshot/java/review_wurcsframework-1.3.1.jar +3 -0
- releases/2026-10-02/iar_completion/runtime_snapshot/project/bert_training_v4/downstream_tasks/utils/wurcs_bpe_tokenizer.py +740 -0
- releases/2026-10-02/iar_completion/runtime_snapshot/project/data/bpe_ambiguity_tokens.json +721 -0
- releases/2026-10-02/iar_completion/runtime_snapshot/project/data/bpe_vocabulary_clean.json +0 -0
- releases/2026-10-02/iar_completion/runtime_snapshot/project/data/review_sequences_a5_non_iar_later_role_official_array_v4_20260721_r1/review_bpe_ambiguity_tokens.json +764 -0
- releases/2026-10-02/iar_completion/runtime_snapshot/project/data/review_sequences_a5_non_iar_later_role_official_array_v4_20260721_r1/review_bpe_vocabulary.json +0 -0
- releases/2026-10-02/iar_completion/runtime_snapshot/project/data/review_sequences_a5_non_iar_later_role_official_array_v4_20260721_r1/review_frozen_sequence_tree_runtime.py +287 -0
- releases/2026-10-02/iar_completion/runtime_snapshot/project/data/review_sequences_a5_non_iar_later_role_official_array_v4_20260721_r1/review_frozen_training_a5_topology.py +180 -0
- releases/2026-10-02/iar_completion/runtime_snapshot/project/data/review_sequences_a5_non_iar_later_role_official_array_v4_20260721_r1/review_frozen_training_a5_wurcs_bpe.py +368 -0
- releases/2026-10-02/iar_completion/runtime_snapshot/project/writing/cluster/nature_submission/code/model/__init__.py +3 -0
- releases/2026-10-02/iar_completion/runtime_snapshot/project/writing/cluster/nature_submission/code/model/glycan_bert.py +303 -0
- releases/2026-10-02/iar_completion/runtime_snapshot/project/writing/cluster/nature_submission/code/model/multimodal_glycan_bert_v3.py +1084 -0
- releases/2026-10-02/iar_completion/runtime_snapshot/project/writing/cluster/nature_submission/code/training/ipa_bpe_distillation.py +377 -0
- releases/2026-10-02/iar_completion/runtime_snapshot/project/writing/glycangt_heldout_ipa_validation/cluster/heldout_ipa_eval.py +962 -0
- releases/2026-10-02/iar_completion/runtime_snapshot/schema/classify.py +78 -0
- releases/2026-10-02/iar_completion/runtime_snapshot/schema/pipelib.py +119 -0
- releases/2026-10-02/iar_inference/README.md +58 -0
- releases/2026-10-02/iar_inference/SHA256SUMS +10 -0
- releases/2026-10-02/iar_inference/config.json +178 -0
- releases/2026-10-02/iar_inference/fixtures/case0_pre_sequence_head.npy +3 -0
- releases/2026-10-02/iar_inference/fixtures/case1_pre_sequence_head.npy +3 -0
- releases/2026-10-02/iar_inference/fixtures/rebuilt_two_case_inputs.json +3718 -0
- releases/2026-10-02/iar_inference/fixtures/reference_smoke_report.json +253 -0
- releases/2026-10-02/iar_inference/infer.py +290 -0
- releases/2026-10-02/iar_inference/original_inference_helpers.py +97 -0
- releases/2026-10-02/iar_inference/preparation_validation.json +17 -0
- releases/2026-10-02/iar_inference/requirements.txt +3 -0
- releases/2026-10-02/notebooks/BERTose_workbench.ipynb +583 -0
- releases/2026-10-02/provenance/WA3_checkpoint_index.json +1 -0
- releases/2026-10-02/provenance/WA3_final_receipt.json +1 -0
- releases/2026-10-02/provenance/affinose_arms_on_test_20260909.json +263 -0
- releases/2026-10-02/provenance/affinose_cells/affinose_mo_20260908_mo_A_glycan_s42/receipt.json +101 -0
- releases/2026-10-02/provenance/affinose_cells/affinose_mo_20260908_mo_A_glycan_s42/results.json +339 -0
- releases/2026-10-02/provenance/affinose_cells/affinose_mo_20260908_mo_C_doubly_s42/receipt.json +101 -0
- releases/2026-10-02/provenance/affinose_cells/affinose_mo_20260908_mo_C_doubly_s42/results.json +294 -0
- releases/2026-10-02/provenance/affinose_cells/affinose_mof_20260909_mof_B_protein_s43/receipt.json +101 -0
- releases/2026-10-02/provenance/affinose_cells/affinose_mof_20260909_mof_B_protein_s43/results.json +294 -0
- releases/2026-10-02/provenance/affinose_cells/affinose_mof_20260909_mof_B_protein_s44/receipt.json +101 -0
- releases/2026-10-02/provenance/affinose_cells/affinose_mof_20260909_mof_B_protein_s44/results.json +324 -0
- releases/2026-10-02/provenance/affinose_cells/affinose_mof_20260909_mof_C_doubly_s43/receipt.json +101 -0
- releases/2026-10-02/provenance/affinose_cells/affinose_mof_20260909_mof_C_doubly_s43/results.json +234 -0
- releases/2026-10-02/provenance/affinose_cells/affinose_mof_20260909_mof_C_doubly_s44/receipt.json +101 -0
- releases/2026-10-02/provenance/affinose_cells/affinose_mof_20260909_mof_C_doubly_s44/results.json +264 -0
- releases/2026-10-02/provenance/affinose_cells/affinose_sa_20260908_mo_B_protein_s42/receipt.json +101 -0
.gitattributes
CHANGED
|
@@ -6,3 +6,5 @@
|
|
| 6 |
*.npz filter=lfs diff=lfs merge=lfs -text
|
| 7 |
*.npy filter=lfs diff=lfs merge=lfs -text
|
| 8 |
data/splits/train_val_split.json filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
| 6 |
*.npz filter=lfs diff=lfs merge=lfs -text
|
| 7 |
*.npy filter=lfs diff=lfs merge=lfs -text
|
| 8 |
data/splits/train_val_split.json filter=lfs diff=lfs merge=lfs -text
|
| 9 |
+
releases/2026-10-02/iar_completion/runtime_snapshot/java/review_MolWURCS.jar filter=lfs diff=lfs merge=lfs -text
|
| 10 |
+
releases/2026-10-02/iar_completion/runtime_snapshot/java/review_wurcsframework-1.3.1.jar filter=lfs diff=lfs merge=lfs -text
|
README.md
CHANGED
|
@@ -2,103 +2,29 @@
|
|
| 2 |
license: apache-2.0
|
| 3 |
tags:
|
| 4 |
- glycans
|
| 5 |
-
- wurcs
|
| 6 |
- bertose
|
| 7 |
-
- affinose
|
| 8 |
-
- reproducibility
|
| 9 |
-
- training-code
|
| 10 |
-
- pytorch
|
| 11 |
---
|
| 12 |
|
| 13 |
-
# BERTose and
|
| 14 |
|
| 15 |
-
This repository
|
| 16 |
|
| 17 |
-
|
| 18 |
|
| 19 |
-
|
| 20 |
-
- BERTose IAR resolver: `supanthadey1/bertose-iar-resolver`
|
| 21 |
-
- AFFINose interaction model: `supanthadey1/affinose-interaction-model`
|
| 22 |
-
- Cloud inference notebook: `supanthadey1/bertose-affinose-inference`
|
| 23 |
-
|
| 24 |
-
## Repository Map
|
| 25 |
-
|
| 26 |
-
| Public workflow | Files |
|
| 27 |
-
|---|---|
|
| 28 |
-
| BERTose multimodal pretraining | `code/training/train_multimodal.py`, `code/training/multimodal_dataset.py`, `code/training/multimodal_masking.py`, `configs/` |
|
| 29 |
-
| BERTose WURCS-BPE tokenizer training | `code/training/train_wurcs_bpe.py`, `code/model/wurcs_bpe_tokenizer.py`, `data/vocab/` |
|
| 30 |
-
| BERTose IAR / contrastive refinement | `code/contrastive/`, `code/contrastive_training/`, `code/tokenizer/generate_bpe_ambiguity.py` |
|
| 31 |
-
| AFFINose interaction training | `code/affinose/README.md` |
|
| 32 |
-
| Benchmark reproduction | `code/benchmarks/`, `code/downstream_tasks/utils/` |
|
| 33 |
-
| Embedding and biology probes | `code/probes/` |
|
| 34 |
-
| Split and vocabulary assets | `data/splits/`, `data/vocab/` |
|
| 35 |
-
| Compute and lineage provenance | `provenance/` |
|
| 36 |
-
|
| 37 |
-
Some executable filenames and directories retain historical names so that provenance remains traceable to the original training runs. In public-facing text, use BERTose for the glycan encoder / IAR workflows and AFFINose for the protein-glycan interaction workflow.
|
| 38 |
-
|
| 39 |
-
## What Is Included
|
| 40 |
-
|
| 41 |
-
- Core BERTose architecture and dataset utilities.
|
| 42 |
-
- BERTose multimodal pretraining entrypoint and configs.
|
| 43 |
-
- WURCS-BPE tokenizer training and ambiguity-token generation code.
|
| 44 |
-
- Contrastive refinement / IAR training and negative generation scripts.
|
| 45 |
-
- AFFINose interaction-model data construction, split generation, training, and inference code.
|
| 46 |
-
- Benchmark and probe scripts used for manuscript analyses.
|
| 47 |
-
- Vocabulary files, ambiguity-token maps, train/validation split metadata, and leakage-exclusion lists.
|
| 48 |
-
- Compute-provenance notes and representative launch scripts.
|
| 49 |
-
|
| 50 |
-
## What Is Not Included
|
| 51 |
-
|
| 52 |
-
Large training artifacts are intentionally not bundled here:
|
| 53 |
-
|
| 54 |
-
- Full pretraining corpus pickles such as `sequences_bpe.pkl`.
|
| 55 |
-
- Multi-GB intermediate mapping files.
|
| 56 |
-
- Full training checkpoints; released checkpoints are hosted in the separate model repositories listed above.
|
| 57 |
-
- ESM-C protein embeddings required for AFFINose training; users should generate or provide those separately according to the ESM-C access rules.
|
| 58 |
-
|
| 59 |
-
## Quick Import Check
|
| 60 |
-
|
| 61 |
-
After downloading the repository, a lightweight import check should work without access to the full training data:
|
| 62 |
|
| 63 |
```bash
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
"training.multimodal_masking",
|
| 72 |
-
"training.train_multimodal",
|
| 73 |
-
"training.train_wurcs_bpe",
|
| 74 |
-
"model.dataset",
|
| 75 |
-
"downstream_tasks.utils.tokenizer",
|
| 76 |
-
"downstream_tasks.utils.wurcs_bpe_tokenizer",
|
| 77 |
-
"downstream_tasks.utils.dataset",
|
| 78 |
-
]:
|
| 79 |
-
importlib.import_module(module)
|
| 80 |
-
print("ok", module)
|
| 81 |
-
PY
|
| 82 |
```
|
| 83 |
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
## Environment
|
| 87 |
-
|
| 88 |
-
Install the core dependencies with:
|
| 89 |
-
|
| 90 |
-
```bash
|
| 91 |
-
pip install -r requirements.txt
|
| 92 |
-
```
|
| 93 |
-
|
| 94 |
-
Some probe scripts also use optional scientific plotting and glycan-analysis packages. See `requirements.txt` for the split between core and optional dependencies.
|
| 95 |
-
|
| 96 |
-
## Reproducibility Notes
|
| 97 |
-
|
| 98 |
-
- `MANIFEST.md` documents the file provenance and model-lineage mapping.
|
| 99 |
-
- `RELEASE_AUDIT.md` documents the public-release state, fixed gaps, verification checks, and known scope limits.
|
| 100 |
-
- Cluster launch scripts under `provenance/compute_provenance/` preserve the original compute context. They are provenance records, not portable one-command launchers for every environment.
|
| 101 |
|
| 102 |
-
|
| 103 |
|
| 104 |
-
|
|
|
|
| 2 |
license: apache-2.0
|
| 3 |
tags:
|
| 4 |
- glycans
|
|
|
|
| 5 |
- bertose
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6 |
---
|
| 7 |
|
| 8 |
+
# BERTose and BERToseBind shared code
|
| 9 |
|
| 10 |
+
This repository preserves the original submission and provides the revised code once under [`releases/2026-10-02/`](releases/2026-10-02/README.md).
|
| 11 |
|
| 12 |
+
Start with the [shared workbench notebook](https://huggingface.co/supanthadey1/bertose-affinose-inference/blob/main/BERTose_workbench.ipynb) for sequence embeddings, BERToseBind prediction and supported IAR completion. The notebook uses this same code package and downloads only the required separately supplied model/data assets. You can download the notebook from its Hub page and open it in Jupyter or upload it into Google Colab.
|
| 13 |
|
| 14 |
+
## Install locally
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 15 |
|
| 16 |
```bash
|
| 17 |
+
python3.12 -m venv .venv
|
| 18 |
+
source .venv/bin/activate
|
| 19 |
+
python -m pip install huggingface_hub==1.1.5
|
| 20 |
+
hf download supanthadey1/bertose-affinose-training-code --repo-type model --revision main \
|
| 21 |
+
--include "releases/2026-10-02/*" --local-dir shared-code
|
| 22 |
+
cd shared-code/releases/2026-10-02
|
| 23 |
+
python -m pip install -r requirements-workbench.txt
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
```
|
| 25 |
|
| 26 |
+
See the [package README](releases/2026-10-02/README.md) for the task commands and [reproduction instructions](releases/2026-10-02/docs/reproduction.md) for training entrypoints, additional input contracts and compute requirements. The complete sources, configurations, figures and execution evidence are preserved here. Portable inference checks do not establish a complete portable training or benchmark rerun.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
|
| 28 |
+
Model weights remain versioned under `releases/2026-09-28/` in the [encoder](https://huggingface.co/supanthadey1/bertose-glycan-encoder), [BERToseBind](https://huggingface.co/supanthadey1/affinose-interaction-model) and [IAR](https://huggingface.co/supanthadey1/bertose-iar-resolver) repositories. Shared data remain in [GlyCorpus](https://huggingface.co/datasets/supanthadey1/glycorpus). Their scientific-file hashes are recorded in the asset downloader configuration.
|
| 29 |
|
| 30 |
+
Original code uses Apache-2.0 with preserved third-party notices and exceptions. Revised weights use Apache-2.0. Author-generated data use CC-BY-4.0; inherited inputs and ESM-C dependencies retain their own terms. See the versioned LICENSE, NOTICE and provenance manifest.
|
releases/2026-10-02/iar_completion/requirements.txt
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Local artifact checks: Python 3.12.4, these already installed versions.
|
| 2 |
+
# Historical final job: Python 3.10.16, torch 2.9.1+cu128; NumPy unrecorded.
|
| 3 |
+
torch==2.9.1
|
| 4 |
+
numpy==1.26.4
|
| 5 |
+
tqdm>=4.0
|
releases/2026-10-02/iar_completion/runtime_dependencies.json
ADDED
|
@@ -0,0 +1,280 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"scope": "Static dependency audit of the unchanged final entrypoint; no full pipeline replay",
|
| 3 |
+
"final_source": "originals/wa3_final_iar_readout_all.py",
|
| 4 |
+
"top_level_external_packages": [
|
| 5 |
+
"numpy",
|
| 6 |
+
"torch"
|
| 7 |
+
],
|
| 8 |
+
"transitive_direct_packages": [
|
| 9 |
+
"tqdm (submitted WA0 harness and distiller)"
|
| 10 |
+
],
|
| 11 |
+
"external_executables": [
|
| 12 |
+
"java",
|
| 13 |
+
"javac"
|
| 14 |
+
],
|
| 15 |
+
"imports": [
|
| 16 |
+
{
|
| 17 |
+
"module": "__future__",
|
| 18 |
+
"names": [
|
| 19 |
+
"annotations"
|
| 20 |
+
],
|
| 21 |
+
"line": 111
|
| 22 |
+
},
|
| 23 |
+
{
|
| 24 |
+
"module": "base64",
|
| 25 |
+
"line": 113
|
| 26 |
+
},
|
| 27 |
+
{
|
| 28 |
+
"module": "builtins",
|
| 29 |
+
"line": 114
|
| 30 |
+
},
|
| 31 |
+
{
|
| 32 |
+
"module": "collections",
|
| 33 |
+
"line": 115
|
| 34 |
+
},
|
| 35 |
+
{
|
| 36 |
+
"module": "csv",
|
| 37 |
+
"line": 116
|
| 38 |
+
},
|
| 39 |
+
{
|
| 40 |
+
"module": "functools",
|
| 41 |
+
"line": 117
|
| 42 |
+
},
|
| 43 |
+
{
|
| 44 |
+
"module": "gzip",
|
| 45 |
+
"line": 118
|
| 46 |
+
},
|
| 47 |
+
{
|
| 48 |
+
"module": "hashlib",
|
| 49 |
+
"line": 119
|
| 50 |
+
},
|
| 51 |
+
{
|
| 52 |
+
"module": "importlib.util",
|
| 53 |
+
"line": 120
|
| 54 |
+
},
|
| 55 |
+
{
|
| 56 |
+
"module": "json",
|
| 57 |
+
"line": 121
|
| 58 |
+
},
|
| 59 |
+
{
|
| 60 |
+
"module": "os",
|
| 61 |
+
"line": 122
|
| 62 |
+
},
|
| 63 |
+
{
|
| 64 |
+
"module": "platform",
|
| 65 |
+
"line": 123
|
| 66 |
+
},
|
| 67 |
+
{
|
| 68 |
+
"module": "re",
|
| 69 |
+
"line": 124
|
| 70 |
+
},
|
| 71 |
+
{
|
| 72 |
+
"module": "shutil",
|
| 73 |
+
"line": 125
|
| 74 |
+
},
|
| 75 |
+
{
|
| 76 |
+
"module": "subprocess",
|
| 77 |
+
"line": 126
|
| 78 |
+
},
|
| 79 |
+
{
|
| 80 |
+
"module": "sys",
|
| 81 |
+
"line": 127
|
| 82 |
+
},
|
| 83 |
+
{
|
| 84 |
+
"module": "time",
|
| 85 |
+
"line": 128
|
| 86 |
+
},
|
| 87 |
+
{
|
| 88 |
+
"module": "pathlib",
|
| 89 |
+
"names": [
|
| 90 |
+
"Path"
|
| 91 |
+
],
|
| 92 |
+
"line": 129
|
| 93 |
+
},
|
| 94 |
+
{
|
| 95 |
+
"module": "numpy",
|
| 96 |
+
"line": 131
|
| 97 |
+
},
|
| 98 |
+
{
|
| 99 |
+
"module": "torch",
|
| 100 |
+
"line": 132
|
| 101 |
+
},
|
| 102 |
+
{
|
| 103 |
+
"module": "frozen_training.a5_wurcs_bpe",
|
| 104 |
+
"line": 339
|
| 105 |
+
},
|
| 106 |
+
{
|
| 107 |
+
"module": "frozen_tree_runtime",
|
| 108 |
+
"line": 340
|
| 109 |
+
},
|
| 110 |
+
{
|
| 111 |
+
"module": "pipelib",
|
| 112 |
+
"names": [
|
| 113 |
+
"parse_record",
|
| 114 |
+
"SIDE_RE",
|
| 115 |
+
"node_index"
|
| 116 |
+
],
|
| 117 |
+
"line": 521
|
| 118 |
+
},
|
| 119 |
+
{
|
| 120 |
+
"module": "classify",
|
| 121 |
+
"names": [
|
| 122 |
+
"PLAIN_LINK"
|
| 123 |
+
],
|
| 124 |
+
"line": 522
|
| 125 |
+
}
|
| 126 |
+
],
|
| 127 |
+
"path_bindings": [
|
| 128 |
+
{
|
| 129 |
+
"variable": "PROJ",
|
| 130 |
+
"source_expression": "Path(\"/work/ratul1/supantha/glycan-SD-VS/bert_training_v3/v3.1_cluster_training\")",
|
| 131 |
+
"line": 137
|
| 132 |
+
},
|
| 133 |
+
{
|
| 134 |
+
"variable": "PKGD",
|
| 135 |
+
"source_expression": "PROJ / \"data/review_sequences_a5_non_iar_later_role_official_array_v4_20260721_r1\"",
|
| 136 |
+
"line": 138
|
| 137 |
+
},
|
| 138 |
+
{
|
| 139 |
+
"variable": "WA0_HARNESS",
|
| 140 |
+
"source_expression": "PROJ / \"writing/glycangt_heldout_ipa_validation/cluster/heldout_ipa_eval.py\"",
|
| 141 |
+
"line": 139
|
| 142 |
+
},
|
| 143 |
+
{
|
| 144 |
+
"variable": "WA0_VOCAB",
|
| 145 |
+
"source_expression": "PROJ / \"data/bpe_vocabulary_clean.json\"",
|
| 146 |
+
"line": 140
|
| 147 |
+
},
|
| 148 |
+
{
|
| 149 |
+
"variable": "WA0_AMB",
|
| 150 |
+
"source_expression": "PROJ / \"data/bpe_ambiguity_tokens.json\"",
|
| 151 |
+
"line": 141
|
| 152 |
+
},
|
| 153 |
+
{
|
| 154 |
+
"variable": "WA0_CKPT_PATH",
|
| 155 |
+
"source_expression": "PROJ / \"checkpoints_v5b_excluded/best_v5b_excluded_model.pt\"",
|
| 156 |
+
"line": 142
|
| 157 |
+
},
|
| 158 |
+
{
|
| 159 |
+
"variable": "BENCH_DIR",
|
| 160 |
+
"source_expression": "PROJ / \"writing/glycangt_heldout_ipa_validation\"",
|
| 161 |
+
"line": 143
|
| 162 |
+
},
|
| 163 |
+
{
|
| 164 |
+
"variable": "SCHEMA_DIR",
|
| 165 |
+
"source_expression": "Path(\"/work/ratul1/supantha/glycan-SD-VS/review/iar_pipe_schema_20260823_r1\")",
|
| 166 |
+
"line": 144
|
| 167 |
+
},
|
| 168 |
+
{
|
| 169 |
+
"variable": "JAVA_BIN",
|
| 170 |
+
"source_expression": "Path(\"/work/ratul1/supantha/miniconda3/envs/DeepGlycanSite/bin\")",
|
| 171 |
+
"line": 145
|
| 172 |
+
},
|
| 173 |
+
{
|
| 174 |
+
"variable": "ROOT",
|
| 175 |
+
"source_expression": "Path(\"/work/ratul1/supantha/bertose_a5_static_precache_20260723_r2c4_closure31_py310_3c8d5299a4af15bc\")",
|
| 176 |
+
"line": 146
|
| 177 |
+
},
|
| 178 |
+
{
|
| 179 |
+
"variable": "TRAIN_MOD",
|
| 180 |
+
"source_expression": "ROOT / (\"writing/review/multimodal/runtime/md_temporal_20x6_end_to_end_20260802_r3_native_intersection/\"\n \"run_review_md_temporal_20x6_training_r3.py\")",
|
| 181 |
+
"line": 147
|
| 182 |
+
},
|
| 183 |
+
{
|
| 184 |
+
"variable": "CK",
|
| 185 |
+
"source_expression": "ROOT / (\"writing/review/multimodal/outputs/a5_wa345_pretraining_20260817_r1/production/\"\n \"review_md20x6_md20x6-a1111-wa345-20260817-r1_A1111_wa3_seed42/review_checkpoints/\"\n \"review_md20x6_checkpoint_best.pt\")",
|
| 186 |
+
"line": 149
|
| 187 |
+
},
|
| 188 |
+
{
|
| 189 |
+
"variable": "WORK",
|
| 190 |
+
"source_expression": "Path(os.environ[\"WORK\"])",
|
| 191 |
+
"line": 154
|
| 192 |
+
},
|
| 193 |
+
{
|
| 194 |
+
"variable": "OUT",
|
| 195 |
+
"source_expression": "WORK / \"outputs\"",
|
| 196 |
+
"line": 156
|
| 197 |
+
},
|
| 198 |
+
{
|
| 199 |
+
"variable": "JAVA_DIR",
|
| 200 |
+
"source_expression": "WORK / \"inputs/java\"",
|
| 201 |
+
"line": 157
|
| 202 |
+
},
|
| 203 |
+
{
|
| 204 |
+
"variable": "SETS",
|
| 205 |
+
"source_expression": "{\n \"bench1392\": {\"runs\": BENCH_RUNS, \"wa0_root\": BENCH_DIR / \"outputs\",\n \"baseline_runs\": [\"benchmark1392_residue_full\", \"benchmark1392_linkage_full\"]},\n \"seal162\": {\"runs\": SEAL_RUNS, \"wa0_root\": WORK / \"inputs/wa0_seal\",\n \"baseline_runs\": [\"seal162_residue_t080\", \"seal162_linkage_t080\"]},\n}",
|
| 206 |
+
"line": 182
|
| 207 |
+
}
|
| 208 |
+
],
|
| 209 |
+
"dynamic_imports": [
|
| 210 |
+
{
|
| 211 |
+
"entry": "load_wa0_evaluator",
|
| 212 |
+
"path_variable": "WA0_HARNESS",
|
| 213 |
+
"included": "runtime_snapshot/project/writing/glycangt_heldout_ipa_validation/cluster/heldout_ipa_eval.py",
|
| 214 |
+
"transitive": [
|
| 215 |
+
"writing/cluster/nature_submission/code/training/ipa_bpe_distillation.py",
|
| 216 |
+
"writing/cluster/nature_submission/code/model/__init__.py",
|
| 217 |
+
"writing/cluster/nature_submission/code/model/multimodal_glycan_bert_v3.py",
|
| 218 |
+
"writing/cluster/nature_submission/code/model/glycan_bert.py",
|
| 219 |
+
"bert_training_v4/downstream_tasks/utils/wurcs_bpe_tokenizer.py"
|
| 220 |
+
],
|
| 221 |
+
"scope": "Original harness imported and initialized with identity model in smoke check"
|
| 222 |
+
},
|
| 223 |
+
{
|
| 224 |
+
"entry": "build_wa3_tokenizer",
|
| 225 |
+
"included": "runtime_snapshot/project/data/review_sequences_a5_non_iar_later_role_official_array_v4_20260721_r1",
|
| 226 |
+
"transitive": [
|
| 227 |
+
"three frozen Python sources",
|
| 228 |
+
"review_bpe_vocabulary.json",
|
| 229 |
+
"review_bpe_ambiguity_tokens.json",
|
| 230 |
+
"bert_training_v4/downstream_tasks/utils/wurcs_bpe_tokenizer.py"
|
| 231 |
+
],
|
| 232 |
+
"scope": "Imports through generated temporary shim verified"
|
| 233 |
+
},
|
| 234 |
+
{
|
| 235 |
+
"entry": "load_achem",
|
| 236 |
+
"included": "runtime_snapshot/schema",
|
| 237 |
+
"transitive": [
|
| 238 |
+
"pipelib.py",
|
| 239 |
+
"classify.py"
|
| 240 |
+
],
|
| 241 |
+
"scope": "Imports verified; these dependencies were not hash-pinned by final job"
|
| 242 |
+
},
|
| 243 |
+
{
|
| 244 |
+
"entry": "load_model",
|
| 245 |
+
"path_variable": "TRAIN_MOD",
|
| 246 |
+
"in_surrounding_code_package": "../bertose_source/writing/review/multimodal/runtime/md_temporal_20x6_end_to_end_20260802_r3_native_intersection/run_review_md_temporal_20x6_training_r3.py",
|
| 247 |
+
"transitive": "Native runtime imports and authority receipts in ../bertose_source; additional immutable external workspace inputs remain required",
|
| 248 |
+
"scope": "Not called in local checks because it loads the full encoder checkpoint"
|
| 249 |
+
}
|
| 250 |
+
],
|
| 251 |
+
"external_data": [
|
| 252 |
+
{
|
| 253 |
+
"resource": "WA3 checkpoint",
|
| 254 |
+
"sha256": "8e7d95ee492df6d843f495dd4708c97ee16a947e75b5cd8f83b23e4f4a0d6d82",
|
| 255 |
+
"included": false
|
| 256 |
+
},
|
| 257 |
+
{
|
| 258 |
+
"resource": "Parent index and six training arrays",
|
| 259 |
+
"details": "provenance/required_input_hashes.json",
|
| 260 |
+
"included": false
|
| 261 |
+
},
|
| 262 |
+
{
|
| 263 |
+
"resource": "Benchmark and grey-seal CSVs",
|
| 264 |
+
"details": "provenance/final_run/run_manifest.json inputs",
|
| 265 |
+
"included": false
|
| 266 |
+
},
|
| 267 |
+
{
|
| 268 |
+
"resource": "Four original WA0 case_details.jsonl and summary.md pairs",
|
| 269 |
+
"runs": [
|
| 270 |
+
"benchmark1392_residue_full",
|
| 271 |
+
"benchmark1392_linkage_full",
|
| 272 |
+
"seal162_residue_t080",
|
| 273 |
+
"seal162_linkage_t080"
|
| 274 |
+
],
|
| 275 |
+
"included": false
|
| 276 |
+
}
|
| 277 |
+
],
|
| 278 |
+
"lineage_sources_are_runtime_imports": false,
|
| 279 |
+
"java_helper_compilation_checked": false
|
| 280 |
+
}
|
releases/2026-10-02/iar_completion/runtime_snapshot/java/review_A5WurcsArrayTreeAudit.java
ADDED
|
@@ -0,0 +1,467 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package review.a5;
|
| 2 |
+
|
| 3 |
+
import java.io.BufferedReader;
|
| 4 |
+
import java.io.InputStreamReader;
|
| 5 |
+
import java.nio.charset.StandardCharsets;
|
| 6 |
+
import java.security.MessageDigest;
|
| 7 |
+
import java.util.ArrayDeque;
|
| 8 |
+
import java.util.ArrayList;
|
| 9 |
+
import java.util.Base64;
|
| 10 |
+
import java.util.Collections;
|
| 11 |
+
import java.util.HashMap;
|
| 12 |
+
import java.util.HashSet;
|
| 13 |
+
import java.util.LinkedHashMap;
|
| 14 |
+
import java.util.List;
|
| 15 |
+
import java.util.Map;
|
| 16 |
+
import java.util.Queue;
|
| 17 |
+
import java.util.Set;
|
| 18 |
+
|
| 19 |
+
import org.glycoinfo.WURCSFramework.util.array.WURCSImporter;
|
| 20 |
+
import org.glycoinfo.WURCSFramework.wurcs.array.GLIP;
|
| 21 |
+
import org.glycoinfo.WURCSFramework.wurcs.array.GLIPs;
|
| 22 |
+
import org.glycoinfo.WURCSFramework.wurcs.array.LIN;
|
| 23 |
+
import org.glycoinfo.WURCSFramework.wurcs.array.RES;
|
| 24 |
+
import org.glycoinfo.WURCSFramework.wurcs.array.UniqueRES;
|
| 25 |
+
import org.glycoinfo.WURCSFramework.wurcs.array.WURCSArray;
|
| 26 |
+
|
| 27 |
+
/**
|
| 28 |
+
* Original-axis official WURCS adjudicator.
|
| 29 |
+
*
|
| 30 |
+
* <p>This helper deliberately uses WURCSImporter/WURCSArray rather than a
|
| 31 |
+
* normalized WURCSGraph. RES list order is the sequence residue axis and
|
| 32 |
+
* every GLIP carries its explicit RESIndex, so no normalized-backbone
|
| 33 |
+
* permutation is applied to depth or topology targets.</p>
|
| 34 |
+
*/
|
| 35 |
+
public final class A5WurcsArrayTreeAudit {
|
| 36 |
+
private A5WurcsArrayTreeAudit() {}
|
| 37 |
+
|
| 38 |
+
private static final Base64.Decoder B64_DECODER = Base64.getUrlDecoder();
|
| 39 |
+
private static final Base64.Encoder B64_ENCODER =
|
| 40 |
+
Base64.getUrlEncoder().withoutPadding();
|
| 41 |
+
|
| 42 |
+
private static String b64(String value) {
|
| 43 |
+
return B64_ENCODER.encodeToString(value.getBytes(StandardCharsets.UTF_8));
|
| 44 |
+
}
|
| 45 |
+
|
| 46 |
+
private static String sha256(String value) throws Exception {
|
| 47 |
+
byte[] digest = MessageDigest.getInstance("SHA-256")
|
| 48 |
+
.digest(value.getBytes(StandardCharsets.UTF_8));
|
| 49 |
+
StringBuilder result = new StringBuilder(64);
|
| 50 |
+
for (byte item : digest) {
|
| 51 |
+
result.append(String.format("%02x", item & 0xff));
|
| 52 |
+
}
|
| 53 |
+
return result.toString();
|
| 54 |
+
}
|
| 55 |
+
|
| 56 |
+
private static boolean probabilityIsExact(GLIP linkage) {
|
| 57 |
+
return linkage.getBackboneProbabilityLower() == 1.0
|
| 58 |
+
&& linkage.getBackboneProbabilityUpper() == 1.0
|
| 59 |
+
&& linkage.getModificationProbabilityLower() == 1.0
|
| 60 |
+
&& linkage.getModificationProbabilityUpper() == 1.0;
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
+
private static String pairKey(int left, int right) {
|
| 64 |
+
return Math.min(left, right) + ":" + Math.max(left, right);
|
| 65 |
+
}
|
| 66 |
+
|
| 67 |
+
private static String process(String rowIndex, String wurcs) throws Exception {
|
| 68 |
+
WURCSImporter importer = new WURCSImporter();
|
| 69 |
+
WURCSArray array = importer.extractWURCSArray(wurcs);
|
| 70 |
+
List<RES> residues = array.getRESs();
|
| 71 |
+
List<UniqueRES> uniqueResidues = array.getUniqueRESs();
|
| 72 |
+
List<LIN> linkages = array.getLINs();
|
| 73 |
+
int residueCount = residues.size();
|
| 74 |
+
if (residueCount == 0
|
| 75 |
+
|| residueCount != array.getRESCount()
|
| 76 |
+
|| linkages.size() != array.getLINCount()
|
| 77 |
+
|| uniqueResidues.size() != array.getUniqueRESCount()) {
|
| 78 |
+
throw new IllegalStateException("official WURCSArray cardinality mismatch");
|
| 79 |
+
}
|
| 80 |
+
|
| 81 |
+
Map<String, Integer> residueIndex = new LinkedHashMap<>();
|
| 82 |
+
int[] anomericPositions = new int[residueCount];
|
| 83 |
+
List<String> residueLabels = new ArrayList<>();
|
| 84 |
+
List<String> uniqueIds = new ArrayList<>();
|
| 85 |
+
for (int index = 0; index < residueCount; index++) {
|
| 86 |
+
RES residue = residues.get(index);
|
| 87 |
+
String label = residue.getRESIndex();
|
| 88 |
+
if (label == null || label.isEmpty()
|
| 89 |
+
|| residueIndex.put(label, index) != null) {
|
| 90 |
+
throw new IllegalStateException(
|
| 91 |
+
"official RES indices are blank or duplicated"
|
| 92 |
+
);
|
| 93 |
+
}
|
| 94 |
+
int uniqueId = residue.getUniqueRESID();
|
| 95 |
+
if (uniqueId < 1 || uniqueId > uniqueResidues.size()) {
|
| 96 |
+
throw new IllegalStateException(
|
| 97 |
+
"official RES references an invalid UniqueRES"
|
| 98 |
+
);
|
| 99 |
+
}
|
| 100 |
+
anomericPositions[index] =
|
| 101 |
+
uniqueResidues.get(uniqueId - 1).getAnomericPosition();
|
| 102 |
+
residueLabels.add(label);
|
| 103 |
+
uniqueIds.add(Integer.toString(uniqueId));
|
| 104 |
+
}
|
| 105 |
+
|
| 106 |
+
List<Set<Integer>> adjacency = new ArrayList<>();
|
| 107 |
+
List<List<Integer>> directedChildren = new ArrayList<>();
|
| 108 |
+
for (int index = 0; index < residueCount; index++) {
|
| 109 |
+
adjacency.add(new HashSet<>());
|
| 110 |
+
directedChildren.add(new ArrayList<>());
|
| 111 |
+
}
|
| 112 |
+
Map<Integer, Integer> childParent = new HashMap<>();
|
| 113 |
+
Set<String> seenPairs = new HashSet<>();
|
| 114 |
+
List<String> pairRecords = new ArrayList<>();
|
| 115 |
+
int connectorCount = 0;
|
| 116 |
+
int monovalentCount = 0;
|
| 117 |
+
int repeatCount = 0;
|
| 118 |
+
int alternativeGroupCount = 0;
|
| 119 |
+
int residueIdentityAmbiguousGroupCount = 0;
|
| 120 |
+
int sameResidueAlternativeGroupCount = 0;
|
| 121 |
+
int groupedPositionGroupCount = 0;
|
| 122 |
+
int probabilityEndpointCount = 0;
|
| 123 |
+
int unknownBackbonePositionCount = 0;
|
| 124 |
+
int unknownModificationPositionCount = 0;
|
| 125 |
+
int unknownDirectionCount = 0;
|
| 126 |
+
int mapConnectorCount = 0;
|
| 127 |
+
int hyperedgeCount = 0;
|
| 128 |
+
int duplicatePairCount = 0;
|
| 129 |
+
int orientationFailureCount = 0;
|
| 130 |
+
int groupedOrientationNonInvariantCount = 0;
|
| 131 |
+
String topologyBlocker = "";
|
| 132 |
+
String rootedBlocker = "";
|
| 133 |
+
StringBuilder serialization = new StringBuilder();
|
| 134 |
+
|
| 135 |
+
if (array.isComposition()) {
|
| 136 |
+
topologyBlocker = "official_composition_record";
|
| 137 |
+
}
|
| 138 |
+
|
| 139 |
+
for (int linkageIndex = 0;
|
| 140 |
+
linkageIndex < linkages.size();
|
| 141 |
+
linkageIndex++) {
|
| 142 |
+
LIN linkage = linkages.get(linkageIndex);
|
| 143 |
+
if (linkage.isRepeatingUnit()) {
|
| 144 |
+
repeatCount++;
|
| 145 |
+
}
|
| 146 |
+
Map<Integer, List<GLIP>> byResidue = new LinkedHashMap<>();
|
| 147 |
+
boolean groupIdentityUncertain = false;
|
| 148 |
+
boolean connectorProbability = false;
|
| 149 |
+
for (GLIPs group : linkage.getListOfGLIPs()) {
|
| 150 |
+
boolean officialAlternative =
|
| 151 |
+
group.getAlternativeType() != null;
|
| 152 |
+
if (officialAlternative) {
|
| 153 |
+
alternativeGroupCount++;
|
| 154 |
+
}
|
| 155 |
+
if (group.getGLIPs().size() > 1) {
|
| 156 |
+
groupedPositionGroupCount++;
|
| 157 |
+
}
|
| 158 |
+
Set<Integer> groupResidues = new HashSet<>();
|
| 159 |
+
for (GLIP endpoint : group.getGLIPs()) {
|
| 160 |
+
Integer index = residueIndex.get(endpoint.getRESIndex());
|
| 161 |
+
if (index == null) {
|
| 162 |
+
throw new IllegalStateException(
|
| 163 |
+
"official GLIP references an unknown RESIndex"
|
| 164 |
+
);
|
| 165 |
+
}
|
| 166 |
+
groupResidues.add(index);
|
| 167 |
+
byResidue.computeIfAbsent(
|
| 168 |
+
index, ignored -> new ArrayList<>()
|
| 169 |
+
).add(endpoint);
|
| 170 |
+
if (!probabilityIsExact(endpoint)) {
|
| 171 |
+
probabilityEndpointCount++;
|
| 172 |
+
connectorProbability = true;
|
| 173 |
+
}
|
| 174 |
+
if (endpoint.getBackbonePosition() < 1) {
|
| 175 |
+
unknownBackbonePositionCount++;
|
| 176 |
+
}
|
| 177 |
+
if (endpoint.getModificationPosition() < 0) {
|
| 178 |
+
unknownModificationPositionCount++;
|
| 179 |
+
}
|
| 180 |
+
char direction = endpoint.getBackboneDirection();
|
| 181 |
+
if (direction == '?' || direction == 'x'
|
| 182 |
+
|| direction == 'X') {
|
| 183 |
+
unknownDirectionCount++;
|
| 184 |
+
}
|
| 185 |
+
}
|
| 186 |
+
if (groupResidues.size() != 1) {
|
| 187 |
+
groupIdentityUncertain = true;
|
| 188 |
+
residueIdentityAmbiguousGroupCount++;
|
| 189 |
+
} else if (officialAlternative) {
|
| 190 |
+
/*
|
| 191 |
+
* Official ``{``/``}`` marks an alternative lead-out or
|
| 192 |
+
* lead-in GLIPs group. It does not by itself make the
|
| 193 |
+
* residue identity uncertain. If every endpoint in the
|
| 194 |
+
* group names the same RES, undirected residue adjacency
|
| 195 |
+
* remains exact; only attachment chemistry and, unless
|
| 196 |
+
* every endpoint has the same donor status, rooting are
|
| 197 |
+
* uncertain.
|
| 198 |
+
*/
|
| 199 |
+
sameResidueAlternativeGroupCount++;
|
| 200 |
+
}
|
| 201 |
+
}
|
| 202 |
+
|
| 203 |
+
int degree = byResidue.size();
|
| 204 |
+
if (degree <= 1) {
|
| 205 |
+
monovalentCount++;
|
| 206 |
+
if (linkage.isRepeatingUnit() && topologyBlocker.isEmpty()) {
|
| 207 |
+
topologyBlocker = "official_repeat_record";
|
| 208 |
+
}
|
| 209 |
+
continue;
|
| 210 |
+
}
|
| 211 |
+
if (linkage.isRepeatingUnit() && topologyBlocker.isEmpty()) {
|
| 212 |
+
topologyBlocker = "official_repeat_connector";
|
| 213 |
+
}
|
| 214 |
+
if (groupIdentityUncertain && topologyBlocker.isEmpty()) {
|
| 215 |
+
topologyBlocker = "residue_identity_ambiguous_connector";
|
| 216 |
+
}
|
| 217 |
+
if (degree != 2) {
|
| 218 |
+
hyperedgeCount++;
|
| 219 |
+
if (topologyBlocker.isEmpty()) {
|
| 220 |
+
topologyBlocker = "connector_residue_degree_not_two";
|
| 221 |
+
}
|
| 222 |
+
continue;
|
| 223 |
+
}
|
| 224 |
+
if (connectorProbability && topologyBlocker.isEmpty()) {
|
| 225 |
+
topologyBlocker = "probabilistic_connector_endpoint";
|
| 226 |
+
}
|
| 227 |
+
|
| 228 |
+
List<Integer> linked = new ArrayList<>(byResidue.keySet());
|
| 229 |
+
Collections.sort(linked);
|
| 230 |
+
int left = linked.get(0);
|
| 231 |
+
int right = linked.get(1);
|
| 232 |
+
String pair = pairKey(left, right);
|
| 233 |
+
pairRecords.add(left + "-" + right);
|
| 234 |
+
connectorCount++;
|
| 235 |
+
if (!seenPairs.add(pair)) {
|
| 236 |
+
duplicatePairCount++;
|
| 237 |
+
if (topologyBlocker.isEmpty()) {
|
| 238 |
+
topologyBlocker = "duplicate_residue_pair_connector";
|
| 239 |
+
}
|
| 240 |
+
}
|
| 241 |
+
adjacency.get(left).add(right);
|
| 242 |
+
adjacency.get(right).add(left);
|
| 243 |
+
String mapCode = linkage.getMAPCode();
|
| 244 |
+
if (mapCode != null && !mapCode.isEmpty()) {
|
| 245 |
+
mapConnectorCount++;
|
| 246 |
+
}
|
| 247 |
+
|
| 248 |
+
Map<Integer, Boolean> donorByResidue = new HashMap<>();
|
| 249 |
+
boolean orientationConsistent = true;
|
| 250 |
+
for (int residue : linked) {
|
| 251 |
+
Boolean donor = null;
|
| 252 |
+
boolean grouped = byResidue.get(residue).size() > 1;
|
| 253 |
+
for (GLIP endpoint : byResidue.get(residue)) {
|
| 254 |
+
int position = endpoint.getBackbonePosition();
|
| 255 |
+
int anomeric = anomericPositions[residue];
|
| 256 |
+
if (position < 1 || anomeric < 0) {
|
| 257 |
+
orientationConsistent = false;
|
| 258 |
+
continue;
|
| 259 |
+
}
|
| 260 |
+
boolean endpointDonor = anomeric > 0
|
| 261 |
+
&& position == anomeric;
|
| 262 |
+
if (donor != null
|
| 263 |
+
&& donor.booleanValue() != endpointDonor) {
|
| 264 |
+
orientationConsistent = false;
|
| 265 |
+
if (grouped) {
|
| 266 |
+
groupedOrientationNonInvariantCount++;
|
| 267 |
+
}
|
| 268 |
+
}
|
| 269 |
+
donor = endpointDonor;
|
| 270 |
+
}
|
| 271 |
+
if (donor == null) {
|
| 272 |
+
orientationConsistent = false;
|
| 273 |
+
} else {
|
| 274 |
+
donorByResidue.put(residue, donor);
|
| 275 |
+
}
|
| 276 |
+
}
|
| 277 |
+
boolean leftDonor = Boolean.TRUE.equals(donorByResidue.get(left));
|
| 278 |
+
boolean rightDonor = Boolean.TRUE.equals(donorByResidue.get(right));
|
| 279 |
+
if (!orientationConsistent || leftDonor == rightDonor) {
|
| 280 |
+
orientationFailureCount++;
|
| 281 |
+
if (rootedBlocker.isEmpty()) {
|
| 282 |
+
rootedBlocker = "official_donor_not_unique";
|
| 283 |
+
}
|
| 284 |
+
} else {
|
| 285 |
+
int child = leftDonor ? left : right;
|
| 286 |
+
int parent = leftDonor ? right : left;
|
| 287 |
+
Integer previous = childParent.putIfAbsent(child, parent);
|
| 288 |
+
if (previous != null && previous.intValue() != parent) {
|
| 289 |
+
orientationFailureCount++;
|
| 290 |
+
if (rootedBlocker.isEmpty()) {
|
| 291 |
+
rootedBlocker = "residue_has_multiple_parents";
|
| 292 |
+
}
|
| 293 |
+
}
|
| 294 |
+
directedChildren.get(parent).add(child);
|
| 295 |
+
}
|
| 296 |
+
serialization.append(linkageIndex).append(':')
|
| 297 |
+
.append(left).append('-').append(right).append(':')
|
| 298 |
+
.append(leftDonor).append('-').append(rightDonor).append(':')
|
| 299 |
+
.append(mapCode == null ? "NULL" : mapCode).append('\n');
|
| 300 |
+
}
|
| 301 |
+
|
| 302 |
+
if (repeatCount > 0 && topologyBlocker.isEmpty()) {
|
| 303 |
+
topologyBlocker = "official_repeat_record";
|
| 304 |
+
}
|
| 305 |
+
if (connectorCount != residueCount - 1 && topologyBlocker.isEmpty()) {
|
| 306 |
+
topologyBlocker = "edge_count_not_residue_count_minus_one";
|
| 307 |
+
}
|
| 308 |
+
|
| 309 |
+
Set<Integer> visited = new HashSet<>();
|
| 310 |
+
Queue<Integer> queue = new ArrayDeque<>();
|
| 311 |
+
visited.add(0);
|
| 312 |
+
queue.add(0);
|
| 313 |
+
while (!queue.isEmpty()) {
|
| 314 |
+
int current = queue.remove();
|
| 315 |
+
for (int neighbor : adjacency.get(current)) {
|
| 316 |
+
if (visited.add(neighbor)) {
|
| 317 |
+
queue.add(neighbor);
|
| 318 |
+
}
|
| 319 |
+
}
|
| 320 |
+
}
|
| 321 |
+
boolean connected = visited.size() == residueCount;
|
| 322 |
+
if (!connected && topologyBlocker.isEmpty()) {
|
| 323 |
+
topologyBlocker = "residue_graph_disconnected";
|
| 324 |
+
}
|
| 325 |
+
boolean exactUndirectedTree = topologyBlocker.isEmpty();
|
| 326 |
+
|
| 327 |
+
List<Integer> depths = new ArrayList<>();
|
| 328 |
+
int maxDepth = -1;
|
| 329 |
+
if (!exactUndirectedTree && rootedBlocker.isEmpty()) {
|
| 330 |
+
rootedBlocker = topologyBlocker;
|
| 331 |
+
}
|
| 332 |
+
if (rootedBlocker.isEmpty()) {
|
| 333 |
+
Set<Integer> roots = new HashSet<>();
|
| 334 |
+
for (int index = 0; index < residueCount; index++) {
|
| 335 |
+
if (!childParent.containsKey(index)) {
|
| 336 |
+
roots.add(index);
|
| 337 |
+
}
|
| 338 |
+
}
|
| 339 |
+
if (roots.size() != 1) {
|
| 340 |
+
rootedBlocker = "root_not_unique";
|
| 341 |
+
} else {
|
| 342 |
+
int[] values = new int[residueCount];
|
| 343 |
+
for (int index = 0; index < residueCount; index++) {
|
| 344 |
+
values[index] = -1;
|
| 345 |
+
}
|
| 346 |
+
int root = roots.iterator().next();
|
| 347 |
+
values[root] = 0;
|
| 348 |
+
queue.clear();
|
| 349 |
+
queue.add(root);
|
| 350 |
+
while (!queue.isEmpty() && rootedBlocker.isEmpty()) {
|
| 351 |
+
int parent = queue.remove();
|
| 352 |
+
for (int child : directedChildren.get(parent)) {
|
| 353 |
+
if (values[child] >= 0) {
|
| 354 |
+
rootedBlocker = "directed_cycle_or_duplicate_child";
|
| 355 |
+
break;
|
| 356 |
+
}
|
| 357 |
+
values[child] = values[parent] + 1;
|
| 358 |
+
queue.add(child);
|
| 359 |
+
}
|
| 360 |
+
}
|
| 361 |
+
for (int value : values) {
|
| 362 |
+
if (value < 0 && rootedBlocker.isEmpty()) {
|
| 363 |
+
rootedBlocker = "directed_tree_disconnected";
|
| 364 |
+
}
|
| 365 |
+
depths.add(value);
|
| 366 |
+
maxDepth = Math.max(maxDepth, value);
|
| 367 |
+
}
|
| 368 |
+
}
|
| 369 |
+
}
|
| 370 |
+
boolean exactRootedTree = exactUndirectedTree && rootedBlocker.isEmpty();
|
| 371 |
+
if (!exactRootedTree) {
|
| 372 |
+
depths.clear();
|
| 373 |
+
maxDepth = -1;
|
| 374 |
+
}
|
| 375 |
+
StringBuilder depthText = new StringBuilder();
|
| 376 |
+
for (int index = 0; index < depths.size(); index++) {
|
| 377 |
+
if (index > 0) {
|
| 378 |
+
depthText.append(',');
|
| 379 |
+
}
|
| 380 |
+
depthText.append(depths.get(index));
|
| 381 |
+
}
|
| 382 |
+
Collections.sort(pairRecords);
|
| 383 |
+
String pairText = exactUndirectedTree
|
| 384 |
+
? String.join(",", pairRecords) : "";
|
| 385 |
+
StringBuilder parentText = new StringBuilder();
|
| 386 |
+
if (exactRootedTree) {
|
| 387 |
+
for (int index = 0; index < residueCount; index++) {
|
| 388 |
+
if (index > 0) {
|
| 389 |
+
parentText.append(',');
|
| 390 |
+
}
|
| 391 |
+
parentText.append(childParent.getOrDefault(index, -1));
|
| 392 |
+
}
|
| 393 |
+
}
|
| 394 |
+
String residueOrder = String.join(",", residueLabels);
|
| 395 |
+
String uniqueOrder = String.join(",", uniqueIds);
|
| 396 |
+
String axisProof = residueOrder + "\n" + uniqueOrder;
|
| 397 |
+
|
| 398 |
+
return String.join("\t",
|
| 399 |
+
rowIndex,
|
| 400 |
+
"OK",
|
| 401 |
+
Integer.toString(residueCount),
|
| 402 |
+
Integer.toString(linkages.size()),
|
| 403 |
+
Integer.toString(connectorCount),
|
| 404 |
+
Integer.toString(monovalentCount),
|
| 405 |
+
Integer.toString(repeatCount),
|
| 406 |
+
Integer.toString(alternativeGroupCount),
|
| 407 |
+
Integer.toString(groupedPositionGroupCount),
|
| 408 |
+
Integer.toString(probabilityEndpointCount),
|
| 409 |
+
Integer.toString(unknownBackbonePositionCount),
|
| 410 |
+
Integer.toString(unknownModificationPositionCount),
|
| 411 |
+
Integer.toString(unknownDirectionCount),
|
| 412 |
+
Integer.toString(mapConnectorCount),
|
| 413 |
+
Integer.toString(hyperedgeCount),
|
| 414 |
+
Integer.toString(duplicatePairCount),
|
| 415 |
+
Integer.toString(orientationFailureCount),
|
| 416 |
+
Integer.toString(groupedOrientationNonInvariantCount),
|
| 417 |
+
Boolean.toString(connected),
|
| 418 |
+
Boolean.toString(exactUndirectedTree),
|
| 419 |
+
Boolean.toString(exactRootedTree),
|
| 420 |
+
b64(topologyBlocker),
|
| 421 |
+
b64(rootedBlocker),
|
| 422 |
+
Integer.toString(maxDepth),
|
| 423 |
+
b64(depthText.toString()),
|
| 424 |
+
b64(pairText),
|
| 425 |
+
b64(parentText.toString()),
|
| 426 |
+
b64(residueOrder),
|
| 427 |
+
b64(uniqueOrder),
|
| 428 |
+
sha256(serialization.toString()),
|
| 429 |
+
sha256(wurcs),
|
| 430 |
+
sha256(axisProof),
|
| 431 |
+
Integer.toString(residueIdentityAmbiguousGroupCount),
|
| 432 |
+
Integer.toString(sameResidueAlternativeGroupCount)
|
| 433 |
+
);
|
| 434 |
+
}
|
| 435 |
+
|
| 436 |
+
public static void main(String[] args) throws Exception {
|
| 437 |
+
try (BufferedReader reader = new BufferedReader(
|
| 438 |
+
new InputStreamReader(System.in, StandardCharsets.UTF_8)
|
| 439 |
+
)) {
|
| 440 |
+
String line;
|
| 441 |
+
while ((line = reader.readLine()) != null) {
|
| 442 |
+
if (line.isEmpty()) {
|
| 443 |
+
continue;
|
| 444 |
+
}
|
| 445 |
+
String[] fields = line.split("\t", -1);
|
| 446 |
+
String rowIndex = fields.length > 0 ? fields[0] : "";
|
| 447 |
+
try {
|
| 448 |
+
if (fields.length != 2 || rowIndex.isEmpty()) {
|
| 449 |
+
throw new IllegalArgumentException(
|
| 450 |
+
"input must be row_index and base64 WURCS"
|
| 451 |
+
);
|
| 452 |
+
}
|
| 453 |
+
String wurcs = new String(
|
| 454 |
+
B64_DECODER.decode(fields[1]), StandardCharsets.UTF_8
|
| 455 |
+
);
|
| 456 |
+
System.out.println(process(rowIndex, wurcs));
|
| 457 |
+
} catch (Exception error) {
|
| 458 |
+
String message = error.getClass().getName() + ": "
|
| 459 |
+
+ error.getMessage();
|
| 460 |
+
System.out.println(
|
| 461 |
+
rowIndex + "\tERROR\t" + b64(message)
|
| 462 |
+
);
|
| 463 |
+
}
|
| 464 |
+
}
|
| 465 |
+
}
|
| 466 |
+
}
|
| 467 |
+
}
|
releases/2026-10-02/iar_completion/runtime_snapshot/java/review_MolWURCS.jar
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:bc38e44e66daed7ec04f7c7907a13509aac125a8a09c97d9972725ab4278edaf
|
| 3 |
+
size 4019920
|
releases/2026-10-02/iar_completion/runtime_snapshot/java/review_wurcsframework-1.3.1.jar
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:5449f9276a7b952adf087468c874bb13c7295062cce7d1afb13fdea78ace7f37
|
| 3 |
+
size 340319
|
releases/2026-10-02/iar_completion/runtime_snapshot/project/bert_training_v4/downstream_tasks/utils/wurcs_bpe_tokenizer.py
ADDED
|
@@ -0,0 +1,740 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""
|
| 3 |
+
WURCS-BPE Tokenizer
|
| 4 |
+
|
| 5 |
+
A hybrid tokenizer that learns semantic subwords from WURCS while preserving
|
| 6 |
+
the ability to handle rare/novel glycan structures character-by-character.
|
| 7 |
+
|
| 8 |
+
Key features:
|
| 9 |
+
1. Pre-tokenization: Split WURCS into semantic units (residues, linkages, mods)
|
| 10 |
+
2. BPE: Learn subword merges from corpus
|
| 11 |
+
3. Character fallback: Handle novel structures
|
| 12 |
+
4. Tree embeddings: Preserve branch_depth and linkage_type per token
|
| 13 |
+
|
| 14 |
+
Usage:
|
| 15 |
+
# Train BPE on corpus
|
| 16 |
+
tokenizer = WURCSBPETokenizer.train_from_corpus(
|
| 17 |
+
wurcs_strings,
|
| 18 |
+
num_merges=500,
|
| 19 |
+
output_path="bpe_vocabulary.json"
|
| 20 |
+
)
|
| 21 |
+
|
| 22 |
+
# Tokenize
|
| 23 |
+
result = tokenizer.tokenize(wurcs_string)
|
| 24 |
+
"""
|
| 25 |
+
|
| 26 |
+
import json
|
| 27 |
+
import re
|
| 28 |
+
from collections import Counter, defaultdict
|
| 29 |
+
from pathlib import Path
|
| 30 |
+
from typing import Dict, List, Optional, Tuple, Set
|
| 31 |
+
import pickle
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
class WURCSPreTokenizer:
|
| 35 |
+
"""
|
| 36 |
+
Pre-tokenize WURCS into semantic units before BPE.
|
| 37 |
+
|
| 38 |
+
WURCS format: WURCS=2.0/count/[residues]/indices/linkages
|
| 39 |
+
|
| 40 |
+
We split into:
|
| 41 |
+
- Residues: [a2122h-1b_1-5_2*NCC/3=O] -> one unit per []
|
| 42 |
+
- Linkages: a4-b1 -> one unit per linkage
|
| 43 |
+
- Special markers: [BRANCH_OPEN], [BRANCH_CLOSE], etc.
|
| 44 |
+
"""
|
| 45 |
+
|
| 46 |
+
# Residue patterns for common monosaccharides
|
| 47 |
+
RESIDUE_PATTERN = re.compile(r'\[([^\]]+)\]')
|
| 48 |
+
LINKAGE_PATTERN = re.compile(r'([a-z])(\d+|\?)-([a-z])(\d+|\?)')
|
| 49 |
+
|
| 50 |
+
def __init__(self):
|
| 51 |
+
self.special_tokens = {
|
| 52 |
+
'[PAD]': 0,
|
| 53 |
+
'[UNK]': 1,
|
| 54 |
+
'[START]': 2,
|
| 55 |
+
'[END]': 3,
|
| 56 |
+
'[MASK]': 4,
|
| 57 |
+
'[BRANCH_OPEN]': 5,
|
| 58 |
+
'[BRANCH_CLOSE]': 6,
|
| 59 |
+
'[LINK]': 7,
|
| 60 |
+
'[MOD]': 8,
|
| 61 |
+
'[RESIDUE_ERROR]': 9,
|
| 62 |
+
}
|
| 63 |
+
|
| 64 |
+
def pre_tokenize(self, wurcs: str) -> List[Dict]:
|
| 65 |
+
"""
|
| 66 |
+
Pre-tokenize WURCS into semantic units.
|
| 67 |
+
|
| 68 |
+
Returns list of dicts with:
|
| 69 |
+
- text: The unit text
|
| 70 |
+
- type: 'special', 'residue', 'linkage', 'mod', 'index'
|
| 71 |
+
- residue_id: Which residue this belongs to (-1 for special, -2 for linkage)
|
| 72 |
+
- branch_depth: Tree depth (computed later)
|
| 73 |
+
"""
|
| 74 |
+
units = []
|
| 75 |
+
|
| 76 |
+
# Add start token
|
| 77 |
+
units.append({
|
| 78 |
+
'text': '[START]',
|
| 79 |
+
'type': 'special',
|
| 80 |
+
'residue_id': -1,
|
| 81 |
+
'branch_depth': 0,
|
| 82 |
+
'linkage_type': 0,
|
| 83 |
+
})
|
| 84 |
+
|
| 85 |
+
# Parse WURCS sections
|
| 86 |
+
if not wurcs.startswith('WURCS='):
|
| 87 |
+
units.append({'text': '[RESIDUE_ERROR]', 'type': 'special', 'residue_id': -1, 'branch_depth': 0, 'linkage_type': 0})
|
| 88 |
+
units.append({'text': '[END]', 'type': 'special', 'residue_id': -1, 'branch_depth': 0, 'linkage_type': 0})
|
| 89 |
+
return units
|
| 90 |
+
|
| 91 |
+
try:
|
| 92 |
+
parts = self._split_wurcs_sections(wurcs)
|
| 93 |
+
if len(parts) < 4:
|
| 94 |
+
return [{'text': '[ERROR]', 'type': 'special', 'residue_id': -1, 'branch_depth': 0, 'linkage_type': 0}]
|
| 95 |
+
|
| 96 |
+
# parts: WURCS=2.0/3,3,2/[a2122h-1b_1-5][a2122h-1a_1-5][a1122h-1b_1-5]/1-2-3-1/a4-b1_b3-c1_c4-d1
|
| 97 |
+
# section 2: residue definitions
|
| 98 |
+
# section 3: indices
|
| 99 |
+
# section 4: linkages (optional)
|
| 100 |
+
|
| 101 |
+
version = parts[0] # WURCS=2.0
|
| 102 |
+
counts = parts[1] # residue_count,node_count,link_count
|
| 103 |
+
residue_defs = parts[2] # [res1][res2]...
|
| 104 |
+
indices = parts[3] # 1-2-3-1
|
| 105 |
+
linkages = parts[4] if len(parts) > 4 else "" # a4-b1_b3-c1
|
| 106 |
+
|
| 107 |
+
# Parse residue definitions
|
| 108 |
+
residue_list = self.RESIDUE_PATTERN.findall(residue_defs)
|
| 109 |
+
|
| 110 |
+
# Parse linkages to compute branch structure
|
| 111 |
+
linkage_list = linkages.split('_') if linkages else []
|
| 112 |
+
branch_points, residue_depths, linkage_types_map, adj = self._analyze_tree_structure(linkage_list, num_residues=len(residue_list))
|
| 113 |
+
|
| 114 |
+
# Compute distance matrix and cache it based on the linkage string (structure)
|
| 115 |
+
# This is the most expensive part, so we cache it
|
| 116 |
+
if not hasattr(self, '_dist_cache'): self._dist_cache = {}
|
| 117 |
+
if linkages not in self._dist_cache:
|
| 118 |
+
self._dist_cache[linkages] = self._compute_distance_matrix(adj, len(residue_list))
|
| 119 |
+
dist_matrix_raw = self._dist_cache[linkages]
|
| 120 |
+
|
| 121 |
+
# Parse indices to map positions to residue definitions
|
| 122 |
+
index_list = indices.split('-') if indices else []
|
| 123 |
+
|
| 124 |
+
# Process each residue instance
|
| 125 |
+
residue_letter = ord('a')
|
| 126 |
+
for idx, res_idx in enumerate(index_list):
|
| 127 |
+
current_residue_id = idx
|
| 128 |
+
res_letter = chr(residue_letter + idx)
|
| 129 |
+
|
| 130 |
+
# Check if this is a branch point - add branch marker before
|
| 131 |
+
if res_letter in branch_points and branch_points[res_letter] > 0:
|
| 132 |
+
for _ in range(branch_points[res_letter]):
|
| 133 |
+
units.append({
|
| 134 |
+
'text': '[BRANCH_OPEN]',
|
| 135 |
+
'type': 'special',
|
| 136 |
+
'residue_id': -1,
|
| 137 |
+
'branch_depth': residue_depths.get(res_letter, 0),
|
| 138 |
+
'linkage_type': 0,
|
| 139 |
+
})
|
| 140 |
+
|
| 141 |
+
# Get residue definition
|
| 142 |
+
try:
|
| 143 |
+
res_def_idx = int(res_idx) - 1 # 1-indexed to 0-indexed
|
| 144 |
+
res_def = residue_list[res_def_idx] if res_def_idx < len(residue_list) else ""
|
| 145 |
+
except (ValueError, IndexError):
|
| 146 |
+
res_def = ""
|
| 147 |
+
|
| 148 |
+
# Split residue into base and modifications
|
| 149 |
+
res_parts = res_def.split('_')
|
| 150 |
+
base = res_parts[0] if res_parts else res_def
|
| 151 |
+
mods = res_parts[1:] if len(res_parts) > 1 else []
|
| 152 |
+
|
| 153 |
+
# Add residue base as a single unit
|
| 154 |
+
depth = residue_depths.get(res_letter, 0)
|
| 155 |
+
units.append({
|
| 156 |
+
'text': base,
|
| 157 |
+
'type': 'residue',
|
| 158 |
+
'residue_id': current_residue_id,
|
| 159 |
+
'branch_depth': depth,
|
| 160 |
+
'linkage_type': 0,
|
| 161 |
+
})
|
| 162 |
+
|
| 163 |
+
# Add modifications
|
| 164 |
+
for mod in mods:
|
| 165 |
+
units.append({
|
| 166 |
+
'text': mod,
|
| 167 |
+
'type': 'mod',
|
| 168 |
+
'residue_id': current_residue_id,
|
| 169 |
+
'branch_depth': depth,
|
| 170 |
+
'linkage_type': 0,
|
| 171 |
+
})
|
| 172 |
+
|
| 173 |
+
# Store distance matrix in units for easy access in tokenizer
|
| 174 |
+
if units:
|
| 175 |
+
# Find first residue unit or just use START
|
| 176 |
+
units[0]['distance_matrix'] = dist_matrix_raw
|
| 177 |
+
|
| 178 |
+
# Add linkages
|
| 179 |
+
for link in linkage_list:
|
| 180 |
+
if not link:
|
| 181 |
+
continue
|
| 182 |
+
# Parse linkage type
|
| 183 |
+
lt = self._parse_linkage_type(link)
|
| 184 |
+
units.append({
|
| 185 |
+
'text': link,
|
| 186 |
+
'type': 'linkage',
|
| 187 |
+
'residue_id': -2,
|
| 188 |
+
'branch_depth': 0,
|
| 189 |
+
'linkage_type': lt,
|
| 190 |
+
})
|
| 191 |
+
except Exception:
|
| 192 |
+
# Fallback for truly broken WURCS
|
| 193 |
+
pass
|
| 194 |
+
|
| 195 |
+
# Add end token
|
| 196 |
+
units.append({
|
| 197 |
+
'text': '[END]',
|
| 198 |
+
'type': 'special',
|
| 199 |
+
'residue_id': -1,
|
| 200 |
+
'branch_depth': 0,
|
| 201 |
+
'linkage_type': 0,
|
| 202 |
+
})
|
| 203 |
+
|
| 204 |
+
return units
|
| 205 |
+
|
| 206 |
+
def _split_wurcs_sections(self, wurcs: str) -> List[str]:
|
| 207 |
+
"""Split WURCS string into sections, handling nested brackets."""
|
| 208 |
+
# Remove WURCS= prefix
|
| 209 |
+
if wurcs.startswith('WURCS='):
|
| 210 |
+
wurcs = wurcs[6:]
|
| 211 |
+
|
| 212 |
+
sections = []
|
| 213 |
+
current = ""
|
| 214 |
+
bracket_depth = 0
|
| 215 |
+
|
| 216 |
+
for char in wurcs:
|
| 217 |
+
if char == '[':
|
| 218 |
+
bracket_depth += 1
|
| 219 |
+
current += char
|
| 220 |
+
elif char == ']':
|
| 221 |
+
bracket_depth -= 1
|
| 222 |
+
current += char
|
| 223 |
+
elif char == '/' and bracket_depth == 0:
|
| 224 |
+
sections.append(current)
|
| 225 |
+
current = ""
|
| 226 |
+
else:
|
| 227 |
+
current += char
|
| 228 |
+
|
| 229 |
+
if current:
|
| 230 |
+
sections.append(current)
|
| 231 |
+
|
| 232 |
+
return sections
|
| 233 |
+
|
| 234 |
+
def _analyze_tree_structure(self, linkages: List[str], num_residues: int) -> Tuple[Dict, Dict, Dict, Dict]:
|
| 235 |
+
"""Analyze linkages to compute branch points and residue depths."""
|
| 236 |
+
branch_points = defaultdict(int) # residue -> number of children
|
| 237 |
+
children = defaultdict(list)
|
| 238 |
+
all_residues = set()
|
| 239 |
+
linkage_types = {}
|
| 240 |
+
|
| 241 |
+
for link in linkages:
|
| 242 |
+
match = self.LINKAGE_PATTERN.match(link)
|
| 243 |
+
if match:
|
| 244 |
+
from_res, from_pos, to_res, to_pos = match.groups()
|
| 245 |
+
children[from_res].append(to_res)
|
| 246 |
+
all_residues.add(from_res)
|
| 247 |
+
all_residues.add(to_res)
|
| 248 |
+
|
| 249 |
+
# Store linkage type
|
| 250 |
+
linkage_types[link] = self._parse_linkage_type(link)
|
| 251 |
+
|
| 252 |
+
# Build adjacency list for BFS
|
| 253 |
+
adj = defaultdict(list)
|
| 254 |
+
for link in linkages:
|
| 255 |
+
match = self.LINKAGE_PATTERN.match(link)
|
| 256 |
+
if match:
|
| 257 |
+
u = ord(match.group(1)) - ord('a')
|
| 258 |
+
v = ord(match.group(3)) - ord('a')
|
| 259 |
+
if 0 <= u < num_residues and 0 <= v < num_residues:
|
| 260 |
+
adj[u].append(v)
|
| 261 |
+
adj[v].append(u)
|
| 262 |
+
|
| 263 |
+
# Find branch points (residues with >1 child)
|
| 264 |
+
for res, kids in children.items():
|
| 265 |
+
if len(kids) > 1:
|
| 266 |
+
branch_points[res] = len(kids) - 1 # Number of extra branches
|
| 267 |
+
|
| 268 |
+
# Compute depths using BFS
|
| 269 |
+
# Find root (residue with no parent)
|
| 270 |
+
child_set = set()
|
| 271 |
+
for kids in children.values():
|
| 272 |
+
child_set.update(kids)
|
| 273 |
+
roots = all_residues - child_set
|
| 274 |
+
root = min(roots) if roots else 'a'
|
| 275 |
+
|
| 276 |
+
depths = {root: 0}
|
| 277 |
+
queue = [root]
|
| 278 |
+
while queue:
|
| 279 |
+
current = queue.pop(0)
|
| 280 |
+
for child in children.get(current, []):
|
| 281 |
+
if child not in depths:
|
| 282 |
+
depths[child] = depths[current] + 1
|
| 283 |
+
queue.append(child)
|
| 284 |
+
|
| 285 |
+
return branch_points, depths, linkage_types, adj
|
| 286 |
+
|
| 287 |
+
def _compute_distance_matrix(self, adj: Dict[int, List[int]], num_residues: int) -> List[List[int]]:
|
| 288 |
+
"""
|
| 289 |
+
Compute shortest path distance (number of bonds) between all residue pairs using BFS.
|
| 290 |
+
"""
|
| 291 |
+
if num_residues == 0:
|
| 292 |
+
return []
|
| 293 |
+
|
| 294 |
+
dist_matrix = [[-1] * num_residues for _ in range(num_residues)]
|
| 295 |
+
|
| 296 |
+
for i in range(num_residues):
|
| 297 |
+
dist_matrix[i][i] = 0
|
| 298 |
+
queue = [(i, 0)]
|
| 299 |
+
visited = {i}
|
| 300 |
+
|
| 301 |
+
while queue:
|
| 302 |
+
curr, d = queue.pop(0)
|
| 303 |
+
dist_matrix[i][curr] = d
|
| 304 |
+
|
| 305 |
+
for neighbor in adj[curr]:
|
| 306 |
+
if neighbor not in visited:
|
| 307 |
+
visited.add(neighbor)
|
| 308 |
+
queue.append((neighbor, d + 1))
|
| 309 |
+
|
| 310 |
+
return dist_matrix
|
| 311 |
+
|
| 312 |
+
def _compute_distance_matrix_OLD(self, linkages: List[str], num_residues: int) -> List[List[int]]:
|
| 313 |
+
"""
|
| 314 |
+
Compute shortest path distance (number of bonds) between all residue pairs.
|
| 315 |
+
Returns a symmetric N x N matrix where N is num_residues.
|
| 316 |
+
Values are integers (number of steps). 0 on diagonal. -1 if unreachable (shouldn't happen in single tree).
|
| 317 |
+
"""
|
| 318 |
+
if num_residues == 0:
|
| 319 |
+
return []
|
| 320 |
+
|
| 321 |
+
# Initialize adjacency list
|
| 322 |
+
adj = defaultdict(list)
|
| 323 |
+
for link in linkages:
|
| 324 |
+
match = self.LINKAGE_PATTERN.match(link)
|
| 325 |
+
if match:
|
| 326 |
+
# WURCS indices are 1-based letters (a=1, b=2...)
|
| 327 |
+
from_res_char, _, to_res_char, _ = match.groups()
|
| 328 |
+
# Convert char to 0-based index
|
| 329 |
+
u = ord(from_res_char) - ord('a')
|
| 330 |
+
v = ord(to_res_char) - ord('a')
|
| 331 |
+
|
| 332 |
+
# Undirected graph for structural distance
|
| 333 |
+
if 0 <= u < num_residues and 0 <= v < num_residues:
|
| 334 |
+
adj[u].append(v)
|
| 335 |
+
adj[v].append(u)
|
| 336 |
+
|
| 337 |
+
# Compute All-Pairs Shortest Path (BFS from each node is fine for small N)
|
| 338 |
+
# Glycans are small (N ~ 5-20 usually), so O(N^2) BFS is cheap.
|
| 339 |
+
dist_matrix = [[-1] * num_residues for _ in range(num_residues)]
|
| 340 |
+
|
| 341 |
+
for i in range(num_residues):
|
| 342 |
+
dist_matrix[i][i] = 0
|
| 343 |
+
queue = [(i, 0)]
|
| 344 |
+
visited = {i}
|
| 345 |
+
|
| 346 |
+
while queue:
|
| 347 |
+
curr, d = queue.pop(0)
|
| 348 |
+
dist_matrix[i][curr] = d
|
| 349 |
+
|
| 350 |
+
for neighbor in adj[curr]:
|
| 351 |
+
if neighbor not in visited:
|
| 352 |
+
visited.add(neighbor)
|
| 353 |
+
queue.append((neighbor, d + 1))
|
| 354 |
+
|
| 355 |
+
return dist_matrix
|
| 356 |
+
|
| 357 |
+
def _parse_linkage_type(self, link: str) -> int:
|
| 358 |
+
"""Parse linkage string to get type ID."""
|
| 359 |
+
LINKAGE_TYPES = {
|
| 360 |
+
(1, 2): 0, (2, 1): 0,
|
| 361 |
+
(1, 3): 1, (3, 1): 1,
|
| 362 |
+
(1, 4): 2, (4, 1): 2,
|
| 363 |
+
(1, 6): 3, (6, 1): 3,
|
| 364 |
+
(2, 3): 4, (3, 2): 4,
|
| 365 |
+
(2, 6): 5, (6, 2): 5,
|
| 366 |
+
(3, 6): 6, (6, 3): 6,
|
| 367 |
+
}
|
| 368 |
+
|
| 369 |
+
match = self.LINKAGE_PATTERN.match(link)
|
| 370 |
+
if match:
|
| 371 |
+
_, from_pos, _, to_pos = match.groups()
|
| 372 |
+
try:
|
| 373 |
+
pos_tuple = (int(from_pos), int(to_pos))
|
| 374 |
+
return LINKAGE_TYPES.get(pos_tuple, 7)
|
| 375 |
+
except ValueError:
|
| 376 |
+
return 8 # Unknown
|
| 377 |
+
return 8
|
| 378 |
+
|
| 379 |
+
|
| 380 |
+
class WURCSBPETokenizer:
|
| 381 |
+
"""
|
| 382 |
+
BPE tokenizer for WURCS with tree-aware embeddings.
|
| 383 |
+
"""
|
| 384 |
+
|
| 385 |
+
def __init__(self, vocab_path: Optional[str] = None):
|
| 386 |
+
self.pre_tokenizer = WURCSPreTokenizer()
|
| 387 |
+
|
| 388 |
+
# Special tokens (fixed)
|
| 389 |
+
self.special_tokens = self.pre_tokenizer.special_tokens
|
| 390 |
+
|
| 391 |
+
# BPE vocabulary
|
| 392 |
+
self.token_to_id: Dict[str, int] = {}
|
| 393 |
+
self.id_to_token: Dict[int, str] = {}
|
| 394 |
+
self.merges: List[Tuple[str, str]] = []
|
| 395 |
+
|
| 396 |
+
if vocab_path:
|
| 397 |
+
self.load_vocab(vocab_path)
|
| 398 |
+
else:
|
| 399 |
+
# Initialize with special tokens only
|
| 400 |
+
self.token_to_id = dict(self.special_tokens)
|
| 401 |
+
self.id_to_token = {v: k for k, v in self.token_to_id.items()}
|
| 402 |
+
|
| 403 |
+
@classmethod
|
| 404 |
+
def train_from_corpus(
|
| 405 |
+
cls,
|
| 406 |
+
wurcs_strings: List[str],
|
| 407 |
+
num_merges: int = 500,
|
| 408 |
+
output_path: Optional[str] = None,
|
| 409 |
+
min_frequency: int = 2,
|
| 410 |
+
max_token_length: Optional[int] = None,
|
| 411 |
+
) -> 'WURCSBPETokenizer':
|
| 412 |
+
"""
|
| 413 |
+
Train BPE on a corpus of WURCS strings.
|
| 414 |
+
|
| 415 |
+
Args:
|
| 416 |
+
wurcs_strings: List of WURCS strings
|
| 417 |
+
num_merges: Number of BPE merge operations
|
| 418 |
+
output_path: Optional path to save vocabulary
|
| 419 |
+
min_frequency: Minimum frequency for a token to be kept
|
| 420 |
+
max_token_length: Maximum length of a merged token (None = no limit)
|
| 421 |
+
|
| 422 |
+
Returns:
|
| 423 |
+
Trained tokenizer
|
| 424 |
+
"""
|
| 425 |
+
tokenizer = cls()
|
| 426 |
+
pre_tok = WURCSPreTokenizer()
|
| 427 |
+
|
| 428 |
+
print(f"Training BPE on {len(wurcs_strings)} WURCS strings...")
|
| 429 |
+
|
| 430 |
+
# Step 1: Pre-tokenize all strings to get semantic units
|
| 431 |
+
all_units = []
|
| 432 |
+
for wurcs in wurcs_strings:
|
| 433 |
+
units = pre_tok.pre_tokenize(wurcs)
|
| 434 |
+
for unit in units:
|
| 435 |
+
if unit['type'] != 'special':
|
| 436 |
+
all_units.append(unit['text'])
|
| 437 |
+
|
| 438 |
+
# Step 2: Count unit frequencies
|
| 439 |
+
unit_counts = Counter(all_units)
|
| 440 |
+
print(f"Found {len(unit_counts)} unique units")
|
| 441 |
+
|
| 442 |
+
# Step 3: Initialize vocabulary with characters from all units
|
| 443 |
+
char_vocab = set()
|
| 444 |
+
for unit in unit_counts:
|
| 445 |
+
for char in unit:
|
| 446 |
+
char_vocab.add(char)
|
| 447 |
+
|
| 448 |
+
# Build initial vocab: special tokens + characters
|
| 449 |
+
vocab_id = len(tokenizer.special_tokens)
|
| 450 |
+
for char in sorted(char_vocab):
|
| 451 |
+
tokenizer.token_to_id[char] = vocab_id
|
| 452 |
+
tokenizer.id_to_token[vocab_id] = char
|
| 453 |
+
vocab_id += 1
|
| 454 |
+
|
| 455 |
+
print(f"Initial vocab size: {vocab_id} (special + characters)")
|
| 456 |
+
|
| 457 |
+
# Step 4: Convert units to character sequences
|
| 458 |
+
word_freqs = {}
|
| 459 |
+
for unit, count in unit_counts.items():
|
| 460 |
+
if count >= min_frequency:
|
| 461 |
+
# Split into characters with space separator
|
| 462 |
+
chars = tuple(unit)
|
| 463 |
+
word_freqs[chars] = count
|
| 464 |
+
|
| 465 |
+
# Step 5: BPE merging
|
| 466 |
+
merges = []
|
| 467 |
+
|
| 468 |
+
for merge_idx in range(num_merges):
|
| 469 |
+
# Count pairs
|
| 470 |
+
pair_counts = Counter()
|
| 471 |
+
for word, freq in word_freqs.items():
|
| 472 |
+
for i in range(len(word) - 1):
|
| 473 |
+
pair = (word[i], word[i + 1])
|
| 474 |
+
pair_counts[pair] += freq
|
| 475 |
+
|
| 476 |
+
if not pair_counts:
|
| 477 |
+
break
|
| 478 |
+
|
| 479 |
+
# Find most frequent pair
|
| 480 |
+
best_pair = pair_counts.most_common(1)[0][0]
|
| 481 |
+
best_count = pair_counts[best_pair]
|
| 482 |
+
|
| 483 |
+
if best_count < min_frequency:
|
| 484 |
+
break
|
| 485 |
+
|
| 486 |
+
# Merge pair
|
| 487 |
+
new_token = best_pair[0] + best_pair[1]
|
| 488 |
+
|
| 489 |
+
# Check length constraint
|
| 490 |
+
if max_token_length and len(new_token) > max_token_length:
|
| 491 |
+
# remove this pair from consideration for this iteration and future?
|
| 492 |
+
# Actually, skipping it here is tricky because we need to ignore it in pair_counts next time
|
| 493 |
+
# Simpler: Just skip adding it to merges and modify word_freqs?
|
| 494 |
+
# No, if we don't merge, we just continue to the next best pair in THIS iteration.
|
| 495 |
+
# But pair_counts is already computed.
|
| 496 |
+
# We need to loop until we find a valid pair or run out
|
| 497 |
+
|
| 498 |
+
# In this simple implementation, let's just skip this merge efficiently
|
| 499 |
+
# We need to find the NEXT most common pair.
|
| 500 |
+
|
| 501 |
+
# Re-do finding best pair loop
|
| 502 |
+
found_valid_pair = False
|
| 503 |
+
for pair, count in pair_counts.most_common():
|
| 504 |
+
token_candidate = pair[0] + pair[1]
|
| 505 |
+
if max_token_length and len(token_candidate) > max_token_length:
|
| 506 |
+
continue # Skip too long
|
| 507 |
+
|
| 508 |
+
if count < min_frequency:
|
| 509 |
+
break # Stop if frequency too low
|
| 510 |
+
|
| 511 |
+
# Found valid pair
|
| 512 |
+
best_pair = pair
|
| 513 |
+
best_count = count
|
| 514 |
+
new_token = token_candidate
|
| 515 |
+
found_valid_pair = True
|
| 516 |
+
break
|
| 517 |
+
|
| 518 |
+
if not found_valid_pair:
|
| 519 |
+
print(f" Stopping early: No more pairs satisfy max_token_length={max_token_length}")
|
| 520 |
+
break
|
| 521 |
+
|
| 522 |
+
# Final check before merging (in case we didn't enter the if block but updated vars)
|
| 523 |
+
# Actually the logic above handles it. If we entered the block, we either found a new best_pair or broke.
|
| 524 |
+
|
| 525 |
+
merges.append(best_pair)
|
| 526 |
+
|
| 527 |
+
# Add to vocab
|
| 528 |
+
tokenizer.token_to_id[new_token] = vocab_id
|
| 529 |
+
tokenizer.id_to_token[vocab_id] = new_token
|
| 530 |
+
vocab_id += 1
|
| 531 |
+
|
| 532 |
+
# Update word_freqs
|
| 533 |
+
new_word_freqs = {}
|
| 534 |
+
for word, freq in word_freqs.items():
|
| 535 |
+
new_word = []
|
| 536 |
+
i = 0
|
| 537 |
+
while i < len(word):
|
| 538 |
+
if i < len(word) - 1 and word[i] == best_pair[0] and word[i + 1] == best_pair[1]:
|
| 539 |
+
new_word.append(new_token)
|
| 540 |
+
i += 2
|
| 541 |
+
else:
|
| 542 |
+
new_word.append(word[i])
|
| 543 |
+
i += 1
|
| 544 |
+
new_word_freqs[tuple(new_word)] = freq
|
| 545 |
+
word_freqs = new_word_freqs
|
| 546 |
+
|
| 547 |
+
if (merge_idx + 1) % 100 == 0:
|
| 548 |
+
print(f" Merge {merge_idx + 1}/{num_merges}: '{best_pair[0]}' + '{best_pair[1]}' -> '{new_token}' (count={best_count})")
|
| 549 |
+
|
| 550 |
+
tokenizer.merges = merges
|
| 551 |
+
print(f"Final vocab size: {len(tokenizer.token_to_id)}")
|
| 552 |
+
|
| 553 |
+
# Save if requested
|
| 554 |
+
if output_path:
|
| 555 |
+
tokenizer.save_vocab(output_path)
|
| 556 |
+
|
| 557 |
+
return tokenizer
|
| 558 |
+
|
| 559 |
+
def apply_bpe(self, text: str) -> List[str]:
|
| 560 |
+
"""Apply BPE merges to a text string."""
|
| 561 |
+
if text in self.token_to_id:
|
| 562 |
+
return [text]
|
| 563 |
+
|
| 564 |
+
# Split into characters
|
| 565 |
+
tokens = list(text)
|
| 566 |
+
|
| 567 |
+
# Apply merges
|
| 568 |
+
for pair in self.merges:
|
| 569 |
+
new_tokens = []
|
| 570 |
+
i = 0
|
| 571 |
+
while i < len(tokens):
|
| 572 |
+
if i < len(tokens) - 1 and tokens[i] == pair[0] and tokens[i + 1] == pair[1]:
|
| 573 |
+
new_tokens.append(pair[0] + pair[1])
|
| 574 |
+
i += 2
|
| 575 |
+
else:
|
| 576 |
+
new_tokens.append(tokens[i])
|
| 577 |
+
i += 1
|
| 578 |
+
tokens = new_tokens
|
| 579 |
+
|
| 580 |
+
return tokens
|
| 581 |
+
|
| 582 |
+
def tokenize(self, wurcs: str, max_length: int = 256) -> Dict:
|
| 583 |
+
"""
|
| 584 |
+
Tokenize a WURCS string.
|
| 585 |
+
|
| 586 |
+
Returns:
|
| 587 |
+
Dict with:
|
| 588 |
+
- tokens: List of token strings
|
| 589 |
+
- token_ids: List of token IDs
|
| 590 |
+
- residue_ids: List of residue IDs
|
| 591 |
+
- branch_depths: List of branch depths
|
| 592 |
+
- linkage_types: List of linkage types
|
| 593 |
+
- attention_mask: Attention mask
|
| 594 |
+
"""
|
| 595 |
+
# Pre-tokenize
|
| 596 |
+
units = self.pre_tokenizer.pre_tokenize(wurcs)
|
| 597 |
+
|
| 598 |
+
tokens = []
|
| 599 |
+
token_ids = []
|
| 600 |
+
residue_ids = []
|
| 601 |
+
branch_depths = []
|
| 602 |
+
linkage_types = []
|
| 603 |
+
|
| 604 |
+
for unit in units:
|
| 605 |
+
if unit['type'] == 'special':
|
| 606 |
+
# Special tokens stay as-is
|
| 607 |
+
tok = unit['text']
|
| 608 |
+
tokens.append(tok)
|
| 609 |
+
token_ids.append(self.token_to_id.get(tok, self.token_to_id['[UNK]']))
|
| 610 |
+
residue_ids.append(unit['residue_id'])
|
| 611 |
+
branch_depths.append(unit['branch_depth'])
|
| 612 |
+
linkage_types.append(unit['linkage_type'])
|
| 613 |
+
else:
|
| 614 |
+
# Apply BPE to this unit
|
| 615 |
+
bpe_tokens = self.apply_bpe(unit['text'])
|
| 616 |
+
for tok in bpe_tokens:
|
| 617 |
+
tokens.append(tok)
|
| 618 |
+
token_ids.append(self.token_to_id.get(tok, self.token_to_id['[UNK]']))
|
| 619 |
+
residue_ids.append(unit['residue_id'])
|
| 620 |
+
branch_depths.append(unit['branch_depth'])
|
| 621 |
+
linkage_types.append(unit['linkage_type'])
|
| 622 |
+
|
| 623 |
+
# Truncate if needed
|
| 624 |
+
if len(tokens) > max_length:
|
| 625 |
+
tokens = tokens[:max_length - 1] + ['[END]']
|
| 626 |
+
token_ids = token_ids[:max_length - 1] + [self.token_to_id['[END]']]
|
| 627 |
+
residue_ids = residue_ids[:max_length - 1] + [-1]
|
| 628 |
+
branch_depths = branch_depths[:max_length - 1] + [0]
|
| 629 |
+
linkage_types = linkage_types[:max_length - 1] + [0]
|
| 630 |
+
|
| 631 |
+
# Create attention mask and pad
|
| 632 |
+
length = len(tokens)
|
| 633 |
+
attention_mask = [1] * length
|
| 634 |
+
|
| 635 |
+
while len(tokens) < max_length:
|
| 636 |
+
tokens.append('[PAD]')
|
| 637 |
+
token_ids.append(self.token_to_id['[PAD]'])
|
| 638 |
+
residue_ids.append(-1)
|
| 639 |
+
branch_depths.append(0)
|
| 640 |
+
linkage_types.append(0)
|
| 641 |
+
attention_mask.append(0)
|
| 642 |
+
# Pre-tokenize
|
| 643 |
+
units = self.pre_tokenizer.pre_tokenize(wurcs)
|
| 644 |
+
|
| 645 |
+
# Extract distance matrix from pre-tokenizer result
|
| 646 |
+
dist_matrix_raw = units[0].get('distance_matrix', [])
|
| 647 |
+
num_residues = len(dist_matrix_raw)
|
| 648 |
+
|
| 649 |
+
# Map token-to-token distances using residue_ids
|
| 650 |
+
# token_i is associated with residue_ids[i].
|
| 651 |
+
# residue_ids[i] is index into dist_matrix_raw.
|
| 652 |
+
# If residue_ids[i] == -1 (special), distance is undefined (use -1 or 999)
|
| 653 |
+
|
| 654 |
+
# Use UNPADDED length for distance matrix to save massive memory
|
| 655 |
+
# distance_matrix will be e.g. 20x20, while tokens are padded to 256
|
| 656 |
+
token_len = length
|
| 657 |
+
distance_matrix = [[-1] * token_len for _ in range(token_len)]
|
| 658 |
+
|
| 659 |
+
for i in range(token_len):
|
| 660 |
+
for j in range(token_len):
|
| 661 |
+
r_i = residue_ids[i]
|
| 662 |
+
r_j = residue_ids[j]
|
| 663 |
+
|
| 664 |
+
if r_i >= 0 and r_j >= 0 and r_i < num_residues and r_j < num_residues:
|
| 665 |
+
distance_matrix[i][j] = dist_matrix_raw[r_i][r_j]
|
| 666 |
+
else:
|
| 667 |
+
distance_matrix[i][j] = -1 # Special/Padding
|
| 668 |
+
|
| 669 |
+
# MEMORY OPTIMIZATION: Do NOT pad matrix here.
|
| 670 |
+
# Pad on-the-fly in Dataset class instead.
|
| 671 |
+
# This saves massive memory (0.2GB vs 66GB).
|
| 672 |
+
|
| 673 |
+
return {
|
| 674 |
+
'tokens': tokens,
|
| 675 |
+
'token_ids': token_ids,
|
| 676 |
+
'residue_ids': residue_ids,
|
| 677 |
+
'branch_depths': branch_depths,
|
| 678 |
+
'linkage_types': linkage_types,
|
| 679 |
+
'attention_mask': attention_mask,
|
| 680 |
+
'distance_matrix': distance_matrix, # New Output
|
| 681 |
+
'length': length,
|
| 682 |
+
}
|
| 683 |
+
|
| 684 |
+
def save_vocab(self, path: str):
|
| 685 |
+
"""Save vocabulary to JSON file."""
|
| 686 |
+
data = {
|
| 687 |
+
'special_tokens': self.special_tokens,
|
| 688 |
+
'token_to_id': self.token_to_id,
|
| 689 |
+
'merges': [list(m) for m in self.merges],
|
| 690 |
+
'metadata': {
|
| 691 |
+
'vocab_size': len(self.token_to_id),
|
| 692 |
+
'num_merges': len(self.merges),
|
| 693 |
+
}
|
| 694 |
+
}
|
| 695 |
+
with open(path, 'w') as f:
|
| 696 |
+
json.dump(data, f, indent=2)
|
| 697 |
+
print(f"Saved vocabulary to {path}")
|
| 698 |
+
|
| 699 |
+
def load_vocab(self, path: str):
|
| 700 |
+
"""Load vocabulary from JSON file."""
|
| 701 |
+
with open(path, 'r') as f:
|
| 702 |
+
data = json.load(f)
|
| 703 |
+
|
| 704 |
+
self.special_tokens = data['special_tokens']
|
| 705 |
+
self.token_to_id = data['token_to_id']
|
| 706 |
+
self.id_to_token = {int(v): k for k, v in self.token_to_id.items()}
|
| 707 |
+
self.merges = [tuple(m) for m in data['merges']]
|
| 708 |
+
|
| 709 |
+
print(f"Loaded vocabulary with {len(self.token_to_id)} tokens")
|
| 710 |
+
|
| 711 |
+
@property
|
| 712 |
+
def vocab_size(self) -> int:
|
| 713 |
+
return len(self.token_to_id)
|
| 714 |
+
|
| 715 |
+
|
| 716 |
+
# ============================================================================
|
| 717 |
+
# Testing
|
| 718 |
+
# ============================================================================
|
| 719 |
+
|
| 720 |
+
if __name__ == '__main__':
|
| 721 |
+
# Test pre-tokenizer
|
| 722 |
+
print("="*80)
|
| 723 |
+
print("Testing WURCSPreTokenizer")
|
| 724 |
+
print("="*80)
|
| 725 |
+
|
| 726 |
+
pre_tok = WURCSPreTokenizer()
|
| 727 |
+
|
| 728 |
+
test_wurcs = [
|
| 729 |
+
"WURCS=2.0/2,2,1/[a2122h-1b_1-5][a2211m-1a_1-5]/1-2/a4-b1",
|
| 730 |
+
"WURCS=2.0/3,3,2/[a2122h-1b_1-5_2*NCC/3=O][a2112h-1a_1-5][a2211m-1a_1-5]/1-2-3/a4-b1_b3-c1",
|
| 731 |
+
]
|
| 732 |
+
|
| 733 |
+
for wurcs in test_wurcs:
|
| 734 |
+
print(f"\nWURCS: {wurcs[:60]}...")
|
| 735 |
+
units = pre_tok.pre_tokenize(wurcs)
|
| 736 |
+
print(f"Units ({len(units)}):")
|
| 737 |
+
for u in units[:10]:
|
| 738 |
+
print(f" {u['type']:10} | res={u['residue_id']:2} | depth={u['branch_depth']} | {u['text']}")
|
| 739 |
+
if len(units) > 10:
|
| 740 |
+
print(f" ... and {len(units) - 10} more")
|
releases/2026-10-02/iar_completion/runtime_snapshot/project/data/bpe_ambiguity_tokens.json
ADDED
|
@@ -0,0 +1,721 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"ambiguous_tokens": {
|
| 3 |
+
"?": 32,
|
| 4 |
+
"?|": 90,
|
| 5 |
+
"a?|": 108,
|
| 6 |
+
"a?|b": 109,
|
| 7 |
+
"?|c": 110,
|
| 8 |
+
"a?|b?|c": 111,
|
| 9 |
+
"?|d": 112,
|
| 10 |
+
"a?|b?|c?|d": 113,
|
| 11 |
+
"?|e": 114,
|
| 12 |
+
"a?|b?|c?|d?|e": 115,
|
| 13 |
+
"?|f": 116,
|
| 14 |
+
"a?|b?|c?|d?|e?|f": 117,
|
| 15 |
+
"?-": 118,
|
| 16 |
+
"?|g": 119,
|
| 17 |
+
"a?|b?|c?|d?|e?|f?|g": 120,
|
| 18 |
+
"?|h": 122,
|
| 19 |
+
"?|i": 123,
|
| 20 |
+
"?|h?|i": 124,
|
| 21 |
+
"?|j": 125,
|
| 22 |
+
"?|h?|i?|j": 126,
|
| 23 |
+
"?|k": 128,
|
| 24 |
+
"?|h?|i?|j?|k": 129,
|
| 25 |
+
"?|l": 130,
|
| 26 |
+
"?|h?|i?|j?|k?|l": 131,
|
| 27 |
+
"?|m": 132,
|
| 28 |
+
"?|h?|i?|j?|k?|l?|m": 133,
|
| 29 |
+
"?|h?|i?|j?|k?|l?|m?|": 138,
|
| 30 |
+
"n?|": 141,
|
| 31 |
+
"n?|o": 142,
|
| 32 |
+
"?}": 143,
|
| 33 |
+
"n?|o?|": 146,
|
| 34 |
+
"n?|o?|p": 147,
|
| 35 |
+
"?}-": 149,
|
| 36 |
+
"?}-{": 150,
|
| 37 |
+
"n?|o?|p?|": 153,
|
| 38 |
+
"n?|o?|p?|q": 154,
|
| 39 |
+
"n?|o?|p?|q?|": 157,
|
| 40 |
+
"n?|o?|p?|q?|r": 158,
|
| 41 |
+
"n?|o?|p?|q?|r?|": 165,
|
| 42 |
+
"n?|o?|p?|q?|r?|s": 166,
|
| 43 |
+
"n?|o?|p?|q?|r?|s?|": 170,
|
| 44 |
+
"n?|o?|p?|q?|r?|s?|t": 171,
|
| 45 |
+
"?|u": 189,
|
| 46 |
+
"a?-": 197,
|
| 47 |
+
"c?-": 201,
|
| 48 |
+
"?|u?|": 209,
|
| 49 |
+
"?|u?|v": 210,
|
| 50 |
+
"b?-": 211,
|
| 51 |
+
"a?-b1": 213,
|
| 52 |
+
"d?-": 217,
|
| 53 |
+
"b?-c1": 221,
|
| 54 |
+
"c?-d1": 230,
|
| 55 |
+
"?|u?|v?|": 231,
|
| 56 |
+
"?|u?|v?|w": 232,
|
| 57 |
+
"1-?": 242,
|
| 58 |
+
"d?-e1": 244,
|
| 59 |
+
"e?-": 245,
|
| 60 |
+
"e?-f1": 262,
|
| 61 |
+
"?|u?|v?|w?|": 266,
|
| 62 |
+
"?|u?|v?|w?|x": 267,
|
| 63 |
+
"f?-": 273,
|
| 64 |
+
"?|u?|v?|w?|x?|": 288,
|
| 65 |
+
"?|u?|v?|w?|x?|y": 289,
|
| 66 |
+
"g?-": 298,
|
| 67 |
+
"n?|o?|p?|q?|r?|s?|t?": 304,
|
| 68 |
+
"i?-": 306,
|
| 69 |
+
"h?-": 308,
|
| 70 |
+
"?|u?}-{": 312,
|
| 71 |
+
"?|u?": 313,
|
| 72 |
+
"n?|o?|p?|q?|r?}-{": 314,
|
| 73 |
+
"n?|o?|p?|q?|r?": 315,
|
| 74 |
+
"f?-g1": 318,
|
| 75 |
+
"n?|o?}-{": 322,
|
| 76 |
+
"n?|o?": 323,
|
| 77 |
+
"?|u?|v?|w?|x?|y?|": 325,
|
| 78 |
+
"?|u?|v?|w?|x?|y?|z": 326,
|
| 79 |
+
"n?|o?|p?|q?|r?|s?}-{": 328,
|
| 80 |
+
"n?|o?|p?|q?|r?|s?": 329,
|
| 81 |
+
"n?|o?|p?}-{": 331,
|
| 82 |
+
"n?|o?|p?": 332,
|
| 83 |
+
"n?|o?|p?|q?}-{": 336,
|
| 84 |
+
"n?|o?|p?|q?": 337,
|
| 85 |
+
"g?-h1": 339,
|
| 86 |
+
"?|h?|i?|j?|k?|l?}-{": 342,
|
| 87 |
+
"?|h?|i?|j?|k?|l?": 343,
|
| 88 |
+
"n?}-{": 344,
|
| 89 |
+
"n?": 345,
|
| 90 |
+
"j?-": 346,
|
| 91 |
+
"h?-i1": 347,
|
| 92 |
+
"?|u?|v?}-{": 351,
|
| 93 |
+
"?|u?|v?": 352,
|
| 94 |
+
"k?-": 353,
|
| 95 |
+
"i?-j1": 355,
|
| 96 |
+
"?|h?|i?|j?|k?|l?|m?": 363,
|
| 97 |
+
"?|h?|i?|j?|k?}-{": 364,
|
| 98 |
+
"?|h?|i?|j?|k?": 365,
|
| 99 |
+
"?|u?|v?|w?|x?|y?|z?|": 369,
|
| 100 |
+
"?|h?|i?|j?}-{": 375,
|
| 101 |
+
"?|h?|i?|j?": 376,
|
| 102 |
+
"l?-": 377,
|
| 103 |
+
"A?|": 392,
|
| 104 |
+
"A?|B": 393,
|
| 105 |
+
"j?-k1": 401,
|
| 106 |
+
"m?-": 404,
|
| 107 |
+
"?|h?|i?}-{": 408,
|
| 108 |
+
"?|h?|i?": 409,
|
| 109 |
+
"k?-l1": 418,
|
| 110 |
+
"?|h?}-{": 420,
|
| 111 |
+
"?|h?": 421,
|
| 112 |
+
"A?|B?|": 424,
|
| 113 |
+
"A?|B?|C": 425,
|
| 114 |
+
"a?|b?|c?|d?|e?|f?|g?": 427,
|
| 115 |
+
"f?-g2": 431,
|
| 116 |
+
"a?|b?|c?|d?|e?|f?}-{": 437,
|
| 117 |
+
"a?|b?|c?|d?|e?|f?": 438,
|
| 118 |
+
"l?-m1": 442,
|
| 119 |
+
"?|u?|v?|w?}-{": 450,
|
| 120 |
+
"?|u?|v?|w?": 451,
|
| 121 |
+
"A?|B?|C?|": 464,
|
| 122 |
+
"A?|B?|C?|D": 465,
|
| 123 |
+
"a?|b?|c?|d?|e?}-{": 475,
|
| 124 |
+
"a?|b?|c?|d?|e?": 476,
|
| 125 |
+
"n?-": 499,
|
| 126 |
+
"a?|b?|c?|d?}-{": 502,
|
| 127 |
+
"a?|b?|c?|d?": 503,
|
| 128 |
+
"m?-n1": 518,
|
| 129 |
+
"A?|B?|C?|D?|": 521,
|
| 130 |
+
"A?|B?|C?|D?|E": 522,
|
| 131 |
+
"o?-": 534,
|
| 132 |
+
"d?-h1": 536,
|
| 133 |
+
"A?|B?|C?|D?|E?|": 542,
|
| 134 |
+
"A?|B?|C?|D?|E?|F": 543,
|
| 135 |
+
"c?-i1": 544,
|
| 136 |
+
"c?-h1": 549,
|
| 137 |
+
"A?|B?|C?|D?|E?|F?|": 550,
|
| 138 |
+
"A?|B?|C?|D?|E?|F?|G": 551,
|
| 139 |
+
"?|u?|v?|w?|x?}-{": 563,
|
| 140 |
+
"?|u?|v?|w?|x?": 564,
|
| 141 |
+
"a?|b?|c?}-{": 571,
|
| 142 |
+
"a?|b?|c?}-{a?|b?|c": 572,
|
| 143 |
+
"a?|b?|c?}-{a?|b?|c?": 573,
|
| 144 |
+
"?|H": 581,
|
| 145 |
+
"2-?": 592,
|
| 146 |
+
"?|H?|": 598,
|
| 147 |
+
"?|H?|I": 599,
|
| 148 |
+
"?}*OC": 600,
|
| 149 |
+
"c?-k1": 607,
|
| 150 |
+
"c?-g1": 609,
|
| 151 |
+
"?|H?|I?|": 615,
|
| 152 |
+
"?|H?|I?|J": 616,
|
| 153 |
+
"n?-o1": 617,
|
| 154 |
+
"d?-g1": 629,
|
| 155 |
+
"o?-p1": 634,
|
| 156 |
+
"p?-": 646,
|
| 157 |
+
"?|u?|v?|w?|x?|y?}-{": 653,
|
| 158 |
+
"?|u?|v?|w?|x?|y?": 654,
|
| 159 |
+
"b?-c2": 656,
|
| 160 |
+
"d?-i1": 658,
|
| 161 |
+
"c?-j1": 691,
|
| 162 |
+
"?}*OSO": 696,
|
| 163 |
+
"e?-h1": 701,
|
| 164 |
+
"q?-": 713,
|
| 165 |
+
"c?-f1": 720,
|
| 166 |
+
"i?-j2": 728,
|
| 167 |
+
"?|h?|i?}": 742,
|
| 168 |
+
"h?-i2": 747,
|
| 169 |
+
"g?-h2": 753,
|
| 170 |
+
"c?-l1": 756,
|
| 171 |
+
"j?-k2": 758,
|
| 172 |
+
"?|h?}": 759,
|
| 173 |
+
"c?-e1": 760,
|
| 174 |
+
"?|H?|I?|J?|": 761,
|
| 175 |
+
"?|H?|I?|J?|K": 762,
|
| 176 |
+
"a?|b?|c?|d?|e?|f?}": 772,
|
| 177 |
+
"b?-e1": 774,
|
| 178 |
+
"b?-f1": 791,
|
| 179 |
+
"d?-f1": 794,
|
| 180 |
+
"p?-q1": 796,
|
| 181 |
+
"a?|b?|c?|d?|e?}": 798,
|
| 182 |
+
"a?-d1": 800,
|
| 183 |
+
"m?-n2": 803,
|
| 184 |
+
"e?-g1": 809,
|
| 185 |
+
"?|h?|i?|j?}": 812,
|
| 186 |
+
"r?-": 817,
|
| 187 |
+
"a?-c1": 818,
|
| 188 |
+
"?|u?|v?|w?|x?|y?|z?": 822,
|
| 189 |
+
"a?-e1": 826,
|
| 190 |
+
"d?-j1": 833,
|
| 191 |
+
"b?-g1": 834,
|
| 192 |
+
"q?-r1": 847,
|
| 193 |
+
"d?-e2": 854,
|
| 194 |
+
"c?-m1": 860,
|
| 195 |
+
"a?-f1": 875,
|
| 196 |
+
"b?-d1": 887,
|
| 197 |
+
"?|H?|I?|J?|K?|": 892,
|
| 198 |
+
"?|H?|I?|J?|K?|L": 893,
|
| 199 |
+
"?|H?|I?|J?|K?|L?|": 894,
|
| 200 |
+
"?|H?|I?|J?|K?|L?|M": 895,
|
| 201 |
+
"?|H?|I?|J?|K?|L?|M?|": 896,
|
| 202 |
+
"a?-l1": 920,
|
| 203 |
+
"?*OSO/3=O/3=O": 923,
|
| 204 |
+
"k?-l2": 940,
|
| 205 |
+
"k?-o1": 942,
|
| 206 |
+
"N?|": 965,
|
| 207 |
+
"N?|O": 966,
|
| 208 |
+
"N?|O?|": 967,
|
| 209 |
+
"N?|O?|P": 968,
|
| 210 |
+
"N?|O?|P?|": 969,
|
| 211 |
+
"N?|O?|P?|Q": 970,
|
| 212 |
+
"N?|O?|P?|Q?|": 971,
|
| 213 |
+
"N?|O?|P?|Q?|R": 972,
|
| 214 |
+
"N?|O?|P?|Q?|R?|": 973,
|
| 215 |
+
"N?|O?|P?|Q?|R?|S": 974,
|
| 216 |
+
"N?|O?|P?|Q?|R?|S?|": 975,
|
| 217 |
+
"N?|O?|P?|Q?|R?|S?|T": 976,
|
| 218 |
+
"?|U": 977,
|
| 219 |
+
"?|U?|": 978,
|
| 220 |
+
"?|U?|V": 979,
|
| 221 |
+
"c?-d2": 983,
|
| 222 |
+
"r?-s1": 988,
|
| 223 |
+
"a?|b?}-{": 995,
|
| 224 |
+
"a?|b?}-{a?|b": 996,
|
| 225 |
+
"a?|b?}-{a?|b?": 997,
|
| 226 |
+
"e?-f2": 1001,
|
| 227 |
+
"g?-i1": 1006,
|
| 228 |
+
"i?-l1": 1010,
|
| 229 |
+
"s?-": 1011,
|
| 230 |
+
"?|h?|i?|j?|k?}": 1017,
|
| 231 |
+
"b?-h1": 1034,
|
| 232 |
+
"a?-j1": 1038,
|
| 233 |
+
"n?-o2": 1046,
|
| 234 |
+
"a?-b2": 1069,
|
| 235 |
+
"e?-i1": 1095,
|
| 236 |
+
"h?-j1": 1102,
|
| 237 |
+
"a?-k1": 1108,
|
| 238 |
+
"i?-k1": 1115,
|
| 239 |
+
"a?-g1": 1116,
|
| 240 |
+
"?}*OPO": 1122,
|
| 241 |
+
"d?-k1": 1129,
|
| 242 |
+
"a?-m1": 1151,
|
| 243 |
+
"a?-i1": 1159,
|
| 244 |
+
"A?}-{": 1174,
|
| 245 |
+
"A?": 1175,
|
| 246 |
+
"?}*OCC": 1177,
|
| 247 |
+
"l?-m2": 1179,
|
| 248 |
+
"A?|B?}-{": 1180,
|
| 249 |
+
"A?|B?": 1181,
|
| 250 |
+
"f?-h1": 1183,
|
| 251 |
+
"a?-n1": 1189,
|
| 252 |
+
"p?-q2": 1192,
|
| 253 |
+
"c?-n1": 1197,
|
| 254 |
+
"?|U?|V?|": 1202,
|
| 255 |
+
"?|U?|V?|W": 1203,
|
| 256 |
+
"?|U?|V?|W?|": 1204,
|
| 257 |
+
"?|U?|V?|W?|X": 1205,
|
| 258 |
+
"?|U?|V?|W?|X?|": 1206,
|
| 259 |
+
"?|U?|V?|W?|X?|Y": 1207,
|
| 260 |
+
"?|a": 1208,
|
| 261 |
+
"s?-t1": 1223,
|
| 262 |
+
"?|h?|i?|j?|k?|l?|m?}": 1228,
|
| 263 |
+
"g?-j1": 1234,
|
| 264 |
+
"A?|B?|C?|D?}-{": 1242,
|
| 265 |
+
"A?|B?|C?|D?": 1243,
|
| 266 |
+
"a?-h1": 1253,
|
| 267 |
+
"?|H?|I?|J?}-{": 1257,
|
| 268 |
+
"?|H?|I?|J?": 1258,
|
| 269 |
+
"o?-p2": 1261,
|
| 270 |
+
"b?-i1": 1273,
|
| 271 |
+
"?|h?|i?|j?|k?|l?}": 1309,
|
| 272 |
+
"j?-m1": 1317,
|
| 273 |
+
"c?-o1": 1318,
|
| 274 |
+
"a?-o1": 1330,
|
| 275 |
+
"a?|b?|c?}*OC": 1331,
|
| 276 |
+
"b?-j1": 1357,
|
| 277 |
+
"a?-r1": 1361,
|
| 278 |
+
"n?}": 1363,
|
| 279 |
+
"A?|B?|C?}-{": 1371,
|
| 280 |
+
"A?|B?|C?": 1372,
|
| 281 |
+
"m?-p1": 1375,
|
| 282 |
+
"l?-p1": 1383,
|
| 283 |
+
"a?-p1": 1444,
|
| 284 |
+
"k?-n1": 1446,
|
| 285 |
+
"j?-l1": 1470,
|
| 286 |
+
"?|U?|V?|W?|X?|Y?|": 1471,
|
| 287 |
+
"?|U?|V?|W?|X?|Y?|Z": 1472,
|
| 288 |
+
"?|aa?|": 1473,
|
| 289 |
+
"?|aa?|a": 1474,
|
| 290 |
+
"?|aa?|ab": 1475,
|
| 291 |
+
"?*OPO/3O/3=O": 1476,
|
| 292 |
+
"l?-q1": 1489,
|
| 293 |
+
"l?-n1": 1499,
|
| 294 |
+
"a?-s1": 1517,
|
| 295 |
+
"k?-m1": 1524,
|
| 296 |
+
"a?-q1": 1546,
|
| 297 |
+
"c?-q1": 1547,
|
| 298 |
+
"t?-": 1551,
|
| 299 |
+
"a?|b?|c?|d?}*OC": 1565,
|
| 300 |
+
"f?-i1": 1590,
|
| 301 |
+
"c?-p1": 1591,
|
| 302 |
+
"n?-q1": 1593,
|
| 303 |
+
"?|i?}": 1611,
|
| 304 |
+
"a?|b?|c?|d?|e?}*OC": 1612,
|
| 305 |
+
"m?-q1": 1617,
|
| 306 |
+
"q?-r2": 1623,
|
| 307 |
+
"l?-o1": 1624,
|
| 308 |
+
"m?-r1": 1628,
|
| 309 |
+
"a?-t1": 1630,
|
| 310 |
+
"a?|b?|c?|d?}*OSO": 1649,
|
| 311 |
+
"c?-r1": 1675,
|
| 312 |
+
"1-d?|i?}": 1683,
|
| 313 |
+
"j?-n1": 1691,
|
| 314 |
+
"u?-": 1694,
|
| 315 |
+
"a?|b?|c?|d?|e?}*OSO": 1718,
|
| 316 |
+
"?*OCC/3=O": 1723,
|
| 317 |
+
"?%": 1752,
|
| 318 |
+
"?*OP^XOCCN/3O/3=O": 1770,
|
| 319 |
+
"t?-u1": 1772,
|
| 320 |
+
"?*": 1774,
|
| 321 |
+
"c?-s1": 1775,
|
| 322 |
+
"a?-u1": 1793,
|
| 323 |
+
"f?-h2": 1808,
|
| 324 |
+
"e?-j1": 1811,
|
| 325 |
+
"c?-t1": 1818,
|
| 326 |
+
"f1-a?|b?|c?|d?|e?}": 1822,
|
| 327 |
+
"u?-v1": 1835,
|
| 328 |
+
"h?-k1": 1841,
|
| 329 |
+
"?|H?|I?|J?|K?}-{": 1846,
|
| 330 |
+
"?|H?|I?|J?|K?": 1847,
|
| 331 |
+
"n?|o?}": 1851,
|
| 332 |
+
"1-d?|h?}": 1852,
|
| 333 |
+
"q?-s1": 1872,
|
| 334 |
+
"%?%": 1880,
|
| 335 |
+
"b?-g2": 1881,
|
| 336 |
+
"r?-s2": 1882,
|
| 337 |
+
"d?-l1": 1898,
|
| 338 |
+
"v?-": 1917,
|
| 339 |
+
"b?-k1": 1927,
|
| 340 |
+
"?|aa?|ab?|a": 1942,
|
| 341 |
+
"?|aa?|ab?|ac": 1943,
|
| 342 |
+
"?|aa?|ab?|ac?|": 1944,
|
| 343 |
+
"?|aa?|ab?|ac?|ad": 1945,
|
| 344 |
+
"a?|b?}*OC": 1949,
|
| 345 |
+
"?*OC": 1952,
|
| 346 |
+
"e?-k1": 1955,
|
| 347 |
+
"a?-d2": 1999,
|
| 348 |
+
"s?-t2": 2013,
|
| 349 |
+
"a?-f2": 2027,
|
| 350 |
+
"o?-q1": 2030,
|
| 351 |
+
"?}*OP^XOCCN": 2040,
|
| 352 |
+
"a?|b?|c?}*OCC": 2047,
|
| 353 |
+
"m?-o1": 2048,
|
| 354 |
+
"c?-f2": 2058,
|
| 355 |
+
"A?|B?|C?|D?|E?|F?|G?": 2060,
|
| 356 |
+
"a?|b?|c?}*OSO": 2071,
|
| 357 |
+
"?|U?|V?}-{": 2079,
|
| 358 |
+
"?|U?|V?": 2080,
|
| 359 |
+
"c?-u1": 2087
|
| 360 |
+
},
|
| 361 |
+
"ambiguous_ids": [
|
| 362 |
+
32,
|
| 363 |
+
90,
|
| 364 |
+
108,
|
| 365 |
+
109,
|
| 366 |
+
110,
|
| 367 |
+
111,
|
| 368 |
+
112,
|
| 369 |
+
113,
|
| 370 |
+
114,
|
| 371 |
+
115,
|
| 372 |
+
116,
|
| 373 |
+
117,
|
| 374 |
+
118,
|
| 375 |
+
119,
|
| 376 |
+
120,
|
| 377 |
+
122,
|
| 378 |
+
123,
|
| 379 |
+
124,
|
| 380 |
+
125,
|
| 381 |
+
126,
|
| 382 |
+
128,
|
| 383 |
+
129,
|
| 384 |
+
130,
|
| 385 |
+
131,
|
| 386 |
+
132,
|
| 387 |
+
133,
|
| 388 |
+
138,
|
| 389 |
+
141,
|
| 390 |
+
142,
|
| 391 |
+
143,
|
| 392 |
+
146,
|
| 393 |
+
147,
|
| 394 |
+
149,
|
| 395 |
+
150,
|
| 396 |
+
153,
|
| 397 |
+
154,
|
| 398 |
+
157,
|
| 399 |
+
158,
|
| 400 |
+
165,
|
| 401 |
+
166,
|
| 402 |
+
170,
|
| 403 |
+
171,
|
| 404 |
+
189,
|
| 405 |
+
197,
|
| 406 |
+
201,
|
| 407 |
+
209,
|
| 408 |
+
210,
|
| 409 |
+
211,
|
| 410 |
+
213,
|
| 411 |
+
217,
|
| 412 |
+
221,
|
| 413 |
+
230,
|
| 414 |
+
231,
|
| 415 |
+
232,
|
| 416 |
+
242,
|
| 417 |
+
244,
|
| 418 |
+
245,
|
| 419 |
+
262,
|
| 420 |
+
266,
|
| 421 |
+
267,
|
| 422 |
+
273,
|
| 423 |
+
288,
|
| 424 |
+
289,
|
| 425 |
+
298,
|
| 426 |
+
304,
|
| 427 |
+
306,
|
| 428 |
+
308,
|
| 429 |
+
312,
|
| 430 |
+
313,
|
| 431 |
+
314,
|
| 432 |
+
315,
|
| 433 |
+
318,
|
| 434 |
+
322,
|
| 435 |
+
323,
|
| 436 |
+
325,
|
| 437 |
+
326,
|
| 438 |
+
328,
|
| 439 |
+
329,
|
| 440 |
+
331,
|
| 441 |
+
332,
|
| 442 |
+
336,
|
| 443 |
+
337,
|
| 444 |
+
339,
|
| 445 |
+
342,
|
| 446 |
+
343,
|
| 447 |
+
344,
|
| 448 |
+
345,
|
| 449 |
+
346,
|
| 450 |
+
347,
|
| 451 |
+
351,
|
| 452 |
+
352,
|
| 453 |
+
353,
|
| 454 |
+
355,
|
| 455 |
+
363,
|
| 456 |
+
364,
|
| 457 |
+
365,
|
| 458 |
+
369,
|
| 459 |
+
375,
|
| 460 |
+
376,
|
| 461 |
+
377,
|
| 462 |
+
392,
|
| 463 |
+
393,
|
| 464 |
+
401,
|
| 465 |
+
404,
|
| 466 |
+
408,
|
| 467 |
+
409,
|
| 468 |
+
418,
|
| 469 |
+
420,
|
| 470 |
+
421,
|
| 471 |
+
424,
|
| 472 |
+
425,
|
| 473 |
+
427,
|
| 474 |
+
431,
|
| 475 |
+
437,
|
| 476 |
+
438,
|
| 477 |
+
442,
|
| 478 |
+
450,
|
| 479 |
+
451,
|
| 480 |
+
464,
|
| 481 |
+
465,
|
| 482 |
+
475,
|
| 483 |
+
476,
|
| 484 |
+
499,
|
| 485 |
+
502,
|
| 486 |
+
503,
|
| 487 |
+
518,
|
| 488 |
+
521,
|
| 489 |
+
522,
|
| 490 |
+
534,
|
| 491 |
+
536,
|
| 492 |
+
542,
|
| 493 |
+
543,
|
| 494 |
+
544,
|
| 495 |
+
549,
|
| 496 |
+
550,
|
| 497 |
+
551,
|
| 498 |
+
563,
|
| 499 |
+
564,
|
| 500 |
+
571,
|
| 501 |
+
572,
|
| 502 |
+
573,
|
| 503 |
+
581,
|
| 504 |
+
592,
|
| 505 |
+
598,
|
| 506 |
+
599,
|
| 507 |
+
600,
|
| 508 |
+
607,
|
| 509 |
+
609,
|
| 510 |
+
615,
|
| 511 |
+
616,
|
| 512 |
+
617,
|
| 513 |
+
629,
|
| 514 |
+
634,
|
| 515 |
+
646,
|
| 516 |
+
653,
|
| 517 |
+
654,
|
| 518 |
+
656,
|
| 519 |
+
658,
|
| 520 |
+
691,
|
| 521 |
+
696,
|
| 522 |
+
701,
|
| 523 |
+
713,
|
| 524 |
+
720,
|
| 525 |
+
728,
|
| 526 |
+
742,
|
| 527 |
+
747,
|
| 528 |
+
753,
|
| 529 |
+
756,
|
| 530 |
+
758,
|
| 531 |
+
759,
|
| 532 |
+
760,
|
| 533 |
+
761,
|
| 534 |
+
762,
|
| 535 |
+
772,
|
| 536 |
+
774,
|
| 537 |
+
791,
|
| 538 |
+
794,
|
| 539 |
+
796,
|
| 540 |
+
798,
|
| 541 |
+
800,
|
| 542 |
+
803,
|
| 543 |
+
809,
|
| 544 |
+
812,
|
| 545 |
+
817,
|
| 546 |
+
818,
|
| 547 |
+
822,
|
| 548 |
+
826,
|
| 549 |
+
833,
|
| 550 |
+
834,
|
| 551 |
+
847,
|
| 552 |
+
854,
|
| 553 |
+
860,
|
| 554 |
+
875,
|
| 555 |
+
887,
|
| 556 |
+
892,
|
| 557 |
+
893,
|
| 558 |
+
894,
|
| 559 |
+
895,
|
| 560 |
+
896,
|
| 561 |
+
920,
|
| 562 |
+
923,
|
| 563 |
+
940,
|
| 564 |
+
942,
|
| 565 |
+
965,
|
| 566 |
+
966,
|
| 567 |
+
967,
|
| 568 |
+
968,
|
| 569 |
+
969,
|
| 570 |
+
970,
|
| 571 |
+
971,
|
| 572 |
+
972,
|
| 573 |
+
973,
|
| 574 |
+
974,
|
| 575 |
+
975,
|
| 576 |
+
976,
|
| 577 |
+
977,
|
| 578 |
+
978,
|
| 579 |
+
979,
|
| 580 |
+
983,
|
| 581 |
+
988,
|
| 582 |
+
995,
|
| 583 |
+
996,
|
| 584 |
+
997,
|
| 585 |
+
1001,
|
| 586 |
+
1006,
|
| 587 |
+
1010,
|
| 588 |
+
1011,
|
| 589 |
+
1017,
|
| 590 |
+
1034,
|
| 591 |
+
1038,
|
| 592 |
+
1046,
|
| 593 |
+
1069,
|
| 594 |
+
1095,
|
| 595 |
+
1102,
|
| 596 |
+
1108,
|
| 597 |
+
1115,
|
| 598 |
+
1116,
|
| 599 |
+
1122,
|
| 600 |
+
1129,
|
| 601 |
+
1151,
|
| 602 |
+
1159,
|
| 603 |
+
1174,
|
| 604 |
+
1175,
|
| 605 |
+
1177,
|
| 606 |
+
1179,
|
| 607 |
+
1180,
|
| 608 |
+
1181,
|
| 609 |
+
1183,
|
| 610 |
+
1189,
|
| 611 |
+
1192,
|
| 612 |
+
1197,
|
| 613 |
+
1202,
|
| 614 |
+
1203,
|
| 615 |
+
1204,
|
| 616 |
+
1205,
|
| 617 |
+
1206,
|
| 618 |
+
1207,
|
| 619 |
+
1208,
|
| 620 |
+
1223,
|
| 621 |
+
1228,
|
| 622 |
+
1234,
|
| 623 |
+
1242,
|
| 624 |
+
1243,
|
| 625 |
+
1253,
|
| 626 |
+
1257,
|
| 627 |
+
1258,
|
| 628 |
+
1261,
|
| 629 |
+
1273,
|
| 630 |
+
1309,
|
| 631 |
+
1317,
|
| 632 |
+
1318,
|
| 633 |
+
1330,
|
| 634 |
+
1331,
|
| 635 |
+
1357,
|
| 636 |
+
1361,
|
| 637 |
+
1363,
|
| 638 |
+
1371,
|
| 639 |
+
1372,
|
| 640 |
+
1375,
|
| 641 |
+
1383,
|
| 642 |
+
1444,
|
| 643 |
+
1446,
|
| 644 |
+
1470,
|
| 645 |
+
1471,
|
| 646 |
+
1472,
|
| 647 |
+
1473,
|
| 648 |
+
1474,
|
| 649 |
+
1475,
|
| 650 |
+
1476,
|
| 651 |
+
1489,
|
| 652 |
+
1499,
|
| 653 |
+
1517,
|
| 654 |
+
1524,
|
| 655 |
+
1546,
|
| 656 |
+
1547,
|
| 657 |
+
1551,
|
| 658 |
+
1565,
|
| 659 |
+
1590,
|
| 660 |
+
1591,
|
| 661 |
+
1593,
|
| 662 |
+
1611,
|
| 663 |
+
1612,
|
| 664 |
+
1617,
|
| 665 |
+
1623,
|
| 666 |
+
1624,
|
| 667 |
+
1628,
|
| 668 |
+
1630,
|
| 669 |
+
1649,
|
| 670 |
+
1675,
|
| 671 |
+
1683,
|
| 672 |
+
1691,
|
| 673 |
+
1694,
|
| 674 |
+
1718,
|
| 675 |
+
1723,
|
| 676 |
+
1752,
|
| 677 |
+
1770,
|
| 678 |
+
1772,
|
| 679 |
+
1774,
|
| 680 |
+
1775,
|
| 681 |
+
1793,
|
| 682 |
+
1808,
|
| 683 |
+
1811,
|
| 684 |
+
1818,
|
| 685 |
+
1822,
|
| 686 |
+
1835,
|
| 687 |
+
1841,
|
| 688 |
+
1846,
|
| 689 |
+
1847,
|
| 690 |
+
1851,
|
| 691 |
+
1852,
|
| 692 |
+
1872,
|
| 693 |
+
1880,
|
| 694 |
+
1881,
|
| 695 |
+
1882,
|
| 696 |
+
1898,
|
| 697 |
+
1917,
|
| 698 |
+
1927,
|
| 699 |
+
1942,
|
| 700 |
+
1943,
|
| 701 |
+
1944,
|
| 702 |
+
1945,
|
| 703 |
+
1949,
|
| 704 |
+
1952,
|
| 705 |
+
1955,
|
| 706 |
+
1999,
|
| 707 |
+
2013,
|
| 708 |
+
2027,
|
| 709 |
+
2030,
|
| 710 |
+
2040,
|
| 711 |
+
2047,
|
| 712 |
+
2048,
|
| 713 |
+
2058,
|
| 714 |
+
2060,
|
| 715 |
+
2071,
|
| 716 |
+
2079,
|
| 717 |
+
2080,
|
| 718 |
+
2087
|
| 719 |
+
],
|
| 720 |
+
"source_vocab": "data/bpe_vocabulary_clean.json"
|
| 721 |
+
}
|
releases/2026-10-02/iar_completion/runtime_snapshot/project/data/bpe_vocabulary_clean.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
releases/2026-10-02/iar_completion/runtime_snapshot/project/data/review_sequences_a5_non_iar_later_role_official_array_v4_20260721_r1/review_bpe_ambiguity_tokens.json
ADDED
|
@@ -0,0 +1,764 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"ambiguous_ids": [
|
| 3 |
+
39,
|
| 4 |
+
114,
|
| 5 |
+
131,
|
| 6 |
+
132,
|
| 7 |
+
133,
|
| 8 |
+
134,
|
| 9 |
+
135,
|
| 10 |
+
136,
|
| 11 |
+
137,
|
| 12 |
+
138,
|
| 13 |
+
140,
|
| 14 |
+
141,
|
| 15 |
+
142,
|
| 16 |
+
143,
|
| 17 |
+
144,
|
| 18 |
+
145,
|
| 19 |
+
147,
|
| 20 |
+
148,
|
| 21 |
+
149,
|
| 22 |
+
150,
|
| 23 |
+
151,
|
| 24 |
+
152,
|
| 25 |
+
153,
|
| 26 |
+
155,
|
| 27 |
+
156,
|
| 28 |
+
157,
|
| 29 |
+
158,
|
| 30 |
+
163,
|
| 31 |
+
164,
|
| 32 |
+
165,
|
| 33 |
+
167,
|
| 34 |
+
168,
|
| 35 |
+
170,
|
| 36 |
+
175,
|
| 37 |
+
176,
|
| 38 |
+
180,
|
| 39 |
+
181,
|
| 40 |
+
183,
|
| 41 |
+
184,
|
| 42 |
+
192,
|
| 43 |
+
193,
|
| 44 |
+
197,
|
| 45 |
+
198,
|
| 46 |
+
217,
|
| 47 |
+
218,
|
| 48 |
+
226,
|
| 49 |
+
229,
|
| 50 |
+
237,
|
| 51 |
+
238,
|
| 52 |
+
239,
|
| 53 |
+
241,
|
| 54 |
+
247,
|
| 55 |
+
251,
|
| 56 |
+
258,
|
| 57 |
+
264,
|
| 58 |
+
265,
|
| 59 |
+
273,
|
| 60 |
+
275,
|
| 61 |
+
276,
|
| 62 |
+
295,
|
| 63 |
+
298,
|
| 64 |
+
299,
|
| 65 |
+
309,
|
| 66 |
+
322,
|
| 67 |
+
323,
|
| 68 |
+
329,
|
| 69 |
+
334,
|
| 70 |
+
335,
|
| 71 |
+
336,
|
| 72 |
+
340,
|
| 73 |
+
341,
|
| 74 |
+
342,
|
| 75 |
+
345,
|
| 76 |
+
349,
|
| 77 |
+
350,
|
| 78 |
+
351,
|
| 79 |
+
352,
|
| 80 |
+
353,
|
| 81 |
+
354,
|
| 82 |
+
355,
|
| 83 |
+
359,
|
| 84 |
+
360,
|
| 85 |
+
361,
|
| 86 |
+
363,
|
| 87 |
+
364,
|
| 88 |
+
365,
|
| 89 |
+
366,
|
| 90 |
+
367,
|
| 91 |
+
368,
|
| 92 |
+
369,
|
| 93 |
+
371,
|
| 94 |
+
372,
|
| 95 |
+
373,
|
| 96 |
+
375,
|
| 97 |
+
376,
|
| 98 |
+
377,
|
| 99 |
+
378,
|
| 100 |
+
379,
|
| 101 |
+
380,
|
| 102 |
+
383,
|
| 103 |
+
384,
|
| 104 |
+
385,
|
| 105 |
+
387,
|
| 106 |
+
388,
|
| 107 |
+
389,
|
| 108 |
+
390,
|
| 109 |
+
391,
|
| 110 |
+
401,
|
| 111 |
+
405,
|
| 112 |
+
409,
|
| 113 |
+
415,
|
| 114 |
+
416,
|
| 115 |
+
419,
|
| 116 |
+
420,
|
| 117 |
+
421,
|
| 118 |
+
426,
|
| 119 |
+
427,
|
| 120 |
+
428,
|
| 121 |
+
430,
|
| 122 |
+
431,
|
| 123 |
+
432,
|
| 124 |
+
434,
|
| 125 |
+
435,
|
| 126 |
+
440,
|
| 127 |
+
441,
|
| 128 |
+
442,
|
| 129 |
+
444,
|
| 130 |
+
445,
|
| 131 |
+
446,
|
| 132 |
+
450,
|
| 133 |
+
462,
|
| 134 |
+
463,
|
| 135 |
+
470,
|
| 136 |
+
476,
|
| 137 |
+
477,
|
| 138 |
+
478,
|
| 139 |
+
481,
|
| 140 |
+
487,
|
| 141 |
+
488,
|
| 142 |
+
489,
|
| 143 |
+
493,
|
| 144 |
+
494,
|
| 145 |
+
496,
|
| 146 |
+
499,
|
| 147 |
+
516,
|
| 148 |
+
535,
|
| 149 |
+
536,
|
| 150 |
+
538,
|
| 151 |
+
539,
|
| 152 |
+
540,
|
| 153 |
+
552,
|
| 154 |
+
590,
|
| 155 |
+
592,
|
| 156 |
+
602,
|
| 157 |
+
603,
|
| 158 |
+
604,
|
| 159 |
+
608,
|
| 160 |
+
609,
|
| 161 |
+
620,
|
| 162 |
+
635,
|
| 163 |
+
636,
|
| 164 |
+
637,
|
| 165 |
+
640,
|
| 166 |
+
646,
|
| 167 |
+
647,
|
| 168 |
+
649,
|
| 169 |
+
654,
|
| 170 |
+
659,
|
| 171 |
+
660,
|
| 172 |
+
661,
|
| 173 |
+
667,
|
| 174 |
+
668,
|
| 175 |
+
675,
|
| 176 |
+
676,
|
| 177 |
+
688,
|
| 178 |
+
690,
|
| 179 |
+
711,
|
| 180 |
+
716,
|
| 181 |
+
720,
|
| 182 |
+
721,
|
| 183 |
+
734,
|
| 184 |
+
742,
|
| 185 |
+
752,
|
| 186 |
+
754,
|
| 187 |
+
778,
|
| 188 |
+
788,
|
| 189 |
+
791,
|
| 190 |
+
793,
|
| 191 |
+
808,
|
| 192 |
+
809,
|
| 193 |
+
810,
|
| 194 |
+
817,
|
| 195 |
+
820,
|
| 196 |
+
831,
|
| 197 |
+
833,
|
| 198 |
+
834,
|
| 199 |
+
843,
|
| 200 |
+
844,
|
| 201 |
+
859,
|
| 202 |
+
869,
|
| 203 |
+
870,
|
| 204 |
+
873,
|
| 205 |
+
880,
|
| 206 |
+
885,
|
| 207 |
+
886,
|
| 208 |
+
893,
|
| 209 |
+
894,
|
| 210 |
+
910,
|
| 211 |
+
928,
|
| 212 |
+
938,
|
| 213 |
+
939,
|
| 214 |
+
940,
|
| 215 |
+
941,
|
| 216 |
+
942,
|
| 217 |
+
943,
|
| 218 |
+
944,
|
| 219 |
+
950,
|
| 220 |
+
952,
|
| 221 |
+
953,
|
| 222 |
+
958,
|
| 223 |
+
959,
|
| 224 |
+
961,
|
| 225 |
+
963,
|
| 226 |
+
972,
|
| 227 |
+
979,
|
| 228 |
+
987,
|
| 229 |
+
988,
|
| 230 |
+
989,
|
| 231 |
+
994,
|
| 232 |
+
995,
|
| 233 |
+
996,
|
| 234 |
+
1000,
|
| 235 |
+
1001,
|
| 236 |
+
1003,
|
| 237 |
+
1004,
|
| 238 |
+
1005,
|
| 239 |
+
1006,
|
| 240 |
+
1007,
|
| 241 |
+
1008,
|
| 242 |
+
1009,
|
| 243 |
+
1010,
|
| 244 |
+
1011,
|
| 245 |
+
1012,
|
| 246 |
+
1013,
|
| 247 |
+
1014,
|
| 248 |
+
1015,
|
| 249 |
+
1016,
|
| 250 |
+
1017,
|
| 251 |
+
1019,
|
| 252 |
+
1021,
|
| 253 |
+
1026,
|
| 254 |
+
1038,
|
| 255 |
+
1050,
|
| 256 |
+
1055,
|
| 257 |
+
1072,
|
| 258 |
+
1078,
|
| 259 |
+
1115,
|
| 260 |
+
1116,
|
| 261 |
+
1124,
|
| 262 |
+
1138,
|
| 263 |
+
1150,
|
| 264 |
+
1161,
|
| 265 |
+
1167,
|
| 266 |
+
1168,
|
| 267 |
+
1169,
|
| 268 |
+
1170,
|
| 269 |
+
1171,
|
| 270 |
+
1172,
|
| 271 |
+
1173,
|
| 272 |
+
1178,
|
| 273 |
+
1193,
|
| 274 |
+
1197,
|
| 275 |
+
1220,
|
| 276 |
+
1233,
|
| 277 |
+
1250,
|
| 278 |
+
1253,
|
| 279 |
+
1262,
|
| 280 |
+
1267,
|
| 281 |
+
1301,
|
| 282 |
+
1305,
|
| 283 |
+
1317,
|
| 284 |
+
1318,
|
| 285 |
+
1333,
|
| 286 |
+
1342,
|
| 287 |
+
1349,
|
| 288 |
+
1360,
|
| 289 |
+
1370,
|
| 290 |
+
1371,
|
| 291 |
+
1372,
|
| 292 |
+
1373,
|
| 293 |
+
1374,
|
| 294 |
+
1383,
|
| 295 |
+
1389,
|
| 296 |
+
1390,
|
| 297 |
+
1391,
|
| 298 |
+
1396,
|
| 299 |
+
1416,
|
| 300 |
+
1420,
|
| 301 |
+
1425,
|
| 302 |
+
1428,
|
| 303 |
+
1433,
|
| 304 |
+
1445,
|
| 305 |
+
1478,
|
| 306 |
+
1483,
|
| 307 |
+
1499,
|
| 308 |
+
1500,
|
| 309 |
+
1501,
|
| 310 |
+
1503,
|
| 311 |
+
1513,
|
| 312 |
+
1524,
|
| 313 |
+
1531,
|
| 314 |
+
1561,
|
| 315 |
+
1563,
|
| 316 |
+
1566,
|
| 317 |
+
1567,
|
| 318 |
+
1568,
|
| 319 |
+
1600,
|
| 320 |
+
1601,
|
| 321 |
+
1602,
|
| 322 |
+
1605,
|
| 323 |
+
1608,
|
| 324 |
+
1626,
|
| 325 |
+
1634,
|
| 326 |
+
1635,
|
| 327 |
+
1636,
|
| 328 |
+
1661,
|
| 329 |
+
1669,
|
| 330 |
+
1671,
|
| 331 |
+
1672,
|
| 332 |
+
1686,
|
| 333 |
+
1726,
|
| 334 |
+
1737,
|
| 335 |
+
1738,
|
| 336 |
+
1739,
|
| 337 |
+
1740,
|
| 338 |
+
1741,
|
| 339 |
+
1752,
|
| 340 |
+
1763,
|
| 341 |
+
1773,
|
| 342 |
+
1780,
|
| 343 |
+
1790,
|
| 344 |
+
1796,
|
| 345 |
+
1798,
|
| 346 |
+
1804,
|
| 347 |
+
1829,
|
| 348 |
+
1842,
|
| 349 |
+
1888,
|
| 350 |
+
1893,
|
| 351 |
+
1905,
|
| 352 |
+
1907,
|
| 353 |
+
1912,
|
| 354 |
+
1918,
|
| 355 |
+
1923,
|
| 356 |
+
1940,
|
| 357 |
+
1945,
|
| 358 |
+
1948,
|
| 359 |
+
1951,
|
| 360 |
+
1961,
|
| 361 |
+
1991,
|
| 362 |
+
1992,
|
| 363 |
+
1993,
|
| 364 |
+
2016,
|
| 365 |
+
2020,
|
| 366 |
+
2021,
|
| 367 |
+
2030,
|
| 368 |
+
2033,
|
| 369 |
+
2034,
|
| 370 |
+
2035,
|
| 371 |
+
2064,
|
| 372 |
+
2066,
|
| 373 |
+
2067,
|
| 374 |
+
2077,
|
| 375 |
+
2093,
|
| 376 |
+
2100,
|
| 377 |
+
2101,
|
| 378 |
+
2105,
|
| 379 |
+
2110
|
| 380 |
+
],
|
| 381 |
+
"ambiguous_tokens": {
|
| 382 |
+
"%?%": 1763,
|
| 383 |
+
"-?": 1918,
|
| 384 |
+
"1-?": 273,
|
| 385 |
+
"1-a?|b?|c?|d?|e?|f?}": 928,
|
| 386 |
+
"1-a?|b?|c?|d?|e?}": 869,
|
| 387 |
+
"1-d?|i?}": 2100,
|
| 388 |
+
"2-?": 721,
|
| 389 |
+
"<Q>-?": 2016,
|
| 390 |
+
"?": 39,
|
| 391 |
+
"?%": 1669,
|
| 392 |
+
"?*OCC/3=O": 2033,
|
| 393 |
+
"?*OPO/3O/3=O": 1796,
|
| 394 |
+
"?*OSO/3=O/3=O": 1078,
|
| 395 |
+
"?-": 149,
|
| 396 |
+
"?-?": 2067,
|
| 397 |
+
"?|": 114,
|
| 398 |
+
"?|A": 434,
|
| 399 |
+
"?|B": 462,
|
| 400 |
+
"?|C": 493,
|
| 401 |
+
"?|D": 535,
|
| 402 |
+
"?|E": 608,
|
| 403 |
+
"?|F": 635,
|
| 404 |
+
"?|G": 646,
|
| 405 |
+
"?|H": 667,
|
| 406 |
+
"?|I": 675,
|
| 407 |
+
"?|J": 688,
|
| 408 |
+
"?|K": 831,
|
| 409 |
+
"?|L": 939,
|
| 410 |
+
"?|L?|M": 942,
|
| 411 |
+
"?|L?|M?|N": 943,
|
| 412 |
+
"?|M": 940,
|
| 413 |
+
"?|N": 941,
|
| 414 |
+
"?|O": 1003,
|
| 415 |
+
"?|O?|P": 1011,
|
| 416 |
+
"?|O?|P?|Q": 1012,
|
| 417 |
+
"?|O?|P?|Q?|R": 1013,
|
| 418 |
+
"?|O?|P?|Q?|R?|S": 1014,
|
| 419 |
+
"?|O?|P?|Q?|R?|S?|T": 1015,
|
| 420 |
+
"?|O?|P?|Q?|R?|S?|T?|U": 1016,
|
| 421 |
+
"?|O?|P?|Q?|R?|S?|T?|U?|V": 1017,
|
| 422 |
+
"?|P": 1004,
|
| 423 |
+
"?|Q": 1005,
|
| 424 |
+
"?|R": 1006,
|
| 425 |
+
"?|S": 1007,
|
| 426 |
+
"?|T": 1008,
|
| 427 |
+
"?|U": 1009,
|
| 428 |
+
"?|V": 1010,
|
| 429 |
+
"?|W": 1167,
|
| 430 |
+
"?|W?|X": 1170,
|
| 431 |
+
"?|W?|X?|Y": 1171,
|
| 432 |
+
"?|X": 1168,
|
| 433 |
+
"?|Y": 1169,
|
| 434 |
+
"?|Z": 1370,
|
| 435 |
+
"?|Z?|a": 1371,
|
| 436 |
+
"?|Z?|aa?|": 1372,
|
| 437 |
+
"?|Z?|aa?|ab": 1373,
|
| 438 |
+
"?|a": 552,
|
| 439 |
+
"?|ac": 1738,
|
| 440 |
+
"?|ac?|ad": 1739,
|
| 441 |
+
"?|ad": 1737,
|
| 442 |
+
"?|c": 133,
|
| 443 |
+
"?|d": 135,
|
| 444 |
+
"?|e": 137,
|
| 445 |
+
"?|f": 140,
|
| 446 |
+
"?|g": 142,
|
| 447 |
+
"?|h": 144,
|
| 448 |
+
"?|h?}": 2064,
|
| 449 |
+
"?|i": 147,
|
| 450 |
+
"?|i?}": 1842,
|
| 451 |
+
"?|j": 150,
|
| 452 |
+
"?|k": 152,
|
| 453 |
+
"?|l": 155,
|
| 454 |
+
"?|m": 157,
|
| 455 |
+
"?|n": 164,
|
| 456 |
+
"?|o": 167,
|
| 457 |
+
"?|p": 175,
|
| 458 |
+
"?|s": 192,
|
| 459 |
+
"?|t": 197,
|
| 460 |
+
"?|u": 217,
|
| 461 |
+
"?|v": 238,
|
| 462 |
+
"?|w": 264,
|
| 463 |
+
"?|x": 298,
|
| 464 |
+
"?|y": 322,
|
| 465 |
+
"?|z": 387,
|
| 466 |
+
"?}": 163,
|
| 467 |
+
"?}*OC": 716,
|
| 468 |
+
"?}*OCC/3=O": 870,
|
| 469 |
+
"?}*OPO/3O/3=O": 742,
|
| 470 |
+
"?}*OSO/3=O/3=O": 592,
|
| 471 |
+
"?}-{": 170,
|
| 472 |
+
"?}-{a?|b": 994,
|
| 473 |
+
"?}-{a?|b?": 995,
|
| 474 |
+
"?}-{a?|b?|c": 602,
|
| 475 |
+
"?}-{a?|b?|c?": 603,
|
| 476 |
+
"?}-{a?|b?|c?|d": 487,
|
| 477 |
+
"?}-{a?|b?|c?|d?": 488,
|
| 478 |
+
"?}-{a?|b?|c?|d?|e": 476,
|
| 479 |
+
"?}-{a?|b?|c?|d?|e?": 477,
|
| 480 |
+
"?}-{a?|b?|c?|d?|e?|f": 440,
|
| 481 |
+
"?}-{a?|b?|c?|d?|e?|f?": 441,
|
| 482 |
+
"?}-{a?|b?|c?|d?|e?|f?|g": 444,
|
| 483 |
+
"?}-{a?|b?|c?|d?|e?|f?|g?": 445,
|
| 484 |
+
"?}-{a?|b?|c?|d?|e?|f?|g?|h": 430,
|
| 485 |
+
"?}-{a?|b?|c?|d?|e?|f?|g?|h?": 431,
|
| 486 |
+
"?}-{a?|b?|c?|d?|e?|f?|g?|h?|i": 419,
|
| 487 |
+
"?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?": 420,
|
| 488 |
+
"?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j": 383,
|
| 489 |
+
"?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?": 384,
|
| 490 |
+
"?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k": 371,
|
| 491 |
+
"?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?": 372,
|
| 492 |
+
"?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l": 340,
|
| 493 |
+
"?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?": 341,
|
| 494 |
+
"?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m": 389,
|
| 495 |
+
"?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?": 390,
|
| 496 |
+
"?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n": 378,
|
| 497 |
+
"?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?": 379,
|
| 498 |
+
"?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o": 359,
|
| 499 |
+
"?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?": 360,
|
| 500 |
+
"?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p": 349,
|
| 501 |
+
"?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?": 350,
|
| 502 |
+
"?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q": 375,
|
| 503 |
+
"?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?": 376,
|
| 504 |
+
"?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r": 353,
|
| 505 |
+
"?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?": 354,
|
| 506 |
+
"?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s": 367,
|
| 507 |
+
"?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?": 368,
|
| 508 |
+
"?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t": 334,
|
| 509 |
+
"?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?": 335,
|
| 510 |
+
"?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u": 364,
|
| 511 |
+
"?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?": 365,
|
| 512 |
+
"?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v": 426,
|
| 513 |
+
"?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?": 427,
|
| 514 |
+
"?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w": 538,
|
| 515 |
+
"?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?": 539,
|
| 516 |
+
"?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x": 659,
|
| 517 |
+
"?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x?": 660,
|
| 518 |
+
"?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x?|y": 808,
|
| 519 |
+
"?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x?|y?": 809,
|
| 520 |
+
"?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x?|y?|z": 987,
|
| 521 |
+
"?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x?|y?|z?": 988,
|
| 522 |
+
"?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x?|y?|z?|A": 1499,
|
| 523 |
+
"?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x?|y?|z?|A?": 1500,
|
| 524 |
+
"?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x?|y?|z?|A?|B": 1389,
|
| 525 |
+
"?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x?|y?|z?|A?|B?": 1390,
|
| 526 |
+
"?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x?|y?|z?|A?|B?|C": 1634,
|
| 527 |
+
"?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x?|y?|z?|A?|B?|C?": 1635,
|
| 528 |
+
"?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x?|y?|z?|A?|B?|C?|D": 1600,
|
| 529 |
+
"?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x?|y?|z?|A?|B?|C?|D?": 1601,
|
| 530 |
+
"?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x?|y?|z?|A?|B?|C?|D?|E?|F?|G?|H?|I?|J": 1566,
|
| 531 |
+
"?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x?|y?|z?|A?|B?|C?|D?|E?|F?|G?|H?|I?|J?": 1567,
|
| 532 |
+
"a?-": 226,
|
| 533 |
+
"a?-b1": 241,
|
| 534 |
+
"a?-b2": 1267,
|
| 535 |
+
"a?-c1": 972,
|
| 536 |
+
"a?-d1": 959,
|
| 537 |
+
"a?-e1": 979,
|
| 538 |
+
"a?-f1": 1055,
|
| 539 |
+
"a?-g1": 1342,
|
| 540 |
+
"a?-h1": 1561,
|
| 541 |
+
"a?-i1": 1420,
|
| 542 |
+
"a?-j1": 1233,
|
| 543 |
+
"a?-k1": 1318,
|
| 544 |
+
"a?-l1": 1115,
|
| 545 |
+
"a?-m1": 1416,
|
| 546 |
+
"a?-n1": 1425,
|
| 547 |
+
"a?-o1": 1605,
|
| 548 |
+
"a?-p1": 1740,
|
| 549 |
+
"a?-q1": 1912,
|
| 550 |
+
"a?-r1": 1661,
|
| 551 |
+
"a?-s1": 1907,
|
| 552 |
+
"a?-t1": 2020,
|
| 553 |
+
"a?|": 131,
|
| 554 |
+
"a?|b": 132,
|
| 555 |
+
"a?|b?|c": 134,
|
| 556 |
+
"a?|b?|c?|d": 136,
|
| 557 |
+
"a?|b?|c?|d?|e": 138,
|
| 558 |
+
"a?|b?|c?|d?|e?|f": 141,
|
| 559 |
+
"a?|b?|c?|d?|e?|f?|g": 143,
|
| 560 |
+
"a?|b?|c?|d?|e?|f?|g?|h": 145,
|
| 561 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i": 148,
|
| 562 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j": 151,
|
| 563 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k": 153,
|
| 564 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l": 156,
|
| 565 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m": 158,
|
| 566 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n": 165,
|
| 567 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o": 168,
|
| 568 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p": 176,
|
| 569 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|": 180,
|
| 570 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q": 181,
|
| 571 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|": 183,
|
| 572 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r": 184,
|
| 573 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s": 193,
|
| 574 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t": 198,
|
| 575 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u": 218,
|
| 576 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v": 239,
|
| 577 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w": 265,
|
| 578 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x": 299,
|
| 579 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x?|y": 323,
|
| 580 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x?|y?|z": 388,
|
| 581 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x?|y?|z?|A": 435,
|
| 582 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x?|y?|z?|A?|B": 463,
|
| 583 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x?|y?|z?|A?|B?|C": 494,
|
| 584 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x?|y?|z?|A?|B?|C?|D": 536,
|
| 585 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x?|y?|z?|A?|B?|C?|D?|E": 609,
|
| 586 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x?|y?|z?|A?|B?|C?|D?|E?|F": 636,
|
| 587 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x?|y?|z?|A?|B?|C?|D?|E?|F?|G": 647,
|
| 588 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x?|y?|z?|A?|B?|C?|D?|E?|F?|G?|H": 668,
|
| 589 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x?|y?|z?|A?|B?|C?|D?|E?|F?|G?|H?|I": 676,
|
| 590 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x?|y?|z?|A?|B?|C?|D?|E?|F?|G?|H?|I?|J": 690,
|
| 591 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x?|y?|z?|A?|B?|C?|D?|E?|F?|G?|H?|I?|J?|K": 833,
|
| 592 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x?|y?|z?|A?|B?|C?|D?|E?|F?|G?|H?|I?|J?|K?|L?|M?|N": 944,
|
| 593 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x?|y?|z?|A?|B?|C?|D?|E?|F?|G?|H?|I?|J?|K?|L?|M?|N?|O?|P?|Q?|R?|S?|T?|U?|V": 1019,
|
| 594 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x?|y?|z?|A?|B?|C?|D?|E?|F?|G?|H?|I?|J?|K?|L?|M?|N?|O?|P?|Q?|R?|S?|T?|U?|V?|W?|X?|Y": 1172,
|
| 595 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x?|y?|z?|A?|B?|C?|D?|E?|F?|G?|H?|I?|J?|K?|L?|M?|N?|O?|P?|Q?|R?|S?|T?|U?|V?|W?|X?|Y?|Z?|aa?|ab": 1374,
|
| 596 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x?|y?|z?|A?|B?|C?|D?|E?|F?|G?|H?|I?|J?|K?|L?|M?|N?|O?|P?|Q?|R?|S?|T?|U?|V?|W?|X?|Y?|Z?|aa?|ab?|ac?|ad": 1741,
|
| 597 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x?|y?|z?|A?|B?|C?|D?|E?|F?|G?|H?|I?|J?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x?|y?|z?|A?|B?|C?|D?|E?|F?|G?|H?|I?|J?": 1568,
|
| 598 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x?|y?|z?|A?|B?|C?|D?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x?|y?|z?|A?|B?|C?|D?": 1602,
|
| 599 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x?|y?|z?|A?|B?|C?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x?|y?|z?|A?|B?|C?": 1636,
|
| 600 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x?|y?|z?|A?|B?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x?|y?|z?|A?|B?": 1391,
|
| 601 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x?|y?|z?|A?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x?|y?|z?|A?": 1501,
|
| 602 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x?|y?|z?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x?|y?|z?": 989,
|
| 603 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x?|y?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x?|y?": 810,
|
| 604 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?|x?": 661,
|
| 605 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?|w?": 540,
|
| 606 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?|v?": 428,
|
| 607 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?|u?": 366,
|
| 608 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?|t?": 336,
|
| 609 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?|s?": 369,
|
| 610 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?|r?": 355,
|
| 611 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?|q?": 377,
|
| 612 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?|p?": 351,
|
| 613 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?}": 2105,
|
| 614 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?|o?": 361,
|
| 615 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?}": 1524,
|
| 616 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?|n?": 380,
|
| 617 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?}": 1478,
|
| 618 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?|m?": 391,
|
| 619 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?}": 1483,
|
| 620 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?|l?": 342,
|
| 621 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?}": 1262,
|
| 622 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?|k?": 373,
|
| 623 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?}": 958,
|
| 624 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?|j?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?|j?": 385,
|
| 625 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?}": 886,
|
| 626 |
+
"a?|b?|c?|d?|e?|f?|g?|h?|i?}-{a?|b?|c?|d?|e?|f?|g?|h?|i?": 421,
|
| 627 |
+
"a?|b?|c?|d?|e?|f?|g?|h?}": 1000,
|
| 628 |
+
"a?|b?|c?|d?|e?|f?|g?|h?}*OSO/3=O/3=O": 2035,
|
| 629 |
+
"a?|b?|c?|d?|e?|f?|g?|h?}-{a?|b?|c?|d?|e?|f?|g?|h?": 432,
|
| 630 |
+
"a?|b?|c?|d?|e?|f?|g?}": 1150,
|
| 631 |
+
"a?|b?|c?|d?|e?|f?|g?}-{a?|b?|c?|d?|e?|f?|g?": 446,
|
| 632 |
+
"a?|b?|c?|d?|e?|f?}": 834,
|
| 633 |
+
"a?|b?|c?|d?|e?|f?}*OC": 2110,
|
| 634 |
+
"a?|b?|c?|d?|e?|f?}*OSO/3=O/3=O": 1333,
|
| 635 |
+
"a?|b?|c?|d?|e?|f?}-{a?|b?|c?|d?|e?|f?": 442,
|
| 636 |
+
"a?|b?|c?|d?|e?}": 791,
|
| 637 |
+
"a?|b?|c?|d?|e?}*OC": 2034,
|
| 638 |
+
"a?|b?|c?|d?|e?}*OSO/3=O/3=O": 1253,
|
| 639 |
+
"a?|b?|c?|d?|e?}-{a?|b?|c?|d?|e?": 478,
|
| 640 |
+
"a?|b?|c?|d?}": 1923,
|
| 641 |
+
"a?|b?|c?|d?}*OC": 1951,
|
| 642 |
+
"a?|b?|c?|d?}*OSO/3=O/3=O": 1349,
|
| 643 |
+
"a?|b?|c?|d?}-{a?|b?|c?|d?": 489,
|
| 644 |
+
"a?|b?|c?}*OC": 1563,
|
| 645 |
+
"a?|b?|c?}*OCC/3=O": 1773,
|
| 646 |
+
"a?|b?|c?}*OSO/3=O/3=O": 2030,
|
| 647 |
+
"a?|b?|c?}-{a?|b?|c?": 604,
|
| 648 |
+
"a?|b?}*OSO/3=O/3=O": 2101,
|
| 649 |
+
"a?|b?}-{a?|b?": 996,
|
| 650 |
+
"b?-": 237,
|
| 651 |
+
"b?-c1": 251,
|
| 652 |
+
"b?-c2": 793,
|
| 653 |
+
"b?-d1": 1072,
|
| 654 |
+
"b?-e1": 910,
|
| 655 |
+
"b?-f1": 938,
|
| 656 |
+
"b?-g1": 1021,
|
| 657 |
+
"b?-h1": 1250,
|
| 658 |
+
"b?-i1": 1531,
|
| 659 |
+
"b?-j1": 1671,
|
| 660 |
+
"c?-": 229,
|
| 661 |
+
"c?-d1": 258,
|
| 662 |
+
"c?-d2": 1161,
|
| 663 |
+
"c?-e1": 880,
|
| 664 |
+
"c?-f1": 844,
|
| 665 |
+
"c?-g1": 711,
|
| 666 |
+
"c?-h1": 649,
|
| 667 |
+
"c?-i1": 654,
|
| 668 |
+
"c?-j1": 820,
|
| 669 |
+
"c?-k1": 720,
|
| 670 |
+
"c?-l1": 894,
|
| 671 |
+
"c?-m1": 1038,
|
| 672 |
+
"c?-n1": 1445,
|
| 673 |
+
"c?-o1": 1608,
|
| 674 |
+
"c?-p1": 1992,
|
| 675 |
+
"c?-q1": 1945,
|
| 676 |
+
"c?-r1": 2066,
|
| 677 |
+
"d?-": 247,
|
| 678 |
+
"d?-e1": 275,
|
| 679 |
+
"d?-e2": 1050,
|
| 680 |
+
"d?-f1": 961,
|
| 681 |
+
"d?-g1": 754,
|
| 682 |
+
"d?-h1": 640,
|
| 683 |
+
"d?-i1": 788,
|
| 684 |
+
"d?-j1": 1001,
|
| 685 |
+
"d?-k1": 1360,
|
| 686 |
+
"e?-": 276,
|
| 687 |
+
"e?-f1": 295,
|
| 688 |
+
"e?-f2": 1197,
|
| 689 |
+
"e?-g1": 953,
|
| 690 |
+
"e?-h1": 817,
|
| 691 |
+
"e?-i1": 1305,
|
| 692 |
+
"f1-a?|b?|c?|d?|e?}": 1798,
|
| 693 |
+
"f?-": 309,
|
| 694 |
+
"f?-g1": 363,
|
| 695 |
+
"f?-g2": 499,
|
| 696 |
+
"f?-h1": 1396,
|
| 697 |
+
"f?-i1": 1940,
|
| 698 |
+
"g1-a?|b?|c?|d?|e?|f?}": 1672,
|
| 699 |
+
"g?-": 329,
|
| 700 |
+
"g?-h1": 401,
|
| 701 |
+
"g?-h2": 885,
|
| 702 |
+
"g?-i1": 1178,
|
| 703 |
+
"g?-j1": 1513,
|
| 704 |
+
"h?-": 352,
|
| 705 |
+
"h?-i1": 409,
|
| 706 |
+
"h?-i2": 893,
|
| 707 |
+
"h?-j1": 1301,
|
| 708 |
+
"i1-a?|b?|c?|d?|e?|f?|g?|h?}": 1961,
|
| 709 |
+
"i1-a?|b?|c?|d?|e?}": 2077,
|
| 710 |
+
"i?-": 345,
|
| 711 |
+
"i?-j1": 415,
|
| 712 |
+
"i?-j2": 859,
|
| 713 |
+
"i?-k1": 1317,
|
| 714 |
+
"i?-l1": 1193,
|
| 715 |
+
"j1-a?|b?|c?|d?|e?|f?|g?|h?|i?}": 1905,
|
| 716 |
+
"j?-": 405,
|
| 717 |
+
"j?-k1": 470,
|
| 718 |
+
"j?-k2": 873,
|
| 719 |
+
"j?-l1": 1752,
|
| 720 |
+
"j?-m1": 1626,
|
| 721 |
+
"j?-n1": 2093,
|
| 722 |
+
"k?-": 416,
|
| 723 |
+
"k?-l1": 496,
|
| 724 |
+
"k?-l2": 1116,
|
| 725 |
+
"k?-m1": 1888,
|
| 726 |
+
"k?-n1": 1780,
|
| 727 |
+
"k?-o1": 1124,
|
| 728 |
+
"l?-": 450,
|
| 729 |
+
"l?-m1": 516,
|
| 730 |
+
"l?-m2": 1383,
|
| 731 |
+
"l?-n1": 1790,
|
| 732 |
+
"l?-o1": 1991,
|
| 733 |
+
"l?-p1": 1726,
|
| 734 |
+
"l?-q1": 1804,
|
| 735 |
+
"m?-": 481,
|
| 736 |
+
"m?-n1": 620,
|
| 737 |
+
"m?-n2": 950,
|
| 738 |
+
"m?-p1": 1686,
|
| 739 |
+
"m?-q1": 2021,
|
| 740 |
+
"m?-r1": 1948,
|
| 741 |
+
"n?-": 590,
|
| 742 |
+
"n?-o1": 734,
|
| 743 |
+
"n?-o2": 1220,
|
| 744 |
+
"n?-q1": 1893,
|
| 745 |
+
"o?-": 637,
|
| 746 |
+
"o?-p1": 752,
|
| 747 |
+
"o?-p2": 1503,
|
| 748 |
+
"p?-": 778,
|
| 749 |
+
"p?-q1": 952,
|
| 750 |
+
"p?-q2": 1433,
|
| 751 |
+
"q?-": 843,
|
| 752 |
+
"q?-r1": 1026,
|
| 753 |
+
"q?-r2": 1993,
|
| 754 |
+
"r?-": 963,
|
| 755 |
+
"r?-s1": 1138,
|
| 756 |
+
"s?-": 1173,
|
| 757 |
+
"s?-t1": 1428,
|
| 758 |
+
"t?-": 1829
|
| 759 |
+
},
|
| 760 |
+
"definition": "non-special vocabulary token containing literal question mark",
|
| 761 |
+
"schema": "bertose_a5_literal_question_mark_ambiguity_v1",
|
| 762 |
+
"source_vocabulary": "review_bpe_vocabulary.json",
|
| 763 |
+
"training_authorized": false
|
| 764 |
+
}
|
releases/2026-10-02/iar_completion/runtime_snapshot/project/data/review_sequences_a5_non_iar_later_role_official_array_v4_20260721_r1/review_bpe_vocabulary.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
releases/2026-10-02/iar_completion/runtime_snapshot/project/data/review_sequences_a5_non_iar_later_role_official_array_v4_20260721_r1/review_frozen_sequence_tree_runtime.py
ADDED
|
@@ -0,0 +1,287 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Fail-closed WURCS tree channels for the review-only A5 runtime.
|
| 2 |
+
|
| 3 |
+
The fitted BPE vocabulary is deliberately not changed here. This module only
|
| 4 |
+
repairs deterministic transform-time annotations. A tree depth is emitted
|
| 5 |
+
only when every linkage is a full, unambiguous residue-pair token, exactly one
|
| 6 |
+
endpoint of every bond is the anomeric donor, and the resulting directed graph
|
| 7 |
+
is one rooted tree. Otherwise residue tokens receive an explicit UNKNOWN
|
| 8 |
+
depth while the original WURCS units remain available to BPE.
|
| 9 |
+
|
| 10 |
+
This file is an isolated review runtime. It must not be copied over the shared
|
| 11 |
+
``training/a5_wurcs_bpe.py`` module.
|
| 12 |
+
"""
|
| 13 |
+
|
| 14 |
+
from __future__ import annotations
|
| 15 |
+
|
| 16 |
+
from collections import defaultdict, deque
|
| 17 |
+
from dataclasses import dataclass
|
| 18 |
+
from pathlib import Path
|
| 19 |
+
from typing import Optional
|
| 20 |
+
|
| 21 |
+
from training.a5_topology import node_index, node_label
|
| 22 |
+
from training.a5_wurcs_bpe import A5WURCSBPETokenizer, A5WURCSPreTokenizer
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
BRANCH_DEPTH_UNKNOWN = 202
|
| 26 |
+
BRANCH_DEPTH_VOCAB_SIZE = 203
|
| 27 |
+
|
| 28 |
+
LINKAGE_NONE = 0
|
| 29 |
+
LINKAGE_1_2 = 1
|
| 30 |
+
LINKAGE_1_3 = 2
|
| 31 |
+
LINKAGE_1_4 = 3
|
| 32 |
+
LINKAGE_1_6 = 4
|
| 33 |
+
LINKAGE_2_3 = 5
|
| 34 |
+
LINKAGE_2_6 = 6
|
| 35 |
+
LINKAGE_3_6 = 7
|
| 36 |
+
LINKAGE_OTHER_EXACT = 8
|
| 37 |
+
LINKAGE_UNKNOWN = 9
|
| 38 |
+
LINKAGE_VOCAB_SIZE = 10
|
| 39 |
+
|
| 40 |
+
|
| 41 |
+
@dataclass(frozen=True)
|
| 42 |
+
class TreeChannelAnalysis:
|
| 43 |
+
residue_count: int
|
| 44 |
+
exact_undirected_tree: bool
|
| 45 |
+
exact_rooted_tree: bool
|
| 46 |
+
failure_reason: str
|
| 47 |
+
depths: dict[int, int]
|
| 48 |
+
branch_open_counts: dict[int, int]
|
| 49 |
+
distance_matrix: list[list[int]]
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
def _distance_matrix(adjacency: dict[int, set[int]], count: int) -> list[list[int]]:
|
| 53 |
+
matrix: list[list[int]] = []
|
| 54 |
+
for source in range(count):
|
| 55 |
+
distances = {source: 0}
|
| 56 |
+
queue: deque[int] = deque([source])
|
| 57 |
+
while queue:
|
| 58 |
+
current = queue.popleft()
|
| 59 |
+
for neighbor in sorted(adjacency[current]):
|
| 60 |
+
if neighbor not in distances:
|
| 61 |
+
distances[neighbor] = distances[current] + 1
|
| 62 |
+
queue.append(neighbor)
|
| 63 |
+
if len(distances) != count:
|
| 64 |
+
return []
|
| 65 |
+
matrix.append([distances[target] for target in range(count)])
|
| 66 |
+
return matrix
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
class ReviewA5WURCSPreTokenizerV3(A5WURCSPreTokenizer):
|
| 70 |
+
"""A5 semantic units with fail-closed branch and linkage channels."""
|
| 71 |
+
|
| 72 |
+
def _sections(
|
| 73 |
+
self, wurcs: str
|
| 74 |
+
) -> tuple[list[str], list[str], list[str], list[int | None]]:
|
| 75 |
+
parts = self._split_wurcs_sections(wurcs)
|
| 76 |
+
if len(parts) < 4:
|
| 77 |
+
return [], [], [], []
|
| 78 |
+
residue_definitions = self.RESIDUE_PATTERN.findall(parts[2])
|
| 79 |
+
index_list = parts[3].split("-") if parts[3] else []
|
| 80 |
+
linkages = parts[4].split("_") if len(parts) > 4 and parts[4] else []
|
| 81 |
+
anomeric = self._instance_anomeric_positions(residue_definitions, index_list)
|
| 82 |
+
return residue_definitions, index_list, linkages, anomeric
|
| 83 |
+
|
| 84 |
+
def analyze_tree(self, wurcs: str) -> TreeChannelAnalysis:
|
| 85 |
+
_, index_list, linkages, anomeric = self._sections(wurcs)
|
| 86 |
+
count = len(index_list)
|
| 87 |
+
if count == 0:
|
| 88 |
+
return TreeChannelAnalysis(0, False, False, "missing_residue_instances", {}, {}, [])
|
| 89 |
+
if count == 1:
|
| 90 |
+
if linkages:
|
| 91 |
+
return TreeChannelAnalysis(
|
| 92 |
+
1, False, False, "single_residue_has_linkage_tokens", {}, {}, []
|
| 93 |
+
)
|
| 94 |
+
return TreeChannelAnalysis(1, True, True, "", {0: 0}, {}, [[0]])
|
| 95 |
+
|
| 96 |
+
adjacency: dict[int, set[int]] = {index: set() for index in range(count)}
|
| 97 |
+
directed_children: dict[int, list[int]] = defaultdict(list)
|
| 98 |
+
child_parent: dict[int, int] = {}
|
| 99 |
+
seen_edges: set[tuple[int, int]] = set()
|
| 100 |
+
orientation_failure = ""
|
| 101 |
+
|
| 102 |
+
for linkage in linkages:
|
| 103 |
+
match = self.A5_LINKAGE_PATTERN.fullmatch(linkage)
|
| 104 |
+
if match is None:
|
| 105 |
+
return TreeChannelAnalysis(
|
| 106 |
+
count, False, False, "non_exact_linkage_token", {}, {}, []
|
| 107 |
+
)
|
| 108 |
+
left_label, left_position, right_label, right_position = match.groups()
|
| 109 |
+
try:
|
| 110 |
+
left = node_index(left_label) - 1
|
| 111 |
+
right = node_index(right_label) - 1
|
| 112 |
+
except ValueError:
|
| 113 |
+
return TreeChannelAnalysis(
|
| 114 |
+
count, False, False, "invalid_residue_label", {}, {}, []
|
| 115 |
+
)
|
| 116 |
+
if not (0 <= left < count and 0 <= right < count) or left == right:
|
| 117 |
+
return TreeChannelAnalysis(
|
| 118 |
+
count, False, False, "invalid_residue_edge", {}, {}, []
|
| 119 |
+
)
|
| 120 |
+
edge = tuple(sorted((left, right)))
|
| 121 |
+
if edge in seen_edges:
|
| 122 |
+
return TreeChannelAnalysis(
|
| 123 |
+
count, False, False, "duplicate_residue_edge", {}, {}, []
|
| 124 |
+
)
|
| 125 |
+
seen_edges.add(edge)
|
| 126 |
+
adjacency[left].add(right)
|
| 127 |
+
adjacency[right].add(left)
|
| 128 |
+
|
| 129 |
+
left_is_donor = (
|
| 130 |
+
left_position != "?"
|
| 131 |
+
and anomeric[left] is not None
|
| 132 |
+
and int(left_position) == anomeric[left]
|
| 133 |
+
)
|
| 134 |
+
right_is_donor = (
|
| 135 |
+
right_position != "?"
|
| 136 |
+
and anomeric[right] is not None
|
| 137 |
+
and int(right_position) == anomeric[right]
|
| 138 |
+
)
|
| 139 |
+
if left_is_donor == right_is_donor:
|
| 140 |
+
orientation_failure = "bond_donor_not_unique"
|
| 141 |
+
continue
|
| 142 |
+
child = left if left_is_donor else right
|
| 143 |
+
parent = right if left_is_donor else left
|
| 144 |
+
if child in child_parent and child_parent[child] != parent:
|
| 145 |
+
orientation_failure = "residue_has_multiple_parents"
|
| 146 |
+
continue
|
| 147 |
+
child_parent[child] = parent
|
| 148 |
+
directed_children[parent].append(child)
|
| 149 |
+
|
| 150 |
+
if len(seen_edges) != count - 1:
|
| 151 |
+
return TreeChannelAnalysis(
|
| 152 |
+
count, False, False, "edge_count_not_residue_count_minus_one", {}, {}, []
|
| 153 |
+
)
|
| 154 |
+
distances = _distance_matrix(adjacency, count)
|
| 155 |
+
if not distances:
|
| 156 |
+
return TreeChannelAnalysis(
|
| 157 |
+
count, False, False, "residue_graph_disconnected", {}, {}, []
|
| 158 |
+
)
|
| 159 |
+
if orientation_failure:
|
| 160 |
+
return TreeChannelAnalysis(
|
| 161 |
+
count, True, False, orientation_failure, {}, {}, distances
|
| 162 |
+
)
|
| 163 |
+
|
| 164 |
+
roots = sorted(set(range(count)) - set(child_parent))
|
| 165 |
+
if len(roots) != 1:
|
| 166 |
+
return TreeChannelAnalysis(
|
| 167 |
+
count, True, False, "root_not_unique", {}, {}, distances
|
| 168 |
+
)
|
| 169 |
+
depths = {roots[0]: 0}
|
| 170 |
+
queue: deque[int] = deque([roots[0]])
|
| 171 |
+
while queue:
|
| 172 |
+
parent = queue.popleft()
|
| 173 |
+
for child in sorted(directed_children.get(parent, [])):
|
| 174 |
+
if child in depths:
|
| 175 |
+
return TreeChannelAnalysis(
|
| 176 |
+
count, True, False, "directed_cycle", {}, {}, distances
|
| 177 |
+
)
|
| 178 |
+
depths[child] = depths[parent] + 1
|
| 179 |
+
queue.append(child)
|
| 180 |
+
if len(depths) != count:
|
| 181 |
+
return TreeChannelAnalysis(
|
| 182 |
+
count, True, False, "directed_tree_disconnected", {}, {}, distances
|
| 183 |
+
)
|
| 184 |
+
if max(depths.values()) >= BRANCH_DEPTH_UNKNOWN:
|
| 185 |
+
return TreeChannelAnalysis(
|
| 186 |
+
count, True, False, "exact_depth_collides_with_unknown_id", {}, {}, distances
|
| 187 |
+
)
|
| 188 |
+
branch_counts = {
|
| 189 |
+
parent: len(children) - 1
|
| 190 |
+
for parent, children in directed_children.items()
|
| 191 |
+
if len(children) > 1
|
| 192 |
+
}
|
| 193 |
+
return TreeChannelAnalysis(
|
| 194 |
+
count, True, True, "", depths, branch_counts, distances
|
| 195 |
+
)
|
| 196 |
+
|
| 197 |
+
@staticmethod
|
| 198 |
+
def exact_linkage_type(linkage: str) -> int:
|
| 199 |
+
match = ReviewA5WURCSPreTokenizerV3.A5_LINKAGE_PATTERN.fullmatch(linkage)
|
| 200 |
+
if match is None:
|
| 201 |
+
return LINKAGE_UNKNOWN
|
| 202 |
+
_, left_position, _, right_position = match.groups()
|
| 203 |
+
if left_position == "?" or right_position == "?":
|
| 204 |
+
return LINKAGE_UNKNOWN
|
| 205 |
+
positions = tuple(sorted((int(left_position), int(right_position))))
|
| 206 |
+
mapping = {
|
| 207 |
+
(1, 2): LINKAGE_1_2,
|
| 208 |
+
(1, 3): LINKAGE_1_3,
|
| 209 |
+
(1, 4): LINKAGE_1_4,
|
| 210 |
+
(1, 6): LINKAGE_1_6,
|
| 211 |
+
(2, 3): LINKAGE_2_3,
|
| 212 |
+
(2, 6): LINKAGE_2_6,
|
| 213 |
+
(3, 6): LINKAGE_3_6,
|
| 214 |
+
}
|
| 215 |
+
return mapping.get(positions, LINKAGE_OTHER_EXACT)
|
| 216 |
+
|
| 217 |
+
def pre_tokenize(self, wurcs: str) -> list[dict]:
|
| 218 |
+
# Reuse only the already-audited semantic WURCS unit extraction. All
|
| 219 |
+
# v2 branch markers, depths, linkage classes, and distance matrices are
|
| 220 |
+
# discarded and rebuilt below.
|
| 221 |
+
inherited = super().pre_tokenize(wurcs)
|
| 222 |
+
units = [dict(unit) for unit in inherited if unit.get("text") != "[BRANCH_OPEN]"]
|
| 223 |
+
analysis = self.analyze_tree(wurcs)
|
| 224 |
+
first_unit_for_residue: set[int] = set()
|
| 225 |
+
repaired: list[dict] = []
|
| 226 |
+
for unit in units:
|
| 227 |
+
unit.pop("distance_matrix", None)
|
| 228 |
+
residue_id = int(unit.get("residue_id", -1))
|
| 229 |
+
unit["linkage_type"] = LINKAGE_NONE
|
| 230 |
+
if residue_id >= 0:
|
| 231 |
+
depth = (
|
| 232 |
+
analysis.depths[residue_id]
|
| 233 |
+
if analysis.exact_rooted_tree
|
| 234 |
+
else BRANCH_DEPTH_UNKNOWN
|
| 235 |
+
)
|
| 236 |
+
unit["branch_depth"] = depth
|
| 237 |
+
if residue_id not in first_unit_for_residue:
|
| 238 |
+
for _ in range(analysis.branch_open_counts.get(residue_id, 0)):
|
| 239 |
+
repaired.append(
|
| 240 |
+
{
|
| 241 |
+
"text": "[BRANCH_OPEN]",
|
| 242 |
+
"type": "special",
|
| 243 |
+
"residue_id": -1,
|
| 244 |
+
"branch_depth": depth,
|
| 245 |
+
"linkage_type": LINKAGE_NONE,
|
| 246 |
+
}
|
| 247 |
+
)
|
| 248 |
+
first_unit_for_residue.add(residue_id)
|
| 249 |
+
else:
|
| 250 |
+
unit["branch_depth"] = 0
|
| 251 |
+
if unit.get("type") == "linkage":
|
| 252 |
+
unit["linkage_type"] = self.exact_linkage_type(str(unit["text"]))
|
| 253 |
+
repaired.append(unit)
|
| 254 |
+
|
| 255 |
+
if repaired:
|
| 256 |
+
repaired[0]["distance_matrix"] = analysis.distance_matrix
|
| 257 |
+
repaired[0]["tree_channels_valid"] = analysis.exact_rooted_tree
|
| 258 |
+
repaired[0]["tree_channel_failure_reason"] = analysis.failure_reason
|
| 259 |
+
return repaired
|
| 260 |
+
|
| 261 |
+
|
| 262 |
+
class ReviewA5WURCSBPETokenizerV3(A5WURCSBPETokenizer):
|
| 263 |
+
"""Existing train-only BPE vocabulary with repaired transform channels."""
|
| 264 |
+
|
| 265 |
+
def __init__(self, vocab_path: Optional[str | Path] = None) -> None:
|
| 266 |
+
super().__init__(vocab_path)
|
| 267 |
+
self.pre_tokenizer = ReviewA5WURCSPreTokenizerV3()
|
| 268 |
+
|
| 269 |
+
def tokenize_sequence(self, wurcs: str, max_length: int = 256) -> dict:
|
| 270 |
+
encoded = super().tokenize_sequence(wurcs, max_length=max_length)
|
| 271 |
+
analysis = self.pre_tokenizer.analyze_tree(wurcs)
|
| 272 |
+
encoded["tree_channels_valid"] = analysis.exact_rooted_tree
|
| 273 |
+
encoded["tree_channel_failure_reason"] = analysis.failure_reason
|
| 274 |
+
return encoded
|
| 275 |
+
|
| 276 |
+
|
| 277 |
+
__all__ = [
|
| 278 |
+
"BRANCH_DEPTH_UNKNOWN",
|
| 279 |
+
"BRANCH_DEPTH_VOCAB_SIZE",
|
| 280 |
+
"LINKAGE_NONE",
|
| 281 |
+
"LINKAGE_OTHER_EXACT",
|
| 282 |
+
"LINKAGE_UNKNOWN",
|
| 283 |
+
"LINKAGE_VOCAB_SIZE",
|
| 284 |
+
"ReviewA5WURCSBPETokenizerV3",
|
| 285 |
+
"ReviewA5WURCSPreTokenizerV3",
|
| 286 |
+
"TreeChannelAnalysis",
|
| 287 |
+
]
|
releases/2026-10-02/iar_completion/runtime_snapshot/project/data/review_sequences_a5_non_iar_later_role_official_array_v4_20260721_r1/review_frozen_training_a5_topology.py
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Residue-level shortest-path targets used by the A5 topology objective."""
|
| 2 |
+
|
| 3 |
+
from __future__ import annotations
|
| 4 |
+
|
| 5 |
+
import hashlib
|
| 6 |
+
import json
|
| 7 |
+
import re
|
| 8 |
+
from collections import deque
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
EDGE_RE = re.compile(
|
| 12 |
+
r"(?P<n1>[A-Za-z]+)(?P<p1>[0-9?]+)-(?P<n2>[A-Za-z]+)(?P<p2>[0-9?]+)"
|
| 13 |
+
)
|
| 14 |
+
RESDEF_RE = re.compile(r"\[([^\]]*)\]")
|
| 15 |
+
WURCS_RES_INDEX_ALPHABET = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
def node_label(index: int) -> str:
|
| 19 |
+
if index < 1:
|
| 20 |
+
raise ValueError("WURCS residue indices are one-based")
|
| 21 |
+
letters = WURCS_RES_INDEX_ALPHABET
|
| 22 |
+
base = len(letters)
|
| 23 |
+
index -= 1
|
| 24 |
+
label = ""
|
| 25 |
+
while True:
|
| 26 |
+
label = letters[index % base] + label
|
| 27 |
+
index = index // base - 1
|
| 28 |
+
if index < 0:
|
| 29 |
+
return label
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
def node_index(label: str) -> int:
|
| 33 |
+
if not label:
|
| 34 |
+
raise ValueError("WURCS residue label cannot be empty")
|
| 35 |
+
base = len(WURCS_RES_INDEX_ALPHABET)
|
| 36 |
+
value = 0
|
| 37 |
+
for character in label:
|
| 38 |
+
try:
|
| 39 |
+
digit = WURCS_RES_INDEX_ALPHABET.index(character) + 1
|
| 40 |
+
except ValueError as error:
|
| 41 |
+
raise ValueError(f"Invalid WURCS residue label: {label}") from error
|
| 42 |
+
value = value * base + digit
|
| 43 |
+
return value
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
def split_wurcs_sections(body: str) -> list[str]:
|
| 47 |
+
sections: list[str] = []
|
| 48 |
+
current: list[str] = []
|
| 49 |
+
bracket_depth = 0
|
| 50 |
+
for character in body:
|
| 51 |
+
if character == "[":
|
| 52 |
+
bracket_depth += 1
|
| 53 |
+
elif character == "]" and bracket_depth:
|
| 54 |
+
bracket_depth -= 1
|
| 55 |
+
if character == "/" and bracket_depth == 0:
|
| 56 |
+
sections.append("".join(current))
|
| 57 |
+
current = []
|
| 58 |
+
else:
|
| 59 |
+
current.append(character)
|
| 60 |
+
sections.append("".join(current))
|
| 61 |
+
return sections
|
| 62 |
+
|
| 63 |
+
|
| 64 |
+
def split_wurcs(wurcs: str) -> tuple[list[str], dict[str, str], str]:
|
| 65 |
+
if not wurcs.startswith("WURCS=2.0/"):
|
| 66 |
+
return [], {}, ""
|
| 67 |
+
parts = split_wurcs_sections(wurcs[len("WURCS=2.0/") :])
|
| 68 |
+
if len(parts) < 4:
|
| 69 |
+
return [], {}, ""
|
| 70 |
+
residue_definitions = RESDEF_RE.findall(parts[1])
|
| 71 |
+
sequence = parts[2].split("-") if parts[2] else []
|
| 72 |
+
node_to_residue: dict[str, str] = {}
|
| 73 |
+
for index, value in enumerate(sequence, start=1):
|
| 74 |
+
try:
|
| 75 |
+
residue = residue_definitions[int(value) - 1]
|
| 76 |
+
except (ValueError, IndexError):
|
| 77 |
+
residue = ""
|
| 78 |
+
node_to_residue[node_label(index)] = residue
|
| 79 |
+
return residue_definitions, node_to_residue, "/".join(parts[3:])
|
| 80 |
+
|
| 81 |
+
|
| 82 |
+
def _hash_fields(*values: object) -> str:
|
| 83 |
+
payload = "\x1f".join(str(value) for value in values).encode("utf-8")
|
| 84 |
+
return hashlib.sha256(payload).hexdigest()
|
| 85 |
+
|
| 86 |
+
|
| 87 |
+
def build_residue_shortest_path(wurcs: str) -> dict[str, object]:
|
| 88 |
+
"""Build the same immutable residue target frozen by the P0/P1 audit."""
|
| 89 |
+
_, node_to_residue, linkage_section = split_wurcs(wurcs)
|
| 90 |
+
node_ids = list(node_to_residue)
|
| 91 |
+
if not node_ids or any(not node_to_residue[node] for node in node_ids):
|
| 92 |
+
return _failure("missing_or_unmapped_residue_sequence", len(node_ids), 0)
|
| 93 |
+
if len(node_ids) < 2:
|
| 94 |
+
return _failure(
|
| 95 |
+
"fewer_than_two_residues_no_off_diagonal_target", len(node_ids), 0
|
| 96 |
+
)
|
| 97 |
+
|
| 98 |
+
adjacency: dict[str, set[str]] = {node: set() for node in node_ids}
|
| 99 |
+
parsed_edges: list[tuple[str, str]] = []
|
| 100 |
+
unparsed_tokens: list[str] = []
|
| 101 |
+
for token in linkage_section.split("_") if linkage_section else []:
|
| 102 |
+
match = EDGE_RE.fullmatch(token)
|
| 103 |
+
if not match:
|
| 104 |
+
if token:
|
| 105 |
+
unparsed_tokens.append(token)
|
| 106 |
+
continue
|
| 107 |
+
left, right = match.group("n1"), match.group("n2")
|
| 108 |
+
if left not in adjacency or right not in adjacency or left == right:
|
| 109 |
+
unparsed_tokens.append(token)
|
| 110 |
+
continue
|
| 111 |
+
parsed_edges.append(tuple(sorted((left, right))))
|
| 112 |
+
adjacency[left].add(right)
|
| 113 |
+
adjacency[right].add(left)
|
| 114 |
+
|
| 115 |
+
reason = ""
|
| 116 |
+
if unparsed_tokens:
|
| 117 |
+
reason = "one_or_more_edge_tokens_not_unambiguous_residue_pairs"
|
| 118 |
+
elif len(set(parsed_edges)) != len(parsed_edges):
|
| 119 |
+
reason = "duplicate_residue_edge"
|
| 120 |
+
elif len(parsed_edges) != len(node_ids) - 1:
|
| 121 |
+
reason = "edge_count_not_residue_count_minus_one"
|
| 122 |
+
|
| 123 |
+
seen = {node_ids[0]}
|
| 124 |
+
queue = deque([node_ids[0]])
|
| 125 |
+
while queue:
|
| 126 |
+
node = queue.popleft()
|
| 127 |
+
for neighbor in sorted(adjacency[node]):
|
| 128 |
+
if neighbor not in seen:
|
| 129 |
+
seen.add(neighbor)
|
| 130 |
+
queue.append(neighbor)
|
| 131 |
+
if not reason and len(seen) != len(node_ids):
|
| 132 |
+
reason = "residue_graph_disconnected"
|
| 133 |
+
if reason:
|
| 134 |
+
return _failure(reason, len(node_ids), len(parsed_edges))
|
| 135 |
+
|
| 136 |
+
matrix: list[list[int]] = []
|
| 137 |
+
for source in node_ids:
|
| 138 |
+
distance = {source: 0}
|
| 139 |
+
queue = deque([source])
|
| 140 |
+
while queue:
|
| 141 |
+
node = queue.popleft()
|
| 142 |
+
for neighbor in sorted(adjacency[node]):
|
| 143 |
+
if neighbor not in distance:
|
| 144 |
+
distance[neighbor] = distance[node] + 1
|
| 145 |
+
queue.append(neighbor)
|
| 146 |
+
matrix.append([distance[target] for target in node_ids])
|
| 147 |
+
|
| 148 |
+
matrix_payload = json.dumps(matrix, separators=(",", ":"))
|
| 149 |
+
matrix_sha256 = hashlib.sha256(matrix_payload.encode("utf-8")).hexdigest()
|
| 150 |
+
return {
|
| 151 |
+
"target_valid": True,
|
| 152 |
+
"failure_reason": "",
|
| 153 |
+
"residue_count": len(node_ids),
|
| 154 |
+
"parsed_edge_count": len(parsed_edges),
|
| 155 |
+
"valid_unordered_pair_count": len(node_ids) * (len(node_ids) - 1) // 2,
|
| 156 |
+
"matrix": matrix,
|
| 157 |
+
"matrix_sha256": matrix_sha256,
|
| 158 |
+
"target_identity_sha256": _hash_fields(
|
| 159 |
+
"residue_shortest_path_v2",
|
| 160 |
+
wurcs,
|
| 161 |
+
matrix_sha256,
|
| 162 |
+
len(node_ids),
|
| 163 |
+
len(parsed_edges),
|
| 164 |
+
),
|
| 165 |
+
"schema": "residue_shortest_path_v2",
|
| 166 |
+
}
|
| 167 |
+
|
| 168 |
+
|
| 169 |
+
def _failure(reason: str, residues: int, edges: int) -> dict[str, object]:
|
| 170 |
+
return {
|
| 171 |
+
"target_valid": False,
|
| 172 |
+
"failure_reason": reason,
|
| 173 |
+
"residue_count": residues,
|
| 174 |
+
"parsed_edge_count": edges,
|
| 175 |
+
"valid_unordered_pair_count": 0,
|
| 176 |
+
"matrix": [],
|
| 177 |
+
"matrix_sha256": "",
|
| 178 |
+
"target_identity_sha256": "",
|
| 179 |
+
"schema": "residue_shortest_path_v2",
|
| 180 |
+
}
|
releases/2026-10-02/iar_completion/runtime_snapshot/project/data/review_sequences_a5_non_iar_later_role_official_array_v4_20260721_r1/review_frozen_training_a5_wurcs_bpe.py
ADDED
|
@@ -0,0 +1,368 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Deterministic train-only WURCS BPE utilities for A5."""
|
| 2 |
+
|
| 3 |
+
from __future__ import annotations
|
| 4 |
+
|
| 5 |
+
import re
|
| 6 |
+
from collections import Counter, defaultdict
|
| 7 |
+
from pathlib import Path
|
| 8 |
+
from typing import Iterable, Optional
|
| 9 |
+
|
| 10 |
+
from .a5_topology import node_index, node_label
|
| 11 |
+
|
| 12 |
+
try:
|
| 13 |
+
from bert_training_v4.downstream_tasks.utils.wurcs_bpe_tokenizer import (
|
| 14 |
+
WURCSBPETokenizer,
|
| 15 |
+
WURCSPreTokenizer,
|
| 16 |
+
)
|
| 17 |
+
except ImportError:
|
| 18 |
+
from ..bert_training_v4.downstream_tasks.utils.wurcs_bpe_tokenizer import (
|
| 19 |
+
WURCSBPETokenizer,
|
| 20 |
+
WURCSPreTokenizer,
|
| 21 |
+
)
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
SUBMITTED_FIT_ALPHABET = tuple(
|
| 25 |
+
"#$%()*-./0123456789<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZ^abcdefghijklmnopqrstuvwxyz{|}~"
|
| 26 |
+
)
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
class _TopLevelBracketPattern:
|
| 30 |
+
"""Expose regex-like findall while respecting nested SMILES brackets."""
|
| 31 |
+
|
| 32 |
+
@staticmethod
|
| 33 |
+
def findall(text: str) -> list[str]:
|
| 34 |
+
residues: list[str] = []
|
| 35 |
+
depth = 0
|
| 36 |
+
start = -1
|
| 37 |
+
for index, character in enumerate(text):
|
| 38 |
+
if character == "[":
|
| 39 |
+
if depth == 0:
|
| 40 |
+
start = index + 1
|
| 41 |
+
depth += 1
|
| 42 |
+
elif character == "]" and depth:
|
| 43 |
+
depth -= 1
|
| 44 |
+
if depth == 0 and start >= 0:
|
| 45 |
+
residues.append(text[start:index])
|
| 46 |
+
start = -1
|
| 47 |
+
if depth:
|
| 48 |
+
return []
|
| 49 |
+
return residues
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
class A5WURCSPreTokenizer(WURCSPreTokenizer):
|
| 53 |
+
"""Submitted pre-tokenizer with nested bracket-safe residue extraction."""
|
| 54 |
+
|
| 55 |
+
A5_LINKAGE_PATTERN = re.compile(
|
| 56 |
+
r"([A-Za-z]+)(\d+|\?)-([A-Za-z]+)(\d+|\?)"
|
| 57 |
+
)
|
| 58 |
+
A5_ANOMERIC_PATTERN = re.compile(r"-([0-9]+)([abuxo])(?:_|$)")
|
| 59 |
+
|
| 60 |
+
def __init__(self) -> None:
|
| 61 |
+
super().__init__()
|
| 62 |
+
self.RESIDUE_PATTERN = _TopLevelBracketPattern()
|
| 63 |
+
|
| 64 |
+
def _split_wurcs_sections(self, wurcs: str) -> list[str]:
|
| 65 |
+
sections = super()._split_wurcs_sections(wurcs)
|
| 66 |
+
if len(sections) <= 5:
|
| 67 |
+
return sections
|
| 68 |
+
# WURCS LIN modifications may contain unbracketed slashes. The format
|
| 69 |
+
# has exactly five top-level sections, so every trailing fragment
|
| 70 |
+
# belongs to the linkage section rather than a new section.
|
| 71 |
+
return sections[:4] + ["/".join(sections[4:])]
|
| 72 |
+
|
| 73 |
+
def _instance_anomeric_positions(
|
| 74 |
+
self, residue_definitions: list[str], index_list: list[str]
|
| 75 |
+
) -> list[int | None]:
|
| 76 |
+
positions: list[int | None] = []
|
| 77 |
+
for definition_index in index_list:
|
| 78 |
+
try:
|
| 79 |
+
residue_definition = residue_definitions[int(definition_index) - 1]
|
| 80 |
+
except (IndexError, ValueError):
|
| 81 |
+
positions.append(None)
|
| 82 |
+
continue
|
| 83 |
+
match = self.A5_ANOMERIC_PATTERN.search(residue_definition)
|
| 84 |
+
positions.append(int(match.group(1)) if match is not None else None)
|
| 85 |
+
return positions
|
| 86 |
+
|
| 87 |
+
def _analyze_a5_tree(
|
| 88 |
+
self,
|
| 89 |
+
linkages: list[str],
|
| 90 |
+
residue_count: int,
|
| 91 |
+
anomeric_positions: list[int | None] | None = None,
|
| 92 |
+
) -> tuple[dict[str, int], dict[str, int], dict[int, list[int]]]:
|
| 93 |
+
branch_points: dict[str, int] = defaultdict(int)
|
| 94 |
+
children: dict[str, list[str]] = defaultdict(list)
|
| 95 |
+
all_residues: set[str] = set()
|
| 96 |
+
adjacency: dict[int, list[int]] = defaultdict(list)
|
| 97 |
+
for linkage in linkages:
|
| 98 |
+
match = self.A5_LINKAGE_PATTERN.match(linkage)
|
| 99 |
+
if not match:
|
| 100 |
+
continue
|
| 101 |
+
left, left_position, right, right_position = match.groups()
|
| 102 |
+
try:
|
| 103 |
+
left_index = node_index(left) - 1
|
| 104 |
+
right_index = node_index(right) - 1
|
| 105 |
+
except ValueError:
|
| 106 |
+
continue
|
| 107 |
+
if not (
|
| 108 |
+
0 <= left_index < residue_count
|
| 109 |
+
and 0 <= right_index < residue_count
|
| 110 |
+
and left_index != right_index
|
| 111 |
+
):
|
| 112 |
+
continue
|
| 113 |
+
parent, child = left, right
|
| 114 |
+
if anomeric_positions is not None:
|
| 115 |
+
left_anomeric = anomeric_positions[left_index]
|
| 116 |
+
right_anomeric = anomeric_positions[right_index]
|
| 117 |
+
left_is_donor = (
|
| 118 |
+
left_position != "?"
|
| 119 |
+
and left_anomeric is not None
|
| 120 |
+
and int(left_position) == left_anomeric
|
| 121 |
+
)
|
| 122 |
+
right_is_donor = (
|
| 123 |
+
right_position != "?"
|
| 124 |
+
and right_anomeric is not None
|
| 125 |
+
and int(right_position) == right_anomeric
|
| 126 |
+
)
|
| 127 |
+
if left_is_donor and not right_is_donor:
|
| 128 |
+
parent, child = right, left
|
| 129 |
+
elif right_is_donor and not left_is_donor:
|
| 130 |
+
parent, child = left, right
|
| 131 |
+
children[parent].append(child)
|
| 132 |
+
all_residues.update((parent, child))
|
| 133 |
+
adjacency[left_index].append(right_index)
|
| 134 |
+
adjacency[right_index].append(left_index)
|
| 135 |
+
|
| 136 |
+
for residue, child_labels in children.items():
|
| 137 |
+
if len(child_labels) > 1:
|
| 138 |
+
branch_points[residue] = len(child_labels) - 1
|
| 139 |
+
child_set = {child for values in children.values() for child in values}
|
| 140 |
+
roots = all_residues - child_set
|
| 141 |
+
root = min(roots, key=node_index) if roots else node_label(1)
|
| 142 |
+
depths = {root: 0}
|
| 143 |
+
queue = [root]
|
| 144 |
+
while queue:
|
| 145 |
+
current = queue.pop(0)
|
| 146 |
+
for child in children.get(current, []):
|
| 147 |
+
if child not in depths:
|
| 148 |
+
depths[child] = depths[current] + 1
|
| 149 |
+
queue.append(child)
|
| 150 |
+
return dict(branch_points), depths, adjacency
|
| 151 |
+
|
| 152 |
+
def _a5_linkage_type(self, linkage: str) -> int:
|
| 153 |
+
match = self.A5_LINKAGE_PATTERN.match(linkage)
|
| 154 |
+
if not match:
|
| 155 |
+
return 8
|
| 156 |
+
_, from_position, _, to_position = match.groups()
|
| 157 |
+
try:
|
| 158 |
+
positions = (int(from_position), int(to_position))
|
| 159 |
+
except ValueError:
|
| 160 |
+
return 8
|
| 161 |
+
linkage_types = {
|
| 162 |
+
(1, 2): 0,
|
| 163 |
+
(2, 1): 0,
|
| 164 |
+
(1, 3): 1,
|
| 165 |
+
(3, 1): 1,
|
| 166 |
+
(1, 4): 2,
|
| 167 |
+
(4, 1): 2,
|
| 168 |
+
(1, 6): 3,
|
| 169 |
+
(6, 1): 3,
|
| 170 |
+
(2, 3): 4,
|
| 171 |
+
(3, 2): 4,
|
| 172 |
+
(2, 6): 5,
|
| 173 |
+
(6, 2): 5,
|
| 174 |
+
(3, 6): 6,
|
| 175 |
+
(6, 3): 6,
|
| 176 |
+
}
|
| 177 |
+
return linkage_types.get(positions, 7)
|
| 178 |
+
|
| 179 |
+
def pre_tokenize(self, wurcs: str) -> list[dict]:
|
| 180 |
+
# Reuse the submitted semantic split, then correct only its tree
|
| 181 |
+
# annotations. This keeps the BPE unit text and special-token behavior.
|
| 182 |
+
inherited_units = super().pre_tokenize(wurcs)
|
| 183 |
+
try:
|
| 184 |
+
parts = self._split_wurcs_sections(wurcs)
|
| 185 |
+
index_list = parts[3].split("-") if len(parts) > 3 and parts[3] else []
|
| 186 |
+
linkages = parts[4].split("_") if len(parts) > 4 and parts[4] else []
|
| 187 |
+
residue_definitions = self.RESIDUE_PATTERN.findall(parts[2])
|
| 188 |
+
anomeric_positions = self._instance_anomeric_positions(
|
| 189 |
+
residue_definitions, index_list
|
| 190 |
+
)
|
| 191 |
+
branch_points, depths, adjacency = self._analyze_a5_tree(
|
| 192 |
+
linkages, len(index_list), anomeric_positions
|
| 193 |
+
)
|
| 194 |
+
except (IndexError, ValueError):
|
| 195 |
+
return inherited_units
|
| 196 |
+
|
| 197 |
+
units: list[dict] = []
|
| 198 |
+
opened_residues: set[int] = set()
|
| 199 |
+
for inherited in inherited_units:
|
| 200 |
+
if inherited.get("text") == "[BRANCH_OPEN]":
|
| 201 |
+
continue
|
| 202 |
+
unit = dict(inherited)
|
| 203 |
+
residue_id = int(unit.get("residue_id", -1))
|
| 204 |
+
if residue_id >= 0:
|
| 205 |
+
label = node_label(residue_id + 1)
|
| 206 |
+
if residue_id not in opened_residues:
|
| 207 |
+
for _ in range(branch_points.get(label, 0)):
|
| 208 |
+
units.append(
|
| 209 |
+
{
|
| 210 |
+
"text": "[BRANCH_OPEN]",
|
| 211 |
+
"type": "special",
|
| 212 |
+
"residue_id": -1,
|
| 213 |
+
"branch_depth": depths.get(label, 0),
|
| 214 |
+
"linkage_type": 0,
|
| 215 |
+
}
|
| 216 |
+
)
|
| 217 |
+
opened_residues.add(residue_id)
|
| 218 |
+
unit["branch_depth"] = depths.get(label, 0)
|
| 219 |
+
elif unit.get("type") == "linkage":
|
| 220 |
+
unit["linkage_type"] = self._a5_linkage_type(str(unit["text"]))
|
| 221 |
+
units.append(unit)
|
| 222 |
+
|
| 223 |
+
if units:
|
| 224 |
+
units[0]["distance_matrix"] = self._compute_distance_matrix(
|
| 225 |
+
adjacency, len(index_list)
|
| 226 |
+
)
|
| 227 |
+
return units
|
| 228 |
+
|
| 229 |
+
|
| 230 |
+
class A5WURCSBPETokenizer(WURCSBPETokenizer):
|
| 231 |
+
"""Train-only BPE with a fit-derived alphabet and deterministic merge ties."""
|
| 232 |
+
|
| 233 |
+
def __init__(self, vocab_path: Optional[str | Path] = None) -> None:
|
| 234 |
+
super().__init__(str(vocab_path) if vocab_path is not None else None)
|
| 235 |
+
self.pre_tokenizer = A5WURCSPreTokenizer()
|
| 236 |
+
|
| 237 |
+
@classmethod
|
| 238 |
+
def train_from_fit_corpus(
|
| 239 |
+
cls,
|
| 240 |
+
wurcs_strings: Iterable[str],
|
| 241 |
+
num_merges: int = 2000,
|
| 242 |
+
output_path: Optional[str | Path] = None,
|
| 243 |
+
min_frequency: int = 2,
|
| 244 |
+
max_token_length: Optional[int] = None,
|
| 245 |
+
) -> "A5WURCSBPETokenizer":
|
| 246 |
+
tokenizer = cls()
|
| 247 |
+
pre_tokenizer = tokenizer.pre_tokenizer
|
| 248 |
+
unit_counts: Counter[str] = Counter()
|
| 249 |
+
for wurcs in wurcs_strings:
|
| 250 |
+
for unit in pre_tokenizer.pre_tokenize(wurcs):
|
| 251 |
+
if unit["type"] != "special":
|
| 252 |
+
unit_counts[unit["text"]] += 1
|
| 253 |
+
|
| 254 |
+
# The submitted tokenizer learned the base character inventory from its
|
| 255 |
+
# corpus. Preserve that behavior, but fit it from training parents only.
|
| 256 |
+
tokenizer.fit_alphabet = tuple(
|
| 257 |
+
sorted({char for unit in unit_counts for char in unit})
|
| 258 |
+
)
|
| 259 |
+
|
| 260 |
+
next_id = len(tokenizer.special_tokens)
|
| 261 |
+
for char in tokenizer.fit_alphabet:
|
| 262 |
+
tokenizer.token_to_id[char] = next_id
|
| 263 |
+
tokenizer.id_to_token[next_id] = char
|
| 264 |
+
next_id += 1
|
| 265 |
+
|
| 266 |
+
word_freqs: dict[tuple[str, ...], int] = {
|
| 267 |
+
tuple(unit): count
|
| 268 |
+
for unit, count in sorted(unit_counts.items())
|
| 269 |
+
if count >= min_frequency
|
| 270 |
+
}
|
| 271 |
+
merges: list[tuple[str, str]] = []
|
| 272 |
+
for _ in range(num_merges):
|
| 273 |
+
pair_counts: Counter[tuple[str, str]] = Counter()
|
| 274 |
+
for word, frequency in word_freqs.items():
|
| 275 |
+
for index in range(len(word) - 1):
|
| 276 |
+
pair_counts[(word[index], word[index + 1])] += frequency
|
| 277 |
+
candidates = [
|
| 278 |
+
(pair, count)
|
| 279 |
+
for pair, count in pair_counts.items()
|
| 280 |
+
if count >= min_frequency
|
| 281 |
+
and (
|
| 282 |
+
max_token_length is None
|
| 283 |
+
or len(pair[0]) + len(pair[1]) <= max_token_length
|
| 284 |
+
)
|
| 285 |
+
]
|
| 286 |
+
if not candidates:
|
| 287 |
+
break
|
| 288 |
+
best_pair, _ = min(
|
| 289 |
+
candidates,
|
| 290 |
+
key=lambda item: (-item[1], item[0][0], item[0][1]),
|
| 291 |
+
)
|
| 292 |
+
new_token = best_pair[0] + best_pair[1]
|
| 293 |
+
merges.append(best_pair)
|
| 294 |
+
tokenizer.token_to_id[new_token] = next_id
|
| 295 |
+
tokenizer.id_to_token[next_id] = new_token
|
| 296 |
+
next_id += 1
|
| 297 |
+
|
| 298 |
+
merged_freqs: Counter[tuple[str, ...]] = Counter()
|
| 299 |
+
for word, frequency in word_freqs.items():
|
| 300 |
+
merged_word: list[str] = []
|
| 301 |
+
index = 0
|
| 302 |
+
while index < len(word):
|
| 303 |
+
if (
|
| 304 |
+
index < len(word) - 1
|
| 305 |
+
and word[index] == best_pair[0]
|
| 306 |
+
and word[index + 1] == best_pair[1]
|
| 307 |
+
):
|
| 308 |
+
merged_word.append(new_token)
|
| 309 |
+
index += 2
|
| 310 |
+
else:
|
| 311 |
+
merged_word.append(word[index])
|
| 312 |
+
index += 1
|
| 313 |
+
merged_freqs[tuple(merged_word)] += frequency
|
| 314 |
+
word_freqs = dict(merged_freqs)
|
| 315 |
+
|
| 316 |
+
tokenizer.merges = merges
|
| 317 |
+
if output_path is not None:
|
| 318 |
+
tokenizer.save_vocab(str(output_path))
|
| 319 |
+
return tokenizer
|
| 320 |
+
|
| 321 |
+
def tokenize_sequence(self, wurcs: str, max_length: int = 256) -> dict:
|
| 322 |
+
units = self.pre_tokenizer.pre_tokenize(wurcs)
|
| 323 |
+
tokens: list[str] = []
|
| 324 |
+
token_ids: list[int] = []
|
| 325 |
+
residue_ids: list[int] = []
|
| 326 |
+
branch_depths: list[int] = []
|
| 327 |
+
linkage_types: list[int] = []
|
| 328 |
+
|
| 329 |
+
for unit in units:
|
| 330 |
+
unit_tokens = (
|
| 331 |
+
[unit["text"]]
|
| 332 |
+
if unit["type"] == "special"
|
| 333 |
+
else self.apply_bpe(unit["text"])
|
| 334 |
+
)
|
| 335 |
+
for token in unit_tokens:
|
| 336 |
+
tokens.append(token)
|
| 337 |
+
token_ids.append(
|
| 338 |
+
self.token_to_id.get(token, self.token_to_id["[UNK]"])
|
| 339 |
+
)
|
| 340 |
+
residue_ids.append(int(unit["residue_id"]))
|
| 341 |
+
branch_depths.append(int(unit["branch_depth"]))
|
| 342 |
+
linkage_types.append(int(unit["linkage_type"]))
|
| 343 |
+
|
| 344 |
+
if len(tokens) > max_length:
|
| 345 |
+
tokens = tokens[: max_length - 1] + ["[END]"]
|
| 346 |
+
token_ids = token_ids[: max_length - 1] + [self.token_to_id["[END]"]]
|
| 347 |
+
residue_ids = residue_ids[: max_length - 1] + [-1]
|
| 348 |
+
branch_depths = branch_depths[: max_length - 1] + [0]
|
| 349 |
+
linkage_types = linkage_types[: max_length - 1] + [0]
|
| 350 |
+
|
| 351 |
+
length = len(tokens)
|
| 352 |
+
attention_mask = [1] * length
|
| 353 |
+
padding = max_length - length
|
| 354 |
+
tokens.extend(["[PAD]"] * padding)
|
| 355 |
+
token_ids.extend([self.token_to_id["[PAD]"]] * padding)
|
| 356 |
+
residue_ids.extend([-1] * padding)
|
| 357 |
+
branch_depths.extend([0] * padding)
|
| 358 |
+
linkage_types.extend([0] * padding)
|
| 359 |
+
attention_mask.extend([0] * padding)
|
| 360 |
+
return {
|
| 361 |
+
"tokens": tokens,
|
| 362 |
+
"token_ids": token_ids,
|
| 363 |
+
"residue_ids": residue_ids,
|
| 364 |
+
"branch_depths": branch_depths,
|
| 365 |
+
"linkage_types": linkage_types,
|
| 366 |
+
"attention_mask": attention_mask,
|
| 367 |
+
"length": length,
|
| 368 |
+
}
|
releases/2026-10-02/iar_completion/runtime_snapshot/project/writing/cluster/nature_submission/code/model/__init__.py
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Model module
|
| 2 |
+
from .multimodal_glycan_bert_v3 import MultimodalGlycanBERT, MultimodalGlycanBERTConfig
|
| 3 |
+
|
releases/2026-10-02/iar_completion/runtime_snapshot/project/writing/cluster/nature_submission/code/model/glycan_bert.py
ADDED
|
@@ -0,0 +1,303 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Glycan BERT Model
|
| 3 |
+
|
| 4 |
+
Transformer-based masked language model for glycan structures.
|
| 5 |
+
Based on BERT/ESM2 architecture adapted for atomic glycan tokenization.
|
| 6 |
+
"""
|
| 7 |
+
|
| 8 |
+
import torch
|
| 9 |
+
import torch.nn as nn
|
| 10 |
+
import math
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
class GlycanBERTConfig:
|
| 14 |
+
"""Configuration for GlycanBERT."""
|
| 15 |
+
|
| 16 |
+
def __init__(
|
| 17 |
+
self,
|
| 18 |
+
vocab_size: int = 102,
|
| 19 |
+
hidden_size: int = 384,
|
| 20 |
+
num_hidden_layers: int = 6,
|
| 21 |
+
num_attention_heads: int = 6,
|
| 22 |
+
intermediate_size: int = 1536,
|
| 23 |
+
hidden_dropout_prob: float = 0.1,
|
| 24 |
+
attention_probs_dropout_prob: float = 0.1,
|
| 25 |
+
max_position_embeddings: int = 512,
|
| 26 |
+
layer_norm_eps: float = 1e-12,
|
| 27 |
+
pad_token_id: int = 0,
|
| 28 |
+
mask_token_id: int = 4,
|
| 29 |
+
initializer_range: float = 0.02
|
| 30 |
+
):
|
| 31 |
+
self.vocab_size = vocab_size
|
| 32 |
+
self.hidden_size = hidden_size
|
| 33 |
+
self.num_hidden_layers = num_hidden_layers
|
| 34 |
+
self.num_attention_heads = num_attention_heads
|
| 35 |
+
self.intermediate_size = intermediate_size
|
| 36 |
+
self.hidden_dropout_prob = hidden_dropout_prob
|
| 37 |
+
self.attention_probs_dropout_prob = attention_probs_dropout_prob
|
| 38 |
+
self.max_position_embeddings = max_position_embeddings
|
| 39 |
+
self.layer_norm_eps = layer_norm_eps
|
| 40 |
+
self.pad_token_id = pad_token_id
|
| 41 |
+
self.mask_token_id = mask_token_id
|
| 42 |
+
self.initializer_range = initializer_range
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
class GlycanBERTEmbeddings(nn.Module):
|
| 46 |
+
"""
|
| 47 |
+
Embeddings for glycan tokens including token and positional embeddings.
|
| 48 |
+
"""
|
| 49 |
+
|
| 50 |
+
def __init__(self, config: GlycanBERTConfig):
|
| 51 |
+
super().__init__()
|
| 52 |
+
self.token_embeddings = nn.Embedding(config.vocab_size, config.hidden_size, padding_idx=config.pad_token_id)
|
| 53 |
+
self.position_embeddings = nn.Embedding(config.max_position_embeddings, config.hidden_size)
|
| 54 |
+
|
| 55 |
+
self.LayerNorm = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)
|
| 56 |
+
self.dropout = nn.Dropout(config.hidden_dropout_prob)
|
| 57 |
+
|
| 58 |
+
# position_ids (1, max_seq_len) is contiguous in memory and exported when serialized
|
| 59 |
+
self.register_buffer("position_ids", torch.arange(config.max_position_embeddings).expand((1, -1)))
|
| 60 |
+
|
| 61 |
+
def forward(self, input_ids: torch.Tensor) -> torch.Tensor:
|
| 62 |
+
"""
|
| 63 |
+
Args:
|
| 64 |
+
input_ids: Tensor of shape (batch_size, seq_len)
|
| 65 |
+
|
| 66 |
+
Returns:
|
| 67 |
+
Embeddings of shape (batch_size, seq_len, hidden_size)
|
| 68 |
+
"""
|
| 69 |
+
batch_size, seq_len = input_ids.shape
|
| 70 |
+
|
| 71 |
+
# Token embeddings
|
| 72 |
+
token_embeds = self.token_embeddings(input_ids)
|
| 73 |
+
|
| 74 |
+
# Position embeddings
|
| 75 |
+
position_ids = self.position_ids[:, :seq_len]
|
| 76 |
+
position_embeds = self.position_embeddings(position_ids)
|
| 77 |
+
|
| 78 |
+
# Combine
|
| 79 |
+
embeddings = token_embeds + position_embeds
|
| 80 |
+
embeddings = self.LayerNorm(embeddings)
|
| 81 |
+
embeddings = self.dropout(embeddings)
|
| 82 |
+
|
| 83 |
+
return embeddings
|
| 84 |
+
|
| 85 |
+
|
| 86 |
+
class GlycanBERTAttention(nn.Module):
|
| 87 |
+
"""Multi-head self-attention."""
|
| 88 |
+
|
| 89 |
+
def __init__(self, config: GlycanBERTConfig):
|
| 90 |
+
super().__init__()
|
| 91 |
+
assert config.hidden_size % config.num_attention_heads == 0
|
| 92 |
+
|
| 93 |
+
self.num_attention_heads = config.num_attention_heads
|
| 94 |
+
self.attention_head_size = config.hidden_size // config.num_attention_heads
|
| 95 |
+
self.all_head_size = self.num_attention_heads * self.attention_head_size
|
| 96 |
+
|
| 97 |
+
self.query = nn.Linear(config.hidden_size, self.all_head_size)
|
| 98 |
+
self.key = nn.Linear(config.hidden_size, self.all_head_size)
|
| 99 |
+
self.value = nn.Linear(config.hidden_size, self.all_head_size)
|
| 100 |
+
|
| 101 |
+
self.dropout = nn.Dropout(config.attention_probs_dropout_prob)
|
| 102 |
+
|
| 103 |
+
def transpose_for_scores(self, x: torch.Tensor) -> torch.Tensor:
|
| 104 |
+
"""Reshape for multi-head attention."""
|
| 105 |
+
new_shape = x.size()[:-1] + (self.num_attention_heads, self.attention_head_size)
|
| 106 |
+
x = x.view(*new_shape)
|
| 107 |
+
return x.permute(0, 2, 1, 3) # (batch, heads, seq_len, head_size)
|
| 108 |
+
|
| 109 |
+
def forward(
|
| 110 |
+
self,
|
| 111 |
+
hidden_states: torch.Tensor,
|
| 112 |
+
attention_mask: torch.Tensor = None
|
| 113 |
+
) -> torch.Tensor:
|
| 114 |
+
"""
|
| 115 |
+
Args:
|
| 116 |
+
hidden_states: (batch_size, seq_len, hidden_size)
|
| 117 |
+
attention_mask: (batch_size, seq_len) - 1 for valid, 0 for padding
|
| 118 |
+
|
| 119 |
+
Returns:
|
| 120 |
+
Attention output: (batch_size, seq_len, hidden_size)
|
| 121 |
+
"""
|
| 122 |
+
batch_size, seq_len, _ = hidden_states.shape
|
| 123 |
+
|
| 124 |
+
# Linear projections
|
| 125 |
+
query_layer = self.transpose_for_scores(self.query(hidden_states))
|
| 126 |
+
key_layer = self.transpose_for_scores(self.key(hidden_states))
|
| 127 |
+
value_layer = self.transpose_for_scores(self.value(hidden_states))
|
| 128 |
+
|
| 129 |
+
# Attention scores
|
| 130 |
+
attention_scores = torch.matmul(query_layer, key_layer.transpose(-1, -2))
|
| 131 |
+
attention_scores = attention_scores / math.sqrt(self.attention_head_size)
|
| 132 |
+
|
| 133 |
+
# Apply attention mask
|
| 134 |
+
if attention_mask is not None:
|
| 135 |
+
# Convert mask to additive mask
|
| 136 |
+
attention_mask = attention_mask.unsqueeze(1).unsqueeze(2) # (batch, 1, 1, seq_len)
|
| 137 |
+
attention_mask = (1.0 - attention_mask) * -10000.0
|
| 138 |
+
attention_scores = attention_scores + attention_mask
|
| 139 |
+
|
| 140 |
+
# Attention probabilities
|
| 141 |
+
attention_probs = nn.functional.softmax(attention_scores, dim=-1)
|
| 142 |
+
attention_probs = self.dropout(attention_probs)
|
| 143 |
+
|
| 144 |
+
# Apply attention to values
|
| 145 |
+
context_layer = torch.matmul(attention_probs, value_layer)
|
| 146 |
+
|
| 147 |
+
# Reshape back
|
| 148 |
+
context_layer = context_layer.permute(0, 2, 1, 3).contiguous()
|
| 149 |
+
new_shape = context_layer.size()[:-2] + (self.all_head_size,)
|
| 150 |
+
context_layer = context_layer.view(*new_shape)
|
| 151 |
+
|
| 152 |
+
return context_layer
|
| 153 |
+
|
| 154 |
+
|
| 155 |
+
class GlycanBERTLayer(nn.Module):
|
| 156 |
+
"""Single transformer layer."""
|
| 157 |
+
|
| 158 |
+
def __init__(self, config: GlycanBERTConfig):
|
| 159 |
+
super().__init__()
|
| 160 |
+
self.attention = GlycanBERTAttention(config)
|
| 161 |
+
self.attention_output = nn.Linear(config.hidden_size, config.hidden_size)
|
| 162 |
+
self.attention_layer_norm = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)
|
| 163 |
+
|
| 164 |
+
self.intermediate = nn.Linear(config.hidden_size, config.intermediate_size)
|
| 165 |
+
self.output = nn.Linear(config.intermediate_size, config.hidden_size)
|
| 166 |
+
self.output_layer_norm = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)
|
| 167 |
+
|
| 168 |
+
self.dropout = nn.Dropout(config.hidden_dropout_prob)
|
| 169 |
+
|
| 170 |
+
def forward(
|
| 171 |
+
self,
|
| 172 |
+
hidden_states: torch.Tensor,
|
| 173 |
+
attention_mask: torch.Tensor = None
|
| 174 |
+
) -> torch.Tensor:
|
| 175 |
+
"""
|
| 176 |
+
Args:
|
| 177 |
+
hidden_states: (batch_size, seq_len, hidden_size)
|
| 178 |
+
attention_mask: (batch_size, seq_len)
|
| 179 |
+
|
| 180 |
+
Returns:
|
| 181 |
+
Output: (batch_size, seq_len, hidden_size)
|
| 182 |
+
"""
|
| 183 |
+
# Self-attention
|
| 184 |
+
attention_output = self.attention(hidden_states, attention_mask)
|
| 185 |
+
attention_output = self.attention_output(attention_output)
|
| 186 |
+
attention_output = self.dropout(attention_output)
|
| 187 |
+
|
| 188 |
+
# Add & Norm
|
| 189 |
+
hidden_states = self.attention_layer_norm(hidden_states + attention_output)
|
| 190 |
+
|
| 191 |
+
# Feed-forward
|
| 192 |
+
intermediate_output = self.intermediate(hidden_states)
|
| 193 |
+
intermediate_output = nn.functional.gelu(intermediate_output)
|
| 194 |
+
|
| 195 |
+
layer_output = self.output(intermediate_output)
|
| 196 |
+
layer_output = self.dropout(layer_output)
|
| 197 |
+
|
| 198 |
+
# Add & Norm
|
| 199 |
+
layer_output = self.output_layer_norm(hidden_states + layer_output)
|
| 200 |
+
|
| 201 |
+
return layer_output
|
| 202 |
+
|
| 203 |
+
|
| 204 |
+
class GlycanBERT(nn.Module):
|
| 205 |
+
"""
|
| 206 |
+
Glycan BERT model for masked language modeling.
|
| 207 |
+
"""
|
| 208 |
+
|
| 209 |
+
def __init__(self, config: GlycanBERTConfig):
|
| 210 |
+
super().__init__()
|
| 211 |
+
self.config = config
|
| 212 |
+
|
| 213 |
+
# Embeddings
|
| 214 |
+
self.embeddings = GlycanBERTEmbeddings(config)
|
| 215 |
+
|
| 216 |
+
# Transformer layers
|
| 217 |
+
self.layers = nn.ModuleList([GlycanBERTLayer(config) for _ in range(config.num_hidden_layers)])
|
| 218 |
+
|
| 219 |
+
# MLM head
|
| 220 |
+
self.mlm_head = nn.Linear(config.hidden_size, config.vocab_size)
|
| 221 |
+
|
| 222 |
+
# Initialize weights
|
| 223 |
+
self.apply(self._init_weights)
|
| 224 |
+
|
| 225 |
+
def _init_weights(self, module):
|
| 226 |
+
"""Initialize weights."""
|
| 227 |
+
if isinstance(module, nn.Linear):
|
| 228 |
+
module.weight.data.normal_(mean=0.0, std=self.config.initializer_range)
|
| 229 |
+
if module.bias is not None:
|
| 230 |
+
module.bias.data.zero_()
|
| 231 |
+
elif isinstance(module, nn.Embedding):
|
| 232 |
+
module.weight.data.normal_(mean=0.0, std=self.config.initializer_range)
|
| 233 |
+
if module.padding_idx is not None:
|
| 234 |
+
module.weight.data[module.padding_idx].zero_()
|
| 235 |
+
elif isinstance(module, nn.LayerNorm):
|
| 236 |
+
module.bias.data.zero_()
|
| 237 |
+
module.weight.data.fill_(1.0)
|
| 238 |
+
|
| 239 |
+
def forward(
|
| 240 |
+
self,
|
| 241 |
+
input_ids: torch.Tensor,
|
| 242 |
+
attention_mask: torch.Tensor = None,
|
| 243 |
+
labels: torch.Tensor = None
|
| 244 |
+
):
|
| 245 |
+
"""
|
| 246 |
+
Args:
|
| 247 |
+
input_ids: (batch_size, seq_len)
|
| 248 |
+
attention_mask: (batch_size, seq_len) - 1 for valid, 0 for padding
|
| 249 |
+
labels: (batch_size, seq_len) - token IDs to predict, -100 for positions to ignore
|
| 250 |
+
|
| 251 |
+
Returns:
|
| 252 |
+
If labels provided: (loss, logits)
|
| 253 |
+
Else: logits
|
| 254 |
+
"""
|
| 255 |
+
# Create attention mask if not provided
|
| 256 |
+
if attention_mask is None:
|
| 257 |
+
attention_mask = (input_ids != self.config.pad_token_id).float()
|
| 258 |
+
|
| 259 |
+
# Embeddings
|
| 260 |
+
hidden_states = self.embeddings(input_ids)
|
| 261 |
+
|
| 262 |
+
# Transformer layers
|
| 263 |
+
for layer in self.layers:
|
| 264 |
+
hidden_states = layer(hidden_states, attention_mask)
|
| 265 |
+
|
| 266 |
+
# MLM prediction
|
| 267 |
+
logits = self.mlm_head(hidden_states)
|
| 268 |
+
|
| 269 |
+
# Calculate loss if labels provided
|
| 270 |
+
loss = None
|
| 271 |
+
if labels is not None:
|
| 272 |
+
loss_fct = nn.CrossEntropyLoss() # -100 is ignored
|
| 273 |
+
loss = loss_fct(logits.view(-1, self.config.vocab_size), labels.view(-1))
|
| 274 |
+
|
| 275 |
+
if loss is not None:
|
| 276 |
+
return loss, logits
|
| 277 |
+
return logits
|
| 278 |
+
|
| 279 |
+
def get_embeddings(
|
| 280 |
+
self,
|
| 281 |
+
input_ids: torch.Tensor,
|
| 282 |
+
attention_mask: torch.Tensor = None
|
| 283 |
+
) -> torch.Tensor:
|
| 284 |
+
"""
|
| 285 |
+
Get contextualized embeddings (for downstream tasks).
|
| 286 |
+
|
| 287 |
+
Args:
|
| 288 |
+
input_ids: (batch_size, seq_len)
|
| 289 |
+
attention_mask: (batch_size, seq_len)
|
| 290 |
+
|
| 291 |
+
Returns:
|
| 292 |
+
Embeddings: (batch_size, seq_len, hidden_size)
|
| 293 |
+
"""
|
| 294 |
+
if attention_mask is None:
|
| 295 |
+
attention_mask = (input_ids != self.config.pad_token_id).float()
|
| 296 |
+
|
| 297 |
+
hidden_states = self.embeddings(input_ids)
|
| 298 |
+
|
| 299 |
+
for layer in self.layers:
|
| 300 |
+
hidden_states = layer(hidden_states, attention_mask)
|
| 301 |
+
|
| 302 |
+
return hidden_states
|
| 303 |
+
|
releases/2026-10-02/iar_completion/runtime_snapshot/project/writing/cluster/nature_submission/code/model/multimodal_glycan_bert_v3.py
ADDED
|
@@ -0,0 +1,1084 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Multimodal Glycan BERT Model v3
|
| 3 |
+
|
| 4 |
+
Extends GlycanBERT to handle three modalities:
|
| 5 |
+
- Sequence (WURCS atomic tokenization)
|
| 6 |
+
- MS (mass spectrometry peaks, RT, intensity)
|
| 7 |
+
- 3D structure (VQ-VAE discrete tokens, 4 per residue)
|
| 8 |
+
|
| 9 |
+
Each modality has its own encoder, with cross-attention for sequence-structure alignment.
|
| 10 |
+
"""
|
| 11 |
+
|
| 12 |
+
import torch
|
| 13 |
+
import torch.nn as nn
|
| 14 |
+
from typing import Dict, Optional, Tuple
|
| 15 |
+
import math
|
| 16 |
+
|
| 17 |
+
try:
|
| 18 |
+
from .glycan_bert import GlycanBERTConfig, GlycanBERTEmbeddings, GlycanBERTLayer
|
| 19 |
+
except ImportError:
|
| 20 |
+
from glycan_bert import GlycanBERTConfig, GlycanBERTEmbeddings, GlycanBERTLayer
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
class ConvGlycanBERTEmbeddings(nn.Module):
|
| 24 |
+
"""
|
| 25 |
+
Improved Convolutional front-end that mixes local WURCS context before the Transformer.
|
| 26 |
+
|
| 27 |
+
Key improvements over original:
|
| 28 |
+
1. Position embeddings added BEFORE convolution (provides spatial context to conv)
|
| 29 |
+
2. Residual connection (conv enriches embeddings rather than replacing them)
|
| 30 |
+
3. Multi-scale convolutions (kernel sizes 3, 5, 7) for better receptive field
|
| 31 |
+
4. Proper layer normalization on the residual path
|
| 32 |
+
"""
|
| 33 |
+
|
| 34 |
+
def __init__(self, config):
|
| 35 |
+
super().__init__()
|
| 36 |
+
self.token_embeddings = nn.Embedding(
|
| 37 |
+
config.vocab_size, config.hidden_size, padding_idx=config.pad_token_id
|
| 38 |
+
)
|
| 39 |
+
self.position_embeddings = nn.Embedding(
|
| 40 |
+
config.max_position_embeddings, config.hidden_size
|
| 41 |
+
)
|
| 42 |
+
|
| 43 |
+
# NEW: Branch depth embeddings - encodes depth in glycan tree (0=root, 1=child, etc.)
|
| 44 |
+
max_branch_depth = getattr(config, "max_branch_depth", 8)
|
| 45 |
+
self.branch_embeddings = nn.Embedding(max_branch_depth, config.hidden_size)
|
| 46 |
+
|
| 47 |
+
# NEW: Linkage type embeddings - encodes chemistry of glycosidic bond
|
| 48 |
+
# 0=none, 1=1-3, 2=1-4, 3=1-6, etc.
|
| 49 |
+
num_linkage_types = getattr(config, "num_linkage_types", 9)
|
| 50 |
+
self.linkage_embeddings = nn.Embedding(num_linkage_types, config.hidden_size)
|
| 51 |
+
|
| 52 |
+
# Multi-scale convolutions for different receptive fields
|
| 53 |
+
kernel_size = getattr(config, "cnn_kernel_size", 3)
|
| 54 |
+
# Split channels evenly: 256 + 256 + 256 = 768 for hidden_size=768
|
| 55 |
+
channels_per_scale = config.hidden_size // 3
|
| 56 |
+
self.conv_layers = nn.ModuleList([
|
| 57 |
+
nn.Conv1d(
|
| 58 |
+
in_channels=config.hidden_size,
|
| 59 |
+
out_channels=channels_per_scale,
|
| 60 |
+
kernel_size=kernel_size + 2 * i, # Kernels: 3, 5, 7
|
| 61 |
+
padding=(kernel_size + 2 * i) // 2, # Same padding
|
| 62 |
+
)
|
| 63 |
+
for i in range(3)
|
| 64 |
+
])
|
| 65 |
+
self.conv_activation = nn.GELU()
|
| 66 |
+
self.conv_proj = nn.Linear(channels_per_scale * 3, config.hidden_size) # Project concatenated back
|
| 67 |
+
|
| 68 |
+
self.LayerNorm = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)
|
| 69 |
+
self.conv_norm = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)
|
| 70 |
+
self.dropout = nn.Dropout(config.hidden_dropout_prob)
|
| 71 |
+
self.register_buffer(
|
| 72 |
+
"position_ids",
|
| 73 |
+
torch.arange(config.max_position_embeddings).expand((1, -1)),
|
| 74 |
+
)
|
| 75 |
+
|
| 76 |
+
self.hidden_size = config.hidden_size
|
| 77 |
+
|
| 78 |
+
def forward(self, input_ids, branch_depths=None, linkage_types=None):
|
| 79 |
+
seq_len = input_ids.shape[1]
|
| 80 |
+
|
| 81 |
+
# Step 1: Token + Position embeddings FIRST (provides spatial context to conv)
|
| 82 |
+
x = self.token_embeddings(input_ids) # (batch, seq, hidden)
|
| 83 |
+
position_ids = self.position_ids[:, :seq_len]
|
| 84 |
+
x = x + self.position_embeddings(position_ids)
|
| 85 |
+
|
| 86 |
+
# NEW: Add branch depth embeddings (encodes tree structure)
|
| 87 |
+
if branch_depths is not None:
|
| 88 |
+
# Clamp to valid range
|
| 89 |
+
branch_depths = branch_depths.clamp(0, self.branch_embeddings.num_embeddings - 1)
|
| 90 |
+
x = x + self.branch_embeddings(branch_depths)
|
| 91 |
+
|
| 92 |
+
# NEW: Add linkage type embeddings (encodes bond chemistry)
|
| 93 |
+
if linkage_types is not None:
|
| 94 |
+
linkage_types = linkage_types.clamp(0, self.linkage_embeddings.num_embeddings - 1)
|
| 95 |
+
x = x + self.linkage_embeddings(linkage_types)
|
| 96 |
+
|
| 97 |
+
x = self.LayerNorm(x)
|
| 98 |
+
|
| 99 |
+
# Step 2: Multi-scale convolution with RESIDUAL connection
|
| 100 |
+
# Convolution expects (batch, hidden, seq)
|
| 101 |
+
conv_in = x.permute(0, 2, 1)
|
| 102 |
+
|
| 103 |
+
# Apply multi-scale convolutions and concatenate
|
| 104 |
+
conv_outputs = []
|
| 105 |
+
for conv in self.conv_layers:
|
| 106 |
+
conv_out = self.conv_activation(conv(conv_in))
|
| 107 |
+
conv_outputs.append(conv_out)
|
| 108 |
+
|
| 109 |
+
# Concatenate multi-scale features and project back
|
| 110 |
+
conv_out = torch.cat(conv_outputs, dim=1) # (batch, hidden, seq)
|
| 111 |
+
conv_out = conv_out.permute(0, 2, 1) # (batch, seq, hidden)
|
| 112 |
+
conv_out = self.conv_proj(conv_out) # Project to correct size
|
| 113 |
+
|
| 114 |
+
# Step 3: Residual connection - conv ENRICHES rather than replaces
|
| 115 |
+
x = self.conv_norm(x + self.dropout(conv_out))
|
| 116 |
+
|
| 117 |
+
return x
|
| 118 |
+
|
| 119 |
+
|
| 120 |
+
def create_residue_level_mask(
|
| 121 |
+
seq_residue_ids: torch.Tensor, # (batch, N_seq)
|
| 122 |
+
struct_residue_ids: torch.Tensor # (batch, N_struct)
|
| 123 |
+
) -> torch.Tensor:
|
| 124 |
+
"""
|
| 125 |
+
Create residue-level attention mask for cross-attention.
|
| 126 |
+
|
| 127 |
+
Maps WURCS tokens to VQ-VAE structural tokens based on residue IDs.
|
| 128 |
+
A WURCS token with residue_id=0 can only attend to VQ-VAE tokens with residue_id=0.
|
| 129 |
+
|
| 130 |
+
Args:
|
| 131 |
+
seq_residue_ids: Residue IDs for sequence tokens (batch, N_seq)
|
| 132 |
+
struct_residue_ids: Residue IDs for structural tokens (batch, N_struct)
|
| 133 |
+
|
| 134 |
+
Returns:
|
| 135 |
+
Boolean mask (batch, N_seq, N_struct) where True = can attend
|
| 136 |
+
"""
|
| 137 |
+
# Expand dimensions for broadcasting
|
| 138 |
+
# seq: (batch, N_seq, 1)
|
| 139 |
+
# struct: (batch, 1, N_struct)
|
| 140 |
+
mask = seq_residue_ids.unsqueeze(2) == struct_residue_ids.unsqueeze(1)
|
| 141 |
+
# Shape: (batch, N_seq, N_struct)
|
| 142 |
+
|
| 143 |
+
# Mask out structural tokens (residue_id = -1) and MS tokens (residue_id = -2)
|
| 144 |
+
# Only tokens with residue_id >= 0 can attend
|
| 145 |
+
mask &= (seq_residue_ids.unsqueeze(2) >= 0)
|
| 146 |
+
|
| 147 |
+
return mask # True = can attend, False = cannot attend
|
| 148 |
+
|
| 149 |
+
|
| 150 |
+
class MultimodalGlycanBERTConfig:
|
| 151 |
+
"""Configuration for Multimodal GlycanBERT v3."""
|
| 152 |
+
|
| 153 |
+
def __init__(
|
| 154 |
+
self,
|
| 155 |
+
# Sequence modality
|
| 156 |
+
seq_vocab_size: int = 166,
|
| 157 |
+
seq_hidden_size: int = 768,
|
| 158 |
+
seq_num_layers: int = 12,
|
| 159 |
+
seq_num_heads: int = 12,
|
| 160 |
+
seq_max_length: int = 512,
|
| 161 |
+
|
| 162 |
+
# MS modality
|
| 163 |
+
ms_vocab_size: int = 242,
|
| 164 |
+
ms_hidden_size: int = 384,
|
| 165 |
+
ms_num_layers: int = 6,
|
| 166 |
+
ms_num_heads: int = 6,
|
| 167 |
+
ms_max_length: int = 150,
|
| 168 |
+
|
| 169 |
+
# 3D structure modality
|
| 170 |
+
struct_vocab_size: int = 1024, # VQ-VAE codebook size
|
| 171 |
+
struct_hidden_size: int = 512,
|
| 172 |
+
struct_num_layers: int = 8,
|
| 173 |
+
struct_num_heads: int = 8,
|
| 174 |
+
struct_max_length: int = 200,
|
| 175 |
+
use_3d: bool = True,
|
| 176 |
+
|
| 177 |
+
# Cross-attention
|
| 178 |
+
use_cross_attention: bool = True,
|
| 179 |
+
cross_attn_num_heads: int = 8,
|
| 180 |
+
|
| 181 |
+
# Fusion
|
| 182 |
+
fusion_hidden_size: int = 768,
|
| 183 |
+
fusion_num_layers: int = 2,
|
| 184 |
+
|
| 185 |
+
# Training
|
| 186 |
+
hidden_dropout_prob: float = 0.1,
|
| 187 |
+
attention_probs_dropout_prob: float = 0.1,
|
| 188 |
+
layer_norm_eps: float = 1e-12,
|
| 189 |
+
initializer_range: float = 0.02,
|
| 190 |
+
|
| 191 |
+
# Conv front-end
|
| 192 |
+
use_cnn_frontend: bool = True,
|
| 193 |
+
cnn_kernel_size: int = 3,
|
| 194 |
+
|
| 195 |
+
# Loss weights
|
| 196 |
+
seq_loss_weight: float = 0.60,
|
| 197 |
+
ms_loss_weight: float = 0.15,
|
| 198 |
+
struct_loss_weight: float = 0.25,
|
| 199 |
+
dist_loss_weight: float = 0.25,
|
| 200 |
+
|
| 201 |
+
# Token IDs
|
| 202 |
+
pad_token_id: int = 0,
|
| 203 |
+
mask_token_id: int = 1,
|
| 204 |
+
):
|
| 205 |
+
# Sequence config
|
| 206 |
+
self.seq_vocab_size = seq_vocab_size
|
| 207 |
+
self.seq_hidden_size = seq_hidden_size
|
| 208 |
+
self.seq_num_layers = seq_num_layers
|
| 209 |
+
self.seq_num_heads = seq_num_heads
|
| 210 |
+
self.seq_max_length = seq_max_length
|
| 211 |
+
|
| 212 |
+
# MS config
|
| 213 |
+
self.ms_vocab_size = ms_vocab_size
|
| 214 |
+
self.ms_vocab_offset = seq_vocab_size # MS tokens start at 166
|
| 215 |
+
self.ms_total_vocab_size = seq_vocab_size + ms_vocab_size # 408 total
|
| 216 |
+
self.ms_hidden_size = ms_hidden_size
|
| 217 |
+
self.ms_num_layers = ms_num_layers
|
| 218 |
+
self.ms_num_heads = ms_num_heads
|
| 219 |
+
self.ms_max_length = ms_max_length
|
| 220 |
+
|
| 221 |
+
# Structure config
|
| 222 |
+
self.struct_vocab_size = struct_vocab_size
|
| 223 |
+
self.struct_hidden_size = struct_hidden_size
|
| 224 |
+
self.struct_num_layers = struct_num_layers
|
| 225 |
+
self.struct_num_heads = struct_num_heads
|
| 226 |
+
self.struct_max_length = struct_max_length
|
| 227 |
+
self.use_3d = use_3d
|
| 228 |
+
|
| 229 |
+
# Cross-attention config
|
| 230 |
+
self.use_cross_attention = use_cross_attention
|
| 231 |
+
self.cross_attn_num_heads = cross_attn_num_heads
|
| 232 |
+
|
| 233 |
+
# Fusion config
|
| 234 |
+
self.fusion_hidden_size = fusion_hidden_size
|
| 235 |
+
self.fusion_num_layers = fusion_num_layers
|
| 236 |
+
|
| 237 |
+
# Training config
|
| 238 |
+
self.hidden_dropout_prob = hidden_dropout_prob
|
| 239 |
+
self.attention_probs_dropout_prob = attention_probs_dropout_prob
|
| 240 |
+
self.layer_norm_eps = layer_norm_eps
|
| 241 |
+
self.initializer_range = initializer_range
|
| 242 |
+
|
| 243 |
+
# Conv front-end
|
| 244 |
+
self.use_cnn_frontend = use_cnn_frontend
|
| 245 |
+
self.cnn_kernel_size = cnn_kernel_size
|
| 246 |
+
|
| 247 |
+
# Loss weights
|
| 248 |
+
self.seq_loss_weight = seq_loss_weight
|
| 249 |
+
self.ms_loss_weight = ms_loss_weight
|
| 250 |
+
self.struct_loss_weight = struct_loss_weight
|
| 251 |
+
self.dist_loss_weight = dist_loss_weight
|
| 252 |
+
|
| 253 |
+
# Token IDs
|
| 254 |
+
self.pad_token_id = pad_token_id
|
| 255 |
+
self.mask_token_id = mask_token_id
|
| 256 |
+
|
| 257 |
+
def to_seq_config(self) -> GlycanBERTConfig:
|
| 258 |
+
"""Convert to sequence-only config."""
|
| 259 |
+
return GlycanBERTConfig(
|
| 260 |
+
vocab_size=self.seq_vocab_size,
|
| 261 |
+
hidden_size=self.seq_hidden_size,
|
| 262 |
+
num_hidden_layers=self.seq_num_layers,
|
| 263 |
+
num_attention_heads=self.seq_num_heads,
|
| 264 |
+
intermediate_size=self.seq_hidden_size * 4,
|
| 265 |
+
hidden_dropout_prob=self.hidden_dropout_prob,
|
| 266 |
+
attention_probs_dropout_prob=self.attention_probs_dropout_prob,
|
| 267 |
+
max_position_embeddings=self.seq_max_length,
|
| 268 |
+
layer_norm_eps=self.layer_norm_eps,
|
| 269 |
+
pad_token_id=self.pad_token_id,
|
| 270 |
+
mask_token_id=self.mask_token_id,
|
| 271 |
+
initializer_range=self.initializer_range,
|
| 272 |
+
)
|
| 273 |
+
|
| 274 |
+
def to_ms_config(self) -> GlycanBERTConfig:
|
| 275 |
+
"""Convert to MS-only config."""
|
| 276 |
+
return GlycanBERTConfig(
|
| 277 |
+
vocab_size=self.ms_total_vocab_size,
|
| 278 |
+
hidden_size=self.ms_hidden_size,
|
| 279 |
+
num_hidden_layers=self.ms_num_layers,
|
| 280 |
+
num_attention_heads=self.ms_num_heads,
|
| 281 |
+
intermediate_size=self.ms_hidden_size * 4,
|
| 282 |
+
hidden_dropout_prob=self.hidden_dropout_prob,
|
| 283 |
+
attention_probs_dropout_prob=self.attention_probs_dropout_prob,
|
| 284 |
+
max_position_embeddings=self.ms_max_length,
|
| 285 |
+
layer_norm_eps=self.layer_norm_eps,
|
| 286 |
+
pad_token_id=self.pad_token_id,
|
| 287 |
+
mask_token_id=self.mask_token_id,
|
| 288 |
+
initializer_range=self.initializer_range,
|
| 289 |
+
)
|
| 290 |
+
|
| 291 |
+
def to_struct_config(self) -> GlycanBERTConfig:
|
| 292 |
+
"""Convert to structure-only config."""
|
| 293 |
+
return GlycanBERTConfig(
|
| 294 |
+
vocab_size=self.struct_vocab_size,
|
| 295 |
+
hidden_size=self.struct_hidden_size,
|
| 296 |
+
num_hidden_layers=self.struct_num_layers,
|
| 297 |
+
num_attention_heads=self.struct_num_heads,
|
| 298 |
+
intermediate_size=self.struct_hidden_size * 4,
|
| 299 |
+
hidden_dropout_prob=self.hidden_dropout_prob,
|
| 300 |
+
attention_probs_dropout_prob=self.attention_probs_dropout_prob,
|
| 301 |
+
max_position_embeddings=self.struct_max_length,
|
| 302 |
+
layer_norm_eps=self.layer_norm_eps,
|
| 303 |
+
pad_token_id=self.pad_token_id,
|
| 304 |
+
mask_token_id=self.mask_token_id,
|
| 305 |
+
initializer_range=self.initializer_range,
|
| 306 |
+
)
|
| 307 |
+
|
| 308 |
+
|
| 309 |
+
# =============================================================================
|
| 310 |
+
# Improvement #1: Monosaccharide-Level Pooling
|
| 311 |
+
# =============================================================================
|
| 312 |
+
|
| 313 |
+
class MonosaccharidePooling(nn.Module):
|
| 314 |
+
"""
|
| 315 |
+
Pool token representations to monosaccharide level, then aggregate.
|
| 316 |
+
|
| 317 |
+
This bridges the gap between token-level BERT and monosaccharide-level CNNs/GNNs.
|
| 318 |
+
Uses monosaccharide_indices from the data to know where each residue starts.
|
| 319 |
+
"""
|
| 320 |
+
|
| 321 |
+
def __init__(self, hidden_size: int, num_attention_heads: int = 8, dropout: float = 0.1):
|
| 322 |
+
super().__init__()
|
| 323 |
+
self.hidden_size = hidden_size
|
| 324 |
+
|
| 325 |
+
# Attention pooling over monosaccharide representations
|
| 326 |
+
self.mono_attention = nn.MultiheadAttention(
|
| 327 |
+
embed_dim=hidden_size,
|
| 328 |
+
num_heads=num_attention_heads,
|
| 329 |
+
dropout=dropout,
|
| 330 |
+
batch_first=True
|
| 331 |
+
)
|
| 332 |
+
self.mono_norm = nn.LayerNorm(hidden_size)
|
| 333 |
+
|
| 334 |
+
# Final aggregation to single glycan representation
|
| 335 |
+
self.glycan_query = nn.Parameter(torch.randn(1, 1, hidden_size) * 0.02)
|
| 336 |
+
self.glycan_attention = nn.MultiheadAttention(
|
| 337 |
+
embed_dim=hidden_size,
|
| 338 |
+
num_heads=num_attention_heads,
|
| 339 |
+
dropout=dropout,
|
| 340 |
+
batch_first=True
|
| 341 |
+
)
|
| 342 |
+
self.glycan_norm = nn.LayerNorm(hidden_size)
|
| 343 |
+
|
| 344 |
+
def forward(
|
| 345 |
+
self,
|
| 346 |
+
hidden_states: torch.Tensor, # (batch, seq_len, hidden)
|
| 347 |
+
residue_ids: torch.Tensor, # (batch, seq_len) - which residue each token belongs to
|
| 348 |
+
attention_mask: torch.Tensor = None, # (batch, seq_len)
|
| 349 |
+
) -> torch.Tensor:
|
| 350 |
+
"""
|
| 351 |
+
Pool tokens to monosaccharide level, then to glycan level.
|
| 352 |
+
|
| 353 |
+
Returns:
|
| 354 |
+
Glycan representation: (batch, hidden_size)
|
| 355 |
+
"""
|
| 356 |
+
batch_size = hidden_states.size(0)
|
| 357 |
+
device = hidden_states.device
|
| 358 |
+
|
| 359 |
+
# Get unique residue IDs per sample (excluding -1 padding)
|
| 360 |
+
max_residues = 50 # Reasonable max for glycans
|
| 361 |
+
|
| 362 |
+
# Pool tokens within each residue using mean pooling
|
| 363 |
+
mono_reps = torch.zeros(batch_size, max_residues, self.hidden_size, device=device)
|
| 364 |
+
mono_mask = torch.zeros(batch_size, max_residues, dtype=torch.bool, device=device)
|
| 365 |
+
|
| 366 |
+
for b in range(batch_size):
|
| 367 |
+
unique_residues = torch.unique(residue_ids[b][residue_ids[b] >= 0])
|
| 368 |
+
for i, rid in enumerate(unique_residues):
|
| 369 |
+
if i >= max_residues:
|
| 370 |
+
break
|
| 371 |
+
token_mask = residue_ids[b] == rid
|
| 372 |
+
if attention_mask is not None:
|
| 373 |
+
token_mask = token_mask & (attention_mask[b] > 0)
|
| 374 |
+
if token_mask.sum() > 0:
|
| 375 |
+
mono_reps[b, i] = hidden_states[b][token_mask].mean(dim=0)
|
| 376 |
+
mono_mask[b, i] = True
|
| 377 |
+
|
| 378 |
+
# Apply attention over monosaccharide representations
|
| 379 |
+
# Convert mask for attention: True = valid, need to invert for PyTorch
|
| 380 |
+
key_padding_mask = ~mono_mask # True = ignore
|
| 381 |
+
|
| 382 |
+
mono_out, _ = self.mono_attention(
|
| 383 |
+
mono_reps, mono_reps, mono_reps,
|
| 384 |
+
key_padding_mask=key_padding_mask
|
| 385 |
+
)
|
| 386 |
+
mono_out = self.mono_norm(mono_reps + mono_out)
|
| 387 |
+
|
| 388 |
+
# Aggregate to single glycan representation using learned query
|
| 389 |
+
glycan_query = self.glycan_query.expand(batch_size, -1, -1)
|
| 390 |
+
glycan_out, _ = self.glycan_attention(
|
| 391 |
+
glycan_query, mono_out, mono_out,
|
| 392 |
+
key_padding_mask=key_padding_mask
|
| 393 |
+
)
|
| 394 |
+
glycan_out = self.glycan_norm(glycan_query + glycan_out)
|
| 395 |
+
|
| 396 |
+
return glycan_out.squeeze(1) # (batch, hidden)
|
| 397 |
+
|
| 398 |
+
|
| 399 |
+
# =============================================================================
|
| 400 |
+
# Improvement #2: Residue Type Embeddings
|
| 401 |
+
# =============================================================================
|
| 402 |
+
|
| 403 |
+
# Common monosaccharide types vocabulary
|
| 404 |
+
MONOSACCHARIDE_VOCAB = {
|
| 405 |
+
'[PAD_MONO]': 0, '[UNK_MONO]': 1,
|
| 406 |
+
'Glc': 2, 'GlcNAc': 3, 'GlcA': 4, 'GlcN': 5,
|
| 407 |
+
'Gal': 6, 'GalNAc': 7, 'GalA': 8, 'GalN': 9,
|
| 408 |
+
'Man': 10, 'ManNAc': 11, 'ManA': 12, 'ManN': 13,
|
| 409 |
+
'Fuc': 14, 'Rha': 15, 'Xyl': 16, 'Ara': 17,
|
| 410 |
+
'Neu5Ac': 18, 'Neu5Gc': 19, 'Kdn': 20, 'Sia': 21,
|
| 411 |
+
'GalNAcA': 22, 'GlcNAcA': 23, 'IdoA': 24, 'GulA': 25,
|
| 412 |
+
'Rib': 26, 'Lyx': 27, 'All': 28, 'Alt': 29,
|
| 413 |
+
'Tal': 30, 'Ido': 31, 'Qui': 32, 'Oli': 33,
|
| 414 |
+
'Tyv': 34, 'Abe': 35, 'Par': 36, 'Dig': 37,
|
| 415 |
+
'Col': 38, 'Dha': 39, 'Kdo': 40, 'Hep': 41,
|
| 416 |
+
'NeuroGc': 42, 'Muramic': 43, 'LDManHep': 44, 'DDManHep': 45,
|
| 417 |
+
'Bac': 46, 'Pse': 47, 'Leg': 48, 'Aci': 49,
|
| 418 |
+
'6dTal': 50, 'Fru': 51, 'Tag': 52, 'Sor': 53,
|
| 419 |
+
'Psi': 54, 'Sed': 55, 'MurNAc': 56, 'MurNGc': 57,
|
| 420 |
+
'Api': 58, 'Erwiniose': 59, 'Yer': 60, 'Thre': 61,
|
| 421 |
+
# Add more as needed, up to ~70
|
| 422 |
+
}
|
| 423 |
+
|
| 424 |
+
|
| 425 |
+
class ResidueTypeEmbeddings(nn.Module):
|
| 426 |
+
"""
|
| 427 |
+
Learnable embeddings for monosaccharide types.
|
| 428 |
+
|
| 429 |
+
Instead of the model having to learn that 'a1221m' = Fucose from character patterns,
|
| 430 |
+
we explicitly add a Fucose embedding to all tokens belonging to that residue.
|
| 431 |
+
"""
|
| 432 |
+
|
| 433 |
+
def __init__(self, hidden_size: int, num_mono_types: int = 70):
|
| 434 |
+
super().__init__()
|
| 435 |
+
self.mono_embeddings = nn.Embedding(num_mono_types, hidden_size)
|
| 436 |
+
self.mono_vocab = MONOSACCHARIDE_VOCAB
|
| 437 |
+
self.hidden_size = hidden_size
|
| 438 |
+
|
| 439 |
+
def forward(
|
| 440 |
+
self,
|
| 441 |
+
token_embeddings: torch.Tensor, # (batch, seq_len, hidden)
|
| 442 |
+
residue_ids: torch.Tensor, # (batch, seq_len)
|
| 443 |
+
mono_type_ids: torch.Tensor = None, # (batch, max_residues) - monosaccharide type per residue
|
| 444 |
+
) -> torch.Tensor:
|
| 445 |
+
"""
|
| 446 |
+
Add residue type embeddings to token embeddings.
|
| 447 |
+
|
| 448 |
+
Args:
|
| 449 |
+
token_embeddings: Base token embeddings
|
| 450 |
+
residue_ids: Which residue each token belongs to (-1 for special tokens)
|
| 451 |
+
mono_type_ids: Monosaccharide type ID for each residue position
|
| 452 |
+
|
| 453 |
+
Returns:
|
| 454 |
+
Enhanced embeddings with residue type information
|
| 455 |
+
"""
|
| 456 |
+
if mono_type_ids is None:
|
| 457 |
+
return token_embeddings
|
| 458 |
+
|
| 459 |
+
batch_size, seq_len, _ = token_embeddings.shape
|
| 460 |
+
enhanced = token_embeddings.clone()
|
| 461 |
+
|
| 462 |
+
# Add mono type embedding to each token based on its residue
|
| 463 |
+
for b in range(batch_size):
|
| 464 |
+
for pos in range(seq_len):
|
| 465 |
+
rid = residue_ids[b, pos].item()
|
| 466 |
+
if rid >= 0 and rid < mono_type_ids.size(1):
|
| 467 |
+
mono_id = mono_type_ids[b, rid]
|
| 468 |
+
enhanced[b, pos] = enhanced[b, pos] + self.mono_embeddings(mono_id)
|
| 469 |
+
|
| 470 |
+
return enhanced
|
| 471 |
+
|
| 472 |
+
@staticmethod
|
| 473 |
+
def get_mono_type_id(mono_name: str) -> int:
|
| 474 |
+
"""Convert monosaccharide name to type ID."""
|
| 475 |
+
return MONOSACCHARIDE_VOCAB.get(mono_name, MONOSACCHARIDE_VOCAB['[UNK_MONO]'])
|
| 476 |
+
|
| 477 |
+
|
| 478 |
+
# =============================================================================
|
| 479 |
+
# Improvement #4: Relative Position Encoding for Glycan Trees
|
| 480 |
+
# =============================================================================
|
| 481 |
+
|
| 482 |
+
class RelativePositionBias(nn.Module):
|
| 483 |
+
"""
|
| 484 |
+
Compute relative position bias for attention based on residue IDs.
|
| 485 |
+
|
| 486 |
+
Tokens in the same residue get distance 0.
|
| 487 |
+
Tokens in adjacent residues get distance ±1.
|
| 488 |
+
This helps the model understand glycan tree structure.
|
| 489 |
+
"""
|
| 490 |
+
|
| 491 |
+
def __init__(self, num_heads: int, max_distance: int = 10):
|
| 492 |
+
super().__init__()
|
| 493 |
+
self.num_heads = num_heads
|
| 494 |
+
self.max_distance = max_distance
|
| 495 |
+
|
| 496 |
+
# Learnable bias for each relative distance (-max to +max)
|
| 497 |
+
num_distances = 2 * max_distance + 1
|
| 498 |
+
self.relative_bias = nn.Embedding(num_distances, num_heads)
|
| 499 |
+
|
| 500 |
+
def forward(self, residue_ids: torch.Tensor) -> torch.Tensor:
|
| 501 |
+
"""
|
| 502 |
+
Compute relative position bias.
|
| 503 |
+
|
| 504 |
+
Args:
|
| 505 |
+
residue_ids: (batch, seq_len)
|
| 506 |
+
|
| 507 |
+
Returns:
|
| 508 |
+
Bias to add to attention scores: (batch, num_heads, seq_len, seq_len)
|
| 509 |
+
"""
|
| 510 |
+
# Compute pairwise residue distances
|
| 511 |
+
# (batch, seq_len, 1) - (batch, 1, seq_len) = (batch, seq_len, seq_len)
|
| 512 |
+
distance = residue_ids.unsqueeze(2) - residue_ids.unsqueeze(1)
|
| 513 |
+
|
| 514 |
+
# Clamp to max distance range and shift to 0-indexed
|
| 515 |
+
distance_clamped = distance.clamp(-self.max_distance, self.max_distance)
|
| 516 |
+
distance_idx = distance_clamped + self.max_distance # Now 0 to 2*max_distance
|
| 517 |
+
|
| 518 |
+
# Look up bias: (batch, seq_len, seq_len, num_heads)
|
| 519 |
+
bias = self.relative_bias(distance_idx)
|
| 520 |
+
|
| 521 |
+
# Transpose to (batch, num_heads, seq_len, seq_len)
|
| 522 |
+
bias = bias.permute(0, 3, 1, 2)
|
| 523 |
+
|
| 524 |
+
return bias
|
| 525 |
+
|
| 526 |
+
|
| 527 |
+
class CrossAttentionLayer(nn.Module):
|
| 528 |
+
"""
|
| 529 |
+
Cross-attention layer for sequence-structure alignment.
|
| 530 |
+
|
| 531 |
+
Allows sequence tokens to attend to structural atoms using attention masks.
|
| 532 |
+
"""
|
| 533 |
+
|
| 534 |
+
def __init__(self, config: MultimodalGlycanBERTConfig):
|
| 535 |
+
super().__init__()
|
| 536 |
+
self.num_heads = config.cross_attn_num_heads
|
| 537 |
+
self.hidden_size = config.seq_hidden_size
|
| 538 |
+
self.head_dim = self.hidden_size // self.num_heads
|
| 539 |
+
|
| 540 |
+
assert self.hidden_size % self.num_heads == 0, "hidden_size must be divisible by num_heads"
|
| 541 |
+
|
| 542 |
+
# Query from sequence, Key/Value from structure (VQ-VAE tokens)
|
| 543 |
+
self.query = nn.Linear(config.seq_hidden_size, self.hidden_size)
|
| 544 |
+
self.key = nn.Linear(config.struct_hidden_size, self.hidden_size)
|
| 545 |
+
self.value = nn.Linear(config.struct_hidden_size, self.hidden_size)
|
| 546 |
+
|
| 547 |
+
self.output = nn.Linear(self.hidden_size, config.seq_hidden_size)
|
| 548 |
+
self.dropout = nn.Dropout(config.attention_probs_dropout_prob)
|
| 549 |
+
self.layer_norm = nn.LayerNorm(config.seq_hidden_size, eps=config.layer_norm_eps)
|
| 550 |
+
|
| 551 |
+
def forward(
|
| 552 |
+
self,
|
| 553 |
+
seq_hidden: torch.Tensor, # (batch, seq_len, seq_hidden)
|
| 554 |
+
struct_hidden: torch.Tensor, # (batch, struct_len, struct_hidden)
|
| 555 |
+
attention_mask: Optional[torch.Tensor] = None, # (batch, seq_len, struct_len)
|
| 556 |
+
) -> torch.Tensor:
|
| 557 |
+
"""
|
| 558 |
+
Apply cross-attention from sequence to structure.
|
| 559 |
+
|
| 560 |
+
Args:
|
| 561 |
+
seq_hidden: Sequence hidden states
|
| 562 |
+
struct_hidden: Structure hidden states
|
| 563 |
+
attention_mask: Boolean mask (True = can attend, False = cannot attend)
|
| 564 |
+
|
| 565 |
+
Returns:
|
| 566 |
+
Updated sequence hidden states
|
| 567 |
+
"""
|
| 568 |
+
batch_size, seq_len, _ = seq_hidden.shape
|
| 569 |
+
struct_len = struct_hidden.shape[1]
|
| 570 |
+
|
| 571 |
+
# Project to Q, K, V
|
| 572 |
+
Q = self.query(seq_hidden) # (batch, seq_len, hidden)
|
| 573 |
+
K = self.key(struct_hidden) # (batch, struct_len, hidden)
|
| 574 |
+
V = self.value(struct_hidden) # (batch, struct_len, hidden)
|
| 575 |
+
|
| 576 |
+
# Reshape for multi-head attention
|
| 577 |
+
Q = Q.view(batch_size, seq_len, self.num_heads, self.head_dim).transpose(1, 2) # (batch, heads, seq_len, head_dim)
|
| 578 |
+
K = K.view(batch_size, struct_len, self.num_heads, self.head_dim).transpose(1, 2) # (batch, heads, struct_len, head_dim)
|
| 579 |
+
V = V.view(batch_size, struct_len, self.num_heads, self.head_dim).transpose(1, 2) # (batch, heads, struct_len, head_dim)
|
| 580 |
+
|
| 581 |
+
# Compute attention scores
|
| 582 |
+
scores = torch.matmul(Q, K.transpose(-2, -1)) / math.sqrt(self.head_dim) # (batch, heads, seq_len, struct_len)
|
| 583 |
+
|
| 584 |
+
# Apply attention mask
|
| 585 |
+
if attention_mask is not None:
|
| 586 |
+
# attention_mask: (batch, seq_len, struct_len) -> (batch, 1, seq_len, struct_len)
|
| 587 |
+
attention_mask = attention_mask.unsqueeze(1)
|
| 588 |
+
# Convert boolean mask to float: True -> 0.0, False -> -10000.0
|
| 589 |
+
attention_mask = (~attention_mask).float() * -10000.0
|
| 590 |
+
scores = scores + attention_mask
|
| 591 |
+
|
| 592 |
+
# Softmax and dropout
|
| 593 |
+
attn_weights = torch.softmax(scores, dim=-1) # (batch, heads, seq_len, struct_len)
|
| 594 |
+
attn_weights = self.dropout(attn_weights)
|
| 595 |
+
|
| 596 |
+
# Apply attention to values
|
| 597 |
+
context = torch.matmul(attn_weights, V) # (batch, heads, seq_len, head_dim)
|
| 598 |
+
|
| 599 |
+
# Reshape back
|
| 600 |
+
context = context.transpose(1, 2).contiguous().view(batch_size, seq_len, self.hidden_size)
|
| 601 |
+
|
| 602 |
+
# Output projection
|
| 603 |
+
output = self.output(context)
|
| 604 |
+
output = self.dropout(output)
|
| 605 |
+
|
| 606 |
+
# Residual connection + layer norm
|
| 607 |
+
output = self.layer_norm(seq_hidden + output)
|
| 608 |
+
|
| 609 |
+
return output
|
| 610 |
+
|
| 611 |
+
|
| 612 |
+
class MultimodalGlycanBERT(nn.Module):
|
| 613 |
+
"""
|
| 614 |
+
Multimodal BERT for glycan representation learning (v3).
|
| 615 |
+
|
| 616 |
+
Architecture:
|
| 617 |
+
1. Separate encoders for each modality (sequence, MS, 3D structure)
|
| 618 |
+
2. Cross-attention for sequence-structure alignment
|
| 619 |
+
3. Modality-specific MLM heads
|
| 620 |
+
4. Fusion layer for combined representation
|
| 621 |
+
"""
|
| 622 |
+
|
| 623 |
+
def __init__(self, config: MultimodalGlycanBERTConfig):
|
| 624 |
+
super().__init__()
|
| 625 |
+
self.config = config
|
| 626 |
+
|
| 627 |
+
# ===== Sequence Encoder =====
|
| 628 |
+
seq_config = config.to_seq_config()
|
| 629 |
+
seq_config.cnn_kernel_size = config.cnn_kernel_size
|
| 630 |
+
|
| 631 |
+
if config.use_cnn_frontend:
|
| 632 |
+
print(f"✅ Enabled Convolutional Front-End (Kernel={config.cnn_kernel_size})")
|
| 633 |
+
self.seq_embeddings = ConvGlycanBERTEmbeddings(seq_config)
|
| 634 |
+
else:
|
| 635 |
+
self.seq_embeddings = GlycanBERTEmbeddings(seq_config)
|
| 636 |
+
self.seq_layers = nn.ModuleList([GlycanBERTLayer(seq_config) for _ in range(seq_config.num_hidden_layers)])
|
| 637 |
+
self.seq_mlm_head = nn.Linear(seq_config.hidden_size, seq_config.vocab_size)
|
| 638 |
+
|
| 639 |
+
# ===== MS Encoder =====
|
| 640 |
+
ms_config = config.to_ms_config()
|
| 641 |
+
self.ms_embeddings = GlycanBERTEmbeddings(ms_config)
|
| 642 |
+
self.ms_layers = nn.ModuleList([GlycanBERTLayer(ms_config) for _ in range(ms_config.num_hidden_layers)])
|
| 643 |
+
self.ms_mlm_head = nn.Linear(ms_config.hidden_size, ms_config.vocab_size)
|
| 644 |
+
|
| 645 |
+
# ===== Structure Encoder (VQ-VAE tokens) =====
|
| 646 |
+
if config.use_3d:
|
| 647 |
+
struct_config = config.to_struct_config()
|
| 648 |
+
self.struct_embeddings = GlycanBERTEmbeddings(struct_config)
|
| 649 |
+
self.struct_layers = nn.ModuleList([GlycanBERTLayer(struct_config) for _ in range(struct_config.num_hidden_layers)])
|
| 650 |
+
self.struct_mlm_head = nn.Linear(struct_config.hidden_size, struct_config.vocab_size)
|
| 651 |
+
|
| 652 |
+
# Cross-attention layer (sequence → VQ-VAE structural tokens)
|
| 653 |
+
if config.use_cross_attention:
|
| 654 |
+
self.cross_attention = CrossAttentionLayer(config)
|
| 655 |
+
|
| 656 |
+
# ===== Projection layers (align hidden sizes) =====
|
| 657 |
+
if config.ms_hidden_size != config.seq_hidden_size:
|
| 658 |
+
self.ms_projection = nn.Linear(config.ms_hidden_size, config.seq_hidden_size)
|
| 659 |
+
else:
|
| 660 |
+
self.ms_projection = nn.Identity()
|
| 661 |
+
|
| 662 |
+
if config.use_3d and config.struct_hidden_size != config.seq_hidden_size:
|
| 663 |
+
self.struct_projection = nn.Linear(config.struct_hidden_size, config.seq_hidden_size)
|
| 664 |
+
else:
|
| 665 |
+
self.struct_projection = nn.Identity()
|
| 666 |
+
|
| 667 |
+
# ===== Fusion Layer =====
|
| 668 |
+
# Concatenate seq + ms + struct
|
| 669 |
+
fusion_input_size = config.seq_hidden_size * (3 if config.use_3d else 2)
|
| 670 |
+
self.fusion_layer = nn.Sequential(
|
| 671 |
+
nn.Linear(fusion_input_size, config.fusion_hidden_size),
|
| 672 |
+
nn.LayerNorm(config.fusion_hidden_size, eps=config.layer_norm_eps),
|
| 673 |
+
nn.GELU(),
|
| 674 |
+
nn.Dropout(config.hidden_dropout_prob),
|
| 675 |
+
nn.Linear(config.fusion_hidden_size, config.fusion_hidden_size),
|
| 676 |
+
)
|
| 677 |
+
|
| 678 |
+
# ===== Distance Prediction Head (Topology) =====
|
| 679 |
+
# OPTIMIZED: Project down to 128 dim first to save GPU memory
|
| 680 |
+
# (Batch, 256, 256, 768) -> (Batch, 256, 256, 128) reduces memory by 6x
|
| 681 |
+
self.dist_proj = nn.Linear(config.seq_hidden_size, 128)
|
| 682 |
+
self.distance_head = nn.Sequential(
|
| 683 |
+
nn.Linear(128, 64),
|
| 684 |
+
nn.ReLU(),
|
| 685 |
+
nn.Linear(64, 1)
|
| 686 |
+
)
|
| 687 |
+
|
| 688 |
+
# Initialize weights
|
| 689 |
+
self.apply(self._init_weights)
|
| 690 |
+
|
| 691 |
+
def _init_weights(self, module):
|
| 692 |
+
"""Initialize weights."""
|
| 693 |
+
if isinstance(module, nn.Linear):
|
| 694 |
+
module.weight.data.normal_(mean=0.0, std=self.config.initializer_range)
|
| 695 |
+
if module.bias is not None:
|
| 696 |
+
module.bias.data.zero_()
|
| 697 |
+
elif isinstance(module, nn.Embedding):
|
| 698 |
+
module.weight.data.normal_(mean=0.0, std=self.config.initializer_range)
|
| 699 |
+
if module.padding_idx is not None:
|
| 700 |
+
module.weight.data[module.padding_idx].zero_()
|
| 701 |
+
elif isinstance(module, nn.LayerNorm):
|
| 702 |
+
module.bias.data.zero_()
|
| 703 |
+
module.weight.data.fill_(1.0)
|
| 704 |
+
|
| 705 |
+
def forward(
|
| 706 |
+
self,
|
| 707 |
+
seq_token_ids: torch.Tensor,
|
| 708 |
+
seq_attention_mask: torch.Tensor,
|
| 709 |
+
seq_residue_ids: torch.Tensor,
|
| 710 |
+
seq_branch_depths: Optional[torch.Tensor] = None, # NEW: Branch depths
|
| 711 |
+
seq_linkage_types: Optional[torch.Tensor] = None, # NEW: Linkage types
|
| 712 |
+
ms_token_ids: torch.Tensor = None,
|
| 713 |
+
ms_attention_mask: torch.Tensor = None,
|
| 714 |
+
has_ms: torch.Tensor = None,
|
| 715 |
+
struct_token_ids: Optional[torch.Tensor] = None,
|
| 716 |
+
struct_attention_mask: Optional[torch.Tensor] = None,
|
| 717 |
+
struct_residue_ids: Optional[torch.Tensor] = None,
|
| 718 |
+
has_3d: Optional[torch.Tensor] = None,
|
| 719 |
+
seq_labels: Optional[torch.Tensor] = None,
|
| 720 |
+
ms_labels: Optional[torch.Tensor] = None,
|
| 721 |
+
struct_labels: Optional[torch.Tensor] = None,
|
| 722 |
+
dist_labels: Optional[torch.Tensor] = None, # NEW: Topology distance labels
|
| 723 |
+
return_dict: bool = True,
|
| 724 |
+
) -> Dict[str, torch.Tensor]:
|
| 725 |
+
"""
|
| 726 |
+
Forward pass for multimodal BERT v3.
|
| 727 |
+
|
| 728 |
+
Args:
|
| 729 |
+
seq_token_ids: (batch_size, seq_len) - Sequence token IDs
|
| 730 |
+
seq_attention_mask: (batch_size, seq_len) - Sequence attention mask
|
| 731 |
+
seq_residue_ids: (batch_size, seq_len) - Sequence token residue IDs
|
| 732 |
+
ms_token_ids: (batch_size, ms_len) - MS token IDs
|
| 733 |
+
ms_attention_mask: (batch_size, ms_len) - MS attention mask
|
| 734 |
+
has_ms: (batch_size,) - Boolean mask for samples with MS data
|
| 735 |
+
struct_token_ids: (batch_size, struct_len) - Structure VQ-VAE token IDs (optional)
|
| 736 |
+
struct_attention_mask: (batch_size, struct_len) - Structure attention mask (optional)
|
| 737 |
+
struct_residue_ids: (batch_size, struct_len) - Structure token residue IDs (optional)
|
| 738 |
+
has_3d: (batch_size,) - Boolean mask for samples with 3D data (optional)
|
| 739 |
+
seq_labels: (batch_size, seq_len) - Masked sequence labels (optional)
|
| 740 |
+
ms_labels: (batch_size, ms_len) - Masked MS labels (optional)
|
| 741 |
+
struct_labels: (batch_size, struct_len) - Masked structure labels (optional)
|
| 742 |
+
return_dict: Whether to return dict or tuple
|
| 743 |
+
|
| 744 |
+
Returns:
|
| 745 |
+
Dictionary containing logits, hidden states, losses, etc.
|
| 746 |
+
"""
|
| 747 |
+
batch_size = seq_token_ids.shape[0]
|
| 748 |
+
device = seq_token_ids.device
|
| 749 |
+
|
| 750 |
+
# ===== Sequence Encoder =====
|
| 751 |
+
# Pass branch_depths and linkage_types to embeddings for tree-aware encoding
|
| 752 |
+
seq_hidden = self.seq_embeddings(seq_token_ids, seq_branch_depths, seq_linkage_types)
|
| 753 |
+
for layer in self.seq_layers:
|
| 754 |
+
seq_hidden = layer(seq_hidden, seq_attention_mask)
|
| 755 |
+
|
| 756 |
+
seq_pooled = seq_hidden[:, 0, :] # [CLS] token
|
| 757 |
+
seq_logits = self.seq_mlm_head(seq_hidden)
|
| 758 |
+
|
| 759 |
+
# ===== Distance Predictions (Topology) =====
|
| 760 |
+
# Compute pairwise distance predictions
|
| 761 |
+
# MEMORY OPTIMIZATION: Project to 128-dim first
|
| 762 |
+
seq_hidden_small = self.dist_proj(seq_hidden) # (batch, seq_len, 128)
|
| 763 |
+
|
| 764 |
+
# Expand for pairwise: (batch, seq_len, 1, 128) - (batch, 1, seq_len, 128)
|
| 765 |
+
h_i = seq_hidden_small.unsqueeze(2)
|
| 766 |
+
h_j = seq_hidden_small.unsqueeze(1)
|
| 767 |
+
h_diff = torch.abs(h_i - h_j) # (batch, seq_len, seq_len, 128) - Much smaller!
|
| 768 |
+
dist_predictions = self.distance_head(h_diff) # (batch, seq_len, seq_len, 1)
|
| 769 |
+
|
| 770 |
+
# ===== MS Encoder =====
|
| 771 |
+
ms_hidden = None
|
| 772 |
+
ms_pooled = None
|
| 773 |
+
ms_logits = None
|
| 774 |
+
|
| 775 |
+
if ms_token_ids is not None:
|
| 776 |
+
ms_hidden = self.ms_embeddings(ms_token_ids)
|
| 777 |
+
for layer in self.ms_layers:
|
| 778 |
+
ms_hidden = layer(ms_hidden, ms_attention_mask)
|
| 779 |
+
|
| 780 |
+
ms_pooled = ms_hidden[:, 0, :] # [CLS] token
|
| 781 |
+
ms_logits = self.ms_mlm_head(ms_hidden)
|
| 782 |
+
|
| 783 |
+
# Zero out MS representations for samples without MS data
|
| 784 |
+
if has_ms is not None:
|
| 785 |
+
has_ms_expanded = has_ms.unsqueeze(1).float() # (batch, 1)
|
| 786 |
+
ms_pooled = ms_pooled * has_ms_expanded
|
| 787 |
+
|
| 788 |
+
# ===== Structure Encoder =====
|
| 789 |
+
struct_pooled = None
|
| 790 |
+
struct_logits = None
|
| 791 |
+
struct_hidden = None
|
| 792 |
+
|
| 793 |
+
if self.config.use_3d and struct_token_ids is not None:
|
| 794 |
+
struct_hidden = self.struct_embeddings(struct_token_ids)
|
| 795 |
+
for layer in self.struct_layers:
|
| 796 |
+
struct_hidden = layer(struct_hidden, struct_attention_mask)
|
| 797 |
+
|
| 798 |
+
struct_pooled = struct_hidden[:, 0, :] # [CLS] token
|
| 799 |
+
struct_logits = self.struct_mlm_head(struct_hidden)
|
| 800 |
+
|
| 801 |
+
# Zero out structure representations for samples without 3D data
|
| 802 |
+
if has_3d is not None:
|
| 803 |
+
has_3d_expanded = has_3d.unsqueeze(1).float() # (batch, 1)
|
| 804 |
+
struct_pooled = struct_pooled * has_3d_expanded
|
| 805 |
+
|
| 806 |
+
# ===== Cross-Attention (Sequence → VQ-VAE Structural Tokens) =====
|
| 807 |
+
# Use residue-level alignment between WURCS tokens and VQ-VAE tokens
|
| 808 |
+
if self.config.use_cross_attention and struct_residue_ids is not None:
|
| 809 |
+
# Create residue-level mask
|
| 810 |
+
# WURCS token with residue_id=0 → VQ-VAE tokens with residue_id=0
|
| 811 |
+
residue_mask = create_residue_level_mask(
|
| 812 |
+
seq_residue_ids=seq_residue_ids,
|
| 813 |
+
struct_residue_ids=struct_residue_ids,
|
| 814 |
+
) # (batch, N_seq, N_struct)
|
| 815 |
+
|
| 816 |
+
# Apply cross-attention: sequence tokens attend to VQ-VAE tokens
|
| 817 |
+
seq_hidden = self.cross_attention(
|
| 818 |
+
seq_hidden=seq_hidden,
|
| 819 |
+
struct_hidden=struct_hidden, # VQ-VAE token features
|
| 820 |
+
attention_mask=residue_mask, # Residue-based mask
|
| 821 |
+
)
|
| 822 |
+
|
| 823 |
+
# Update seq_pooled after cross-attention
|
| 824 |
+
seq_pooled = seq_hidden[:, 0, :]
|
| 825 |
+
|
| 826 |
+
# ===== Fusion =====
|
| 827 |
+
# Project to common hidden size
|
| 828 |
+
ms_pooled_projected = self.ms_projection(ms_pooled)
|
| 829 |
+
|
| 830 |
+
if self.config.use_3d and struct_pooled is not None:
|
| 831 |
+
struct_pooled_projected = self.struct_projection(struct_pooled)
|
| 832 |
+
combined = torch.cat([seq_pooled, ms_pooled_projected, struct_pooled_projected], dim=-1)
|
| 833 |
+
else:
|
| 834 |
+
combined = torch.cat([seq_pooled, ms_pooled_projected], dim=-1)
|
| 835 |
+
|
| 836 |
+
fused_repr = self.fusion_layer(combined)
|
| 837 |
+
|
| 838 |
+
# ===== Compute Losses =====
|
| 839 |
+
total_loss = None
|
| 840 |
+
seq_loss = None
|
| 841 |
+
ms_loss = None
|
| 842 |
+
struct_loss = None
|
| 843 |
+
dist_loss = None # NEW: Topology distance loss
|
| 844 |
+
|
| 845 |
+
if seq_labels is not None:
|
| 846 |
+
loss_fct = nn.CrossEntropyLoss(ignore_index=-100)
|
| 847 |
+
seq_loss = loss_fct(
|
| 848 |
+
seq_logits.view(-1, self.config.seq_vocab_size),
|
| 849 |
+
seq_labels.view(-1)
|
| 850 |
+
)
|
| 851 |
+
|
| 852 |
+
if ms_labels is not None:
|
| 853 |
+
ms_labels_masked = ms_labels.clone()
|
| 854 |
+
ms_labels_masked[~has_ms] = -100
|
| 855 |
+
# Only compute loss if there are valid labels (not all -100)
|
| 856 |
+
if (ms_labels_masked != -100).any():
|
| 857 |
+
loss_fct = nn.CrossEntropyLoss(ignore_index=-100)
|
| 858 |
+
ms_loss = loss_fct(
|
| 859 |
+
ms_logits.view(-1, self.config.ms_total_vocab_size),
|
| 860 |
+
ms_labels_masked.view(-1)
|
| 861 |
+
)
|
| 862 |
+
else:
|
| 863 |
+
ms_loss = torch.tensor(0.0, device=seq_token_ids.device)
|
| 864 |
+
|
| 865 |
+
if self.config.use_3d and struct_labels is not None and struct_logits is not None:
|
| 866 |
+
struct_labels_masked = struct_labels.clone()
|
| 867 |
+
if has_3d is not None:
|
| 868 |
+
struct_labels_masked[~has_3d] = -100
|
| 869 |
+
# Only compute loss if there are valid labels (not all -100)
|
| 870 |
+
if (struct_labels_masked != -100).any():
|
| 871 |
+
loss_fct = nn.CrossEntropyLoss(ignore_index=-100)
|
| 872 |
+
struct_loss = loss_fct(
|
| 873 |
+
struct_logits.view(-1, self.config.struct_vocab_size),
|
| 874 |
+
struct_labels_masked.view(-1)
|
| 875 |
+
)
|
| 876 |
+
else:
|
| 877 |
+
struct_loss = torch.tensor(0.0, device=seq_token_ids.device)
|
| 878 |
+
|
| 879 |
+
# ===== Distance Loss (Topology) =====
|
| 880 |
+
if dist_labels is not None:
|
| 881 |
+
# dist_predictions: (Batch, Seq, Seq, 1) -> (Batch, Seq, Seq)
|
| 882 |
+
preds = dist_predictions.squeeze(-1)
|
| 883 |
+
|
| 884 |
+
# Create mask for valid distance pairs (label != -1)
|
| 885 |
+
# Also respect attention mask to avoid padding
|
| 886 |
+
valid_mask = (dist_labels != -1) & (seq_attention_mask.unsqueeze(1) * seq_attention_mask.unsqueeze(2) == 1)
|
| 887 |
+
|
| 888 |
+
# DEBUG: Print once
|
| 889 |
+
if not hasattr(self, '_dist_debug_printed'):
|
| 890 |
+
print(f"[DIST DEBUG] dist_labels shape: {dist_labels.shape}, valid_mask.sum: {valid_mask.sum().item()}")
|
| 891 |
+
self._dist_debug_printed = True
|
| 892 |
+
|
| 893 |
+
if valid_mask.sum() > 0:
|
| 894 |
+
# MSE loss on valid positions only
|
| 895 |
+
loss_fct = nn.MSELoss()
|
| 896 |
+
dist_loss = loss_fct(preds[valid_mask], dist_labels[valid_mask].float())
|
| 897 |
+
else:
|
| 898 |
+
dist_loss = torch.tensor(0.0, device=seq_token_ids.device)
|
| 899 |
+
else:
|
| 900 |
+
# DEBUG: dist_labels is None
|
| 901 |
+
if not hasattr(self, '_dist_none_printed'):
|
| 902 |
+
print("[DIST DEBUG] dist_labels is None!")
|
| 903 |
+
self._dist_none_printed = True
|
| 904 |
+
|
| 905 |
+
# Weighted combination
|
| 906 |
+
losses = []
|
| 907 |
+
if seq_loss is not None:
|
| 908 |
+
losses.append(self.config.seq_loss_weight * seq_loss)
|
| 909 |
+
if ms_loss is not None:
|
| 910 |
+
losses.append(self.config.ms_loss_weight * ms_loss)
|
| 911 |
+
if struct_loss is not None:
|
| 912 |
+
losses.append(self.config.struct_loss_weight * struct_loss)
|
| 913 |
+
if dist_loss is not None:
|
| 914 |
+
losses.append(self.config.dist_loss_weight * dist_loss)
|
| 915 |
+
|
| 916 |
+
if losses:
|
| 917 |
+
total_loss = sum(losses)
|
| 918 |
+
|
| 919 |
+
if return_dict:
|
| 920 |
+
return {
|
| 921 |
+
'loss': total_loss,
|
| 922 |
+
'seq_loss': seq_loss,
|
| 923 |
+
'ms_loss': ms_loss,
|
| 924 |
+
'struct_loss': struct_loss,
|
| 925 |
+
'dist_loss': dist_loss, # NEW: Topology loss
|
| 926 |
+
'seq_logits': seq_logits,
|
| 927 |
+
'ms_logits': ms_logits,
|
| 928 |
+
'struct_logits': struct_logits,
|
| 929 |
+
'dist_predictions': dist_predictions, # NEW: Distance predictions
|
| 930 |
+
'seq_hidden': seq_hidden,
|
| 931 |
+
'ms_hidden': ms_hidden,
|
| 932 |
+
'struct_hidden': struct_hidden,
|
| 933 |
+
'seq_pooled': seq_pooled,
|
| 934 |
+
'ms_pooled': ms_pooled,
|
| 935 |
+
'struct_pooled': struct_pooled,
|
| 936 |
+
'fused_repr': fused_repr,
|
| 937 |
+
}
|
| 938 |
+
else:
|
| 939 |
+
return (total_loss, seq_logits, ms_logits, struct_logits, fused_repr)
|
| 940 |
+
|
| 941 |
+
def get_multimodal_representation(
|
| 942 |
+
self,
|
| 943 |
+
seq_token_ids: torch.Tensor,
|
| 944 |
+
seq_attention_mask: torch.Tensor,
|
| 945 |
+
seq_residue_ids: torch.Tensor,
|
| 946 |
+
ms_token_ids: torch.Tensor,
|
| 947 |
+
ms_attention_mask: torch.Tensor,
|
| 948 |
+
has_ms: torch.Tensor,
|
| 949 |
+
struct_token_ids: Optional[torch.Tensor] = None,
|
| 950 |
+
struct_attention_mask: Optional[torch.Tensor] = None,
|
| 951 |
+
struct_residue_ids: Optional[torch.Tensor] = None,
|
| 952 |
+
has_3d: Optional[torch.Tensor] = None,
|
| 953 |
+
) -> torch.Tensor:
|
| 954 |
+
"""Get fused multimodal representation (for inference)."""
|
| 955 |
+
outputs = self.forward(
|
| 956 |
+
seq_token_ids=seq_token_ids,
|
| 957 |
+
seq_attention_mask=seq_attention_mask,
|
| 958 |
+
seq_residue_ids=seq_residue_ids,
|
| 959 |
+
ms_token_ids=ms_token_ids,
|
| 960 |
+
ms_attention_mask=ms_attention_mask,
|
| 961 |
+
has_ms=has_ms,
|
| 962 |
+
struct_token_ids=struct_token_ids,
|
| 963 |
+
struct_attention_mask=struct_attention_mask,
|
| 964 |
+
struct_residue_ids=struct_residue_ids,
|
| 965 |
+
has_3d=has_3d,
|
| 966 |
+
return_dict=True,
|
| 967 |
+
)
|
| 968 |
+
return outputs['fused_repr']
|
| 969 |
+
|
| 970 |
+
|
| 971 |
+
if __name__ == "__main__":
|
| 972 |
+
# Test the model
|
| 973 |
+
print("="*80)
|
| 974 |
+
print("Testing Multimodal GlycanBERT v3")
|
| 975 |
+
print("="*80)
|
| 976 |
+
|
| 977 |
+
# Create config
|
| 978 |
+
config = MultimodalGlycanBERTConfig(
|
| 979 |
+
seq_vocab_size=166,
|
| 980 |
+
seq_hidden_size=768,
|
| 981 |
+
seq_num_layers=12,
|
| 982 |
+
seq_num_heads=12,
|
| 983 |
+
ms_vocab_size=242,
|
| 984 |
+
ms_hidden_size=384,
|
| 985 |
+
ms_num_layers=6,
|
| 986 |
+
ms_num_heads=6,
|
| 987 |
+
struct_vocab_size=1024,
|
| 988 |
+
struct_hidden_size=512,
|
| 989 |
+
struct_num_layers=8,
|
| 990 |
+
struct_num_heads=8,
|
| 991 |
+
use_3d=True,
|
| 992 |
+
use_cross_attention=True,
|
| 993 |
+
seq_loss_weight=0.60,
|
| 994 |
+
ms_loss_weight=0.15,
|
| 995 |
+
struct_loss_weight=0.25,
|
| 996 |
+
)
|
| 997 |
+
|
| 998 |
+
print(f"\nConfig:")
|
| 999 |
+
print(f" Sequence vocab: {config.seq_vocab_size}")
|
| 1000 |
+
print(f" MS vocab: {config.ms_vocab_size}")
|
| 1001 |
+
print(f" Structure vocab: {config.struct_vocab_size}")
|
| 1002 |
+
print(f" Loss weights: seq={config.seq_loss_weight}, ms={config.ms_loss_weight}, struct={config.struct_loss_weight}")
|
| 1003 |
+
|
| 1004 |
+
# Create model
|
| 1005 |
+
model = MultimodalGlycanBERT(config)
|
| 1006 |
+
|
| 1007 |
+
# Count parameters
|
| 1008 |
+
total_params = sum(p.numel() for p in model.parameters())
|
| 1009 |
+
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
|
| 1010 |
+
|
| 1011 |
+
print(f"\nModel Parameters:")
|
| 1012 |
+
print(f" Total: {total_params:,}")
|
| 1013 |
+
print(f" Trainable: {trainable_params:,}")
|
| 1014 |
+
|
| 1015 |
+
# Test forward pass
|
| 1016 |
+
print(f"\n{'='*80}")
|
| 1017 |
+
print("Testing Forward Pass (with Conv front-end)")
|
| 1018 |
+
print("="*80)
|
| 1019 |
+
|
| 1020 |
+
batch_size = 4
|
| 1021 |
+
seq_len = 128
|
| 1022 |
+
ms_len = 50
|
| 1023 |
+
struct_len = 40
|
| 1024 |
+
|
| 1025 |
+
# Create dummy inputs
|
| 1026 |
+
seq_token_ids = torch.randint(0, config.seq_vocab_size, (batch_size, seq_len))
|
| 1027 |
+
seq_attention_mask = torch.ones(batch_size, seq_len)
|
| 1028 |
+
# Approximate: ~5 tokens per residue
|
| 1029 |
+
seq_residue_ids = torch.div(
|
| 1030 |
+
torch.arange(seq_len), 5, rounding_mode="floor"
|
| 1031 |
+
).unsqueeze(0).expand(batch_size, -1)
|
| 1032 |
+
|
| 1033 |
+
ms_token_ids = torch.randint(config.ms_vocab_offset, config.ms_total_vocab_size, (batch_size, ms_len))
|
| 1034 |
+
ms_attention_mask = torch.ones(batch_size, ms_len)
|
| 1035 |
+
struct_token_ids = torch.randint(0, config.struct_vocab_size, (batch_size, struct_len))
|
| 1036 |
+
struct_attention_mask = torch.ones(batch_size, struct_len)
|
| 1037 |
+
# Approximate: 4 tokens per residue for VQ-VAE tokens
|
| 1038 |
+
struct_residue_ids = torch.div(
|
| 1039 |
+
torch.arange(struct_len), 4, rounding_mode="floor"
|
| 1040 |
+
).unsqueeze(0).expand(batch_size, -1)
|
| 1041 |
+
|
| 1042 |
+
has_ms = torch.tensor([True, True, False, True])
|
| 1043 |
+
has_3d = torch.tensor([True, False, True, True])
|
| 1044 |
+
|
| 1045 |
+
# Create labels for MLM
|
| 1046 |
+
seq_labels = seq_token_ids.clone()
|
| 1047 |
+
seq_labels[seq_labels != config.mask_token_id] = -100
|
| 1048 |
+
ms_labels = ms_token_ids.clone()
|
| 1049 |
+
ms_labels[ms_labels != config.mask_token_id] = -100
|
| 1050 |
+
struct_labels = struct_token_ids.clone()
|
| 1051 |
+
struct_labels[struct_labels != config.mask_token_id] = -100
|
| 1052 |
+
|
| 1053 |
+
# Forward pass
|
| 1054 |
+
outputs = model(
|
| 1055 |
+
seq_token_ids=seq_token_ids,
|
| 1056 |
+
seq_attention_mask=seq_attention_mask,
|
| 1057 |
+
seq_residue_ids=seq_residue_ids,
|
| 1058 |
+
ms_token_ids=ms_token_ids,
|
| 1059 |
+
ms_attention_mask=ms_attention_mask,
|
| 1060 |
+
has_ms=has_ms,
|
| 1061 |
+
struct_token_ids=struct_token_ids,
|
| 1062 |
+
struct_attention_mask=struct_attention_mask,
|
| 1063 |
+
struct_residue_ids=struct_residue_ids,
|
| 1064 |
+
has_3d=has_3d,
|
| 1065 |
+
seq_labels=seq_labels,
|
| 1066 |
+
ms_labels=ms_labels,
|
| 1067 |
+
struct_labels=struct_labels,
|
| 1068 |
+
)
|
| 1069 |
+
|
| 1070 |
+
print(f"\nOutput shapes:")
|
| 1071 |
+
print(f" seq_logits: {outputs['seq_logits'].shape}")
|
| 1072 |
+
print(f" ms_logits: {outputs['ms_logits'].shape}")
|
| 1073 |
+
print(f" struct_logits: {outputs['struct_logits'].shape}")
|
| 1074 |
+
print(f" fused_repr: {outputs['fused_repr'].shape}")
|
| 1075 |
+
|
| 1076 |
+
print(f"\nLosses:")
|
| 1077 |
+
print(f" Total loss: {outputs['loss'].item():.4f}")
|
| 1078 |
+
print(f" Sequence loss: {outputs['seq_loss'].item():.4f}")
|
| 1079 |
+
print(f" MS loss: {outputs['ms_loss'].item():.4f}")
|
| 1080 |
+
print(f" Structure loss: {outputs['struct_loss'].item():.4f}")
|
| 1081 |
+
|
| 1082 |
+
print(f"\n{'='*80}")
|
| 1083 |
+
print("Model Test Complete!")
|
| 1084 |
+
print("="*80)
|
releases/2026-10-02/iar_completion/runtime_snapshot/project/writing/cluster/nature_submission/code/training/ipa_bpe_distillation.py
ADDED
|
@@ -0,0 +1,377 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""
|
| 3 |
+
IPA Self-Distillation for BPE Tokenized Glycan Sequences
|
| 4 |
+
Iterative Pseudo-Annotation (IPA) to resolve ambiguous BPE tokens.
|
| 5 |
+
"""
|
| 6 |
+
|
| 7 |
+
import sys
|
| 8 |
+
import torch
|
| 9 |
+
import torch.nn.functional as F
|
| 10 |
+
import numpy as np
|
| 11 |
+
from pathlib import Path
|
| 12 |
+
from typing import List, Dict, Set, Tuple
|
| 13 |
+
import logging
|
| 14 |
+
import pickle
|
| 15 |
+
import json
|
| 16 |
+
import argparse
|
| 17 |
+
from copy import deepcopy
|
| 18 |
+
from tqdm import tqdm
|
| 19 |
+
|
| 20 |
+
# Add parent path for model imports
|
| 21 |
+
sys.path.insert(0, str(Path(__file__).parent.parent))
|
| 22 |
+
|
| 23 |
+
from model.multimodal_glycan_bert_v3 import MultimodalGlycanBERT, MultimodalGlycanBERTConfig
|
| 24 |
+
|
| 25 |
+
logger = logging.getLogger(__name__)
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
class BPEIPADistiller:
|
| 29 |
+
"""IPA Self-Distillation for BPE tokenized sequences."""
|
| 30 |
+
|
| 31 |
+
def __init__(
|
| 32 |
+
self,
|
| 33 |
+
checkpoint_path: str,
|
| 34 |
+
vocab_path: str,
|
| 35 |
+
ambiguity_path: str,
|
| 36 |
+
device: str = "cuda",
|
| 37 |
+
threshold: float = 0.8,
|
| 38 |
+
batch_size: int = 32,
|
| 39 |
+
):
|
| 40 |
+
self.checkpoint_path = Path(checkpoint_path)
|
| 41 |
+
self.vocab_path = Path(vocab_path)
|
| 42 |
+
self.device = torch.device(device)
|
| 43 |
+
self.threshold = threshold
|
| 44 |
+
self.batch_size = batch_size
|
| 45 |
+
|
| 46 |
+
# Load vocabulary
|
| 47 |
+
logger.info(f"Loading BPE vocabulary from {vocab_path}")
|
| 48 |
+
with open(vocab_path, 'r') as f:
|
| 49 |
+
vocab = json.load(f)
|
| 50 |
+
|
| 51 |
+
self.vocab = vocab
|
| 52 |
+
self.token_to_id = vocab.get('token_to_id', vocab)
|
| 53 |
+
self.id_to_token = {v: k for k, v in self.token_to_id.items()}
|
| 54 |
+
self.vocab_size = len(self.token_to_id)
|
| 55 |
+
|
| 56 |
+
# Special tokens
|
| 57 |
+
self.pad_id = self.token_to_id.get('[PAD]', 0)
|
| 58 |
+
self.mask_id = self.token_to_id.get('[MASK]', 4)
|
| 59 |
+
self.start_id = self.token_to_id.get('[START]', 2)
|
| 60 |
+
self.end_id = self.token_to_id.get('[END]', 3)
|
| 61 |
+
|
| 62 |
+
logger.info(f"Vocabulary size: {self.vocab_size}")
|
| 63 |
+
logger.info(f"MASK token ID: {self.mask_id}")
|
| 64 |
+
|
| 65 |
+
# Load ambiguous token IDs
|
| 66 |
+
logger.info(f"Loading ambiguity data from {ambiguity_path}")
|
| 67 |
+
with open(ambiguity_path, 'r') as f:
|
| 68 |
+
ambig_data = json.load(f)
|
| 69 |
+
|
| 70 |
+
self.ambiguous_token_ids = set(ambig_data.get('ambiguous_ids', []))
|
| 71 |
+
self.ambiguous_tokens = ambig_data.get('ambiguous_tokens', {})
|
| 72 |
+
|
| 73 |
+
logger.info(f"Ambiguous BPE tokens: {len(self.ambiguous_token_ids)}")
|
| 74 |
+
|
| 75 |
+
# Load model
|
| 76 |
+
logger.info(f"Loading model from {checkpoint_path}")
|
| 77 |
+
self.model = self._load_model()
|
| 78 |
+
self.model.to(self.device)
|
| 79 |
+
self.model.eval()
|
| 80 |
+
|
| 81 |
+
logger.info(f"BPE IPA Distiller initialized (threshold={threshold})")
|
| 82 |
+
|
| 83 |
+
def _load_model(self) -> MultimodalGlycanBERT:
|
| 84 |
+
"""Load model from checkpoint."""
|
| 85 |
+
checkpoint = torch.load(self.checkpoint_path, map_location=self.device)
|
| 86 |
+
|
| 87 |
+
if 'config' in checkpoint:
|
| 88 |
+
cfg = checkpoint['config']['model']
|
| 89 |
+
else:
|
| 90 |
+
cfg = {
|
| 91 |
+
'sequence': {'vocab_size': 2200, 'hidden_size': 768, 'num_hidden_layers': 12,
|
| 92 |
+
'num_attention_heads': 12, 'max_length': 256},
|
| 93 |
+
'mass_spectrometry': {'vocab_size': 242, 'hidden_size': 384,
|
| 94 |
+
'num_hidden_layers': 6, 'num_attention_heads': 6, 'max_length': 150},
|
| 95 |
+
'structure_3d': {'vocab_size': 1024, 'hidden_size': 512,
|
| 96 |
+
'num_hidden_layers': 8, 'num_attention_heads': 8, 'max_length': 200},
|
| 97 |
+
'fusion': {'fusion_hidden_size': 768, 'fusion_num_layers': 2},
|
| 98 |
+
}
|
| 99 |
+
|
| 100 |
+
config = MultimodalGlycanBERTConfig(
|
| 101 |
+
seq_vocab_size=cfg['sequence']['vocab_size'],
|
| 102 |
+
seq_hidden_size=cfg['sequence']['hidden_size'],
|
| 103 |
+
seq_num_layers=cfg['sequence']['num_hidden_layers'],
|
| 104 |
+
seq_num_heads=cfg['sequence']['num_attention_heads'],
|
| 105 |
+
seq_max_length=cfg['sequence']['max_length'],
|
| 106 |
+
ms_vocab_size=cfg['mass_spectrometry']['vocab_size'],
|
| 107 |
+
ms_hidden_size=cfg['mass_spectrometry']['hidden_size'],
|
| 108 |
+
ms_num_layers=cfg['mass_spectrometry']['num_hidden_layers'],
|
| 109 |
+
ms_num_heads=cfg['mass_spectrometry']['num_attention_heads'],
|
| 110 |
+
ms_max_length=cfg['mass_spectrometry']['max_length'],
|
| 111 |
+
struct_vocab_size=cfg['structure_3d']['vocab_size'],
|
| 112 |
+
struct_hidden_size=cfg['structure_3d']['hidden_size'],
|
| 113 |
+
struct_num_layers=cfg['structure_3d']['num_hidden_layers'],
|
| 114 |
+
struct_num_heads=cfg['structure_3d']['num_attention_heads'],
|
| 115 |
+
struct_max_length=cfg['structure_3d']['max_length'],
|
| 116 |
+
fusion_hidden_size=cfg['fusion']['fusion_hidden_size'],
|
| 117 |
+
fusion_num_layers=cfg['fusion']['fusion_num_layers'],
|
| 118 |
+
)
|
| 119 |
+
|
| 120 |
+
model = MultimodalGlycanBERT(config)
|
| 121 |
+
|
| 122 |
+
if 'model_state_dict' in checkpoint:
|
| 123 |
+
model.load_state_dict(checkpoint['model_state_dict'])
|
| 124 |
+
else:
|
| 125 |
+
model.load_state_dict(checkpoint)
|
| 126 |
+
|
| 127 |
+
return model
|
| 128 |
+
|
| 129 |
+
def find_ambiguous_sequences(self, sequences: List[Dict]) -> Tuple[List[Dict], List[Dict], Dict]:
|
| 130 |
+
"""Separate sequences into ambiguous and clean."""
|
| 131 |
+
ambiguous, clean = [], []
|
| 132 |
+
total_ambig_tokens = 0
|
| 133 |
+
|
| 134 |
+
for seq in sequences:
|
| 135 |
+
token_ids = seq.get('token_ids', [])
|
| 136 |
+
ambig_count = sum(1 for tid in token_ids if tid in self.ambiguous_token_ids)
|
| 137 |
+
|
| 138 |
+
if ambig_count > 0:
|
| 139 |
+
seq_copy = seq.copy()
|
| 140 |
+
seq_copy['_ambig_count'] = ambig_count
|
| 141 |
+
ambiguous.append(seq_copy)
|
| 142 |
+
total_ambig_tokens += ambig_count
|
| 143 |
+
else:
|
| 144 |
+
clean.append(seq)
|
| 145 |
+
|
| 146 |
+
stats = {
|
| 147 |
+
'total_sequences': len(sequences),
|
| 148 |
+
'ambiguous_sequences': len(ambiguous),
|
| 149 |
+
'clean_sequences': len(clean),
|
| 150 |
+
'total_ambiguous_tokens': total_ambig_tokens,
|
| 151 |
+
'ambiguous_percentage': 100 * len(ambiguous) / len(sequences) if sequences else 0,
|
| 152 |
+
}
|
| 153 |
+
|
| 154 |
+
return ambiguous, clean, stats
|
| 155 |
+
|
| 156 |
+
@torch.no_grad()
|
| 157 |
+
def resolve_batch(self, sequences: List[Dict], max_length: int = 256) -> Tuple[List[Dict], int, int]:
|
| 158 |
+
"""Resolve ambiguous tokens in a batch."""
|
| 159 |
+
if not sequences:
|
| 160 |
+
return [], 0, 0
|
| 161 |
+
|
| 162 |
+
batch_token_ids, batch_attention_masks, batch_ambig_positions = [], [], []
|
| 163 |
+
|
| 164 |
+
for seq in sequences:
|
| 165 |
+
token_ids = list(seq.get('token_ids', []))
|
| 166 |
+
ambig_positions = [i for i, tid in enumerate(token_ids) if tid in self.ambiguous_token_ids]
|
| 167 |
+
batch_ambig_positions.append(ambig_positions)
|
| 168 |
+
|
| 169 |
+
if len(token_ids) > max_length:
|
| 170 |
+
token_ids = token_ids[:max_length]
|
| 171 |
+
|
| 172 |
+
attention_mask = [1] * len(token_ids)
|
| 173 |
+
pad_length = max_length - len(token_ids)
|
| 174 |
+
token_ids = token_ids + [self.pad_id] * pad_length
|
| 175 |
+
attention_mask = attention_mask + [0] * pad_length
|
| 176 |
+
|
| 177 |
+
masked_ids = token_ids.copy()
|
| 178 |
+
for pos in ambig_positions:
|
| 179 |
+
if pos < max_length:
|
| 180 |
+
masked_ids[pos] = self.mask_id
|
| 181 |
+
|
| 182 |
+
batch_token_ids.append(masked_ids)
|
| 183 |
+
batch_attention_masks.append(attention_mask)
|
| 184 |
+
|
| 185 |
+
seq_tensor = torch.tensor(batch_token_ids, dtype=torch.long, device=self.device)
|
| 186 |
+
attention_tensor = torch.tensor(batch_attention_masks, dtype=torch.long, device=self.device)
|
| 187 |
+
residue_tensor = torch.zeros_like(seq_tensor)
|
| 188 |
+
|
| 189 |
+
batch_size = seq_tensor.shape[0]
|
| 190 |
+
ms_len, struct_len = 150, 200
|
| 191 |
+
|
| 192 |
+
outputs = self.model(
|
| 193 |
+
seq_token_ids=seq_tensor,
|
| 194 |
+
seq_attention_mask=attention_tensor,
|
| 195 |
+
seq_residue_ids=residue_tensor,
|
| 196 |
+
ms_token_ids=torch.zeros(batch_size, ms_len, dtype=torch.long, device=self.device),
|
| 197 |
+
ms_attention_mask=torch.zeros(batch_size, ms_len, dtype=torch.long, device=self.device),
|
| 198 |
+
has_ms=torch.zeros(batch_size, dtype=torch.bool, device=self.device),
|
| 199 |
+
struct_token_ids=torch.zeros(batch_size, struct_len, dtype=torch.long, device=self.device),
|
| 200 |
+
struct_attention_mask=torch.zeros(batch_size, struct_len, dtype=torch.long, device=self.device),
|
| 201 |
+
struct_residue_ids=torch.full((batch_size, struct_len), -1, dtype=torch.long, device=self.device),
|
| 202 |
+
has_3d=torch.zeros(batch_size, dtype=torch.bool, device=self.device),
|
| 203 |
+
return_dict=True,
|
| 204 |
+
)
|
| 205 |
+
|
| 206 |
+
logits = outputs['seq_logits']
|
| 207 |
+
|
| 208 |
+
resolved_sequences = []
|
| 209 |
+
total_resolved, total_remaining = 0, 0
|
| 210 |
+
|
| 211 |
+
for i, seq in enumerate(sequences):
|
| 212 |
+
resolved = deepcopy(seq)
|
| 213 |
+
token_ids = list(resolved['token_ids'])
|
| 214 |
+
ambig_positions = batch_ambig_positions[i]
|
| 215 |
+
n_resolved = 0
|
| 216 |
+
|
| 217 |
+
for pos in ambig_positions:
|
| 218 |
+
if pos >= max_length:
|
| 219 |
+
continue
|
| 220 |
+
|
| 221 |
+
pos_logits = logits[i, pos]
|
| 222 |
+
probs = F.softmax(pos_logits, dim=-1)
|
| 223 |
+
top_prob, top_idx = probs.max(dim=-1)
|
| 224 |
+
confidence = top_prob.item()
|
| 225 |
+
pred_id = top_idx.item()
|
| 226 |
+
|
| 227 |
+
if (confidence >= self.threshold and
|
| 228 |
+
pred_id not in self.ambiguous_token_ids and
|
| 229 |
+
pred_id != token_ids[pos]):
|
| 230 |
+
|
| 231 |
+
original_token = self.id_to_token.get(token_ids[pos], '?')
|
| 232 |
+
new_token = self.id_to_token.get(pred_id, '?')
|
| 233 |
+
|
| 234 |
+
token_ids[pos] = pred_id
|
| 235 |
+
n_resolved += 1
|
| 236 |
+
|
| 237 |
+
if 'resolved_positions' not in resolved:
|
| 238 |
+
resolved['resolved_positions'] = []
|
| 239 |
+
resolved['resolved_positions'].append({
|
| 240 |
+
'pos': pos, 'original': original_token,
|
| 241 |
+
'resolved': new_token, 'confidence': confidence,
|
| 242 |
+
})
|
| 243 |
+
|
| 244 |
+
resolved['token_ids'] = token_ids
|
| 245 |
+
if n_resolved > 0:
|
| 246 |
+
resolved['is_distilled'] = True
|
| 247 |
+
|
| 248 |
+
resolved_sequences.append(resolved)
|
| 249 |
+
total_resolved += n_resolved
|
| 250 |
+
n_remaining = sum(1 for tid in token_ids if tid in self.ambiguous_token_ids)
|
| 251 |
+
total_remaining += n_remaining
|
| 252 |
+
|
| 253 |
+
return resolved_sequences, total_resolved, total_remaining
|
| 254 |
+
|
| 255 |
+
def run_ipa(self, sequences: List[Dict], iterations: int = 3) -> Tuple[List[Dict], Dict]:
|
| 256 |
+
"""Run IPA self-distillation."""
|
| 257 |
+
logger.info(f"Starting BPE IPA self-distillation (threshold={self.threshold}, iterations={iterations})")
|
| 258 |
+
|
| 259 |
+
ambiguous, clean, initial_stats = self.find_ambiguous_sequences(sequences)
|
| 260 |
+
|
| 261 |
+
logger.info(f"Initial: {initial_stats['ambiguous_sequences']} ambiguous sequences ({initial_stats['ambiguous_percentage']:.1f}%)")
|
| 262 |
+
logger.info(f"Total ambiguous tokens: {initial_stats['total_ambiguous_tokens']}")
|
| 263 |
+
|
| 264 |
+
stats = {'initial': initial_stats, 'iterations': [], 'threshold': self.threshold}
|
| 265 |
+
current_sequences = ambiguous
|
| 266 |
+
|
| 267 |
+
for iteration in range(iterations):
|
| 268 |
+
logger.info(f"\n=== Iteration {iteration + 1}/{iterations} ===")
|
| 269 |
+
|
| 270 |
+
resolved_this_iter, total_remaining = 0, 0
|
| 271 |
+
new_sequences = []
|
| 272 |
+
|
| 273 |
+
num_batches = (len(current_sequences) + self.batch_size - 1) // self.batch_size
|
| 274 |
+
|
| 275 |
+
for batch_idx in tqdm(range(num_batches), desc=f"Iteration {iteration + 1}"):
|
| 276 |
+
start_idx = batch_idx * self.batch_size
|
| 277 |
+
end_idx = min(start_idx + self.batch_size, len(current_sequences))
|
| 278 |
+
batch = current_sequences[start_idx:end_idx]
|
| 279 |
+
|
| 280 |
+
resolved_batch, n_resolved, n_remaining = self.resolve_batch(batch)
|
| 281 |
+
new_sequences.extend(resolved_batch)
|
| 282 |
+
resolved_this_iter += n_resolved
|
| 283 |
+
total_remaining += n_remaining
|
| 284 |
+
|
| 285 |
+
current_sequences = new_sequences
|
| 286 |
+
stats['iterations'].append({
|
| 287 |
+
'iteration': iteration + 1,
|
| 288 |
+
'tokens_resolved': resolved_this_iter,
|
| 289 |
+
'tokens_remaining': total_remaining,
|
| 290 |
+
})
|
| 291 |
+
|
| 292 |
+
logger.info(f" Resolved {resolved_this_iter} tokens, {total_remaining} remaining")
|
| 293 |
+
|
| 294 |
+
if resolved_this_iter == 0:
|
| 295 |
+
logger.info(" No progress, stopping early")
|
| 296 |
+
break
|
| 297 |
+
|
| 298 |
+
all_sequences = clean + current_sequences
|
| 299 |
+
_, still_ambiguous, final_stats = self.find_ambiguous_sequences(current_sequences)
|
| 300 |
+
|
| 301 |
+
stats['final'] = {
|
| 302 |
+
'total_sequences': len(all_sequences),
|
| 303 |
+
'fully_resolved': initial_stats['ambiguous_sequences'] - final_stats['ambiguous_sequences'],
|
| 304 |
+
'still_ambiguous': final_stats['ambiguous_sequences'],
|
| 305 |
+
'remaining_ambiguous_tokens': final_stats['total_ambiguous_tokens'],
|
| 306 |
+
'total_tokens_resolved': sum(it['tokens_resolved'] for it in stats['iterations']),
|
| 307 |
+
}
|
| 308 |
+
|
| 309 |
+
logger.info(f"\n=== IPA Complete ===")
|
| 310 |
+
logger.info(f"Total tokens resolved: {stats['final']['total_tokens_resolved']}")
|
| 311 |
+
|
| 312 |
+
return all_sequences, stats
|
| 313 |
+
|
| 314 |
+
|
| 315 |
+
def main():
|
| 316 |
+
parser = argparse.ArgumentParser(description="BPE IPA Self-Distillation")
|
| 317 |
+
parser.add_argument("--checkpoint", type=str, required=True)
|
| 318 |
+
parser.add_argument("--sequences", type=str, required=True)
|
| 319 |
+
parser.add_argument("--vocab", type=str, required=True)
|
| 320 |
+
parser.add_argument("--ambiguity", type=str, required=True)
|
| 321 |
+
parser.add_argument("--output", type=str, required=True)
|
| 322 |
+
parser.add_argument("--threshold", type=float, default=0.8)
|
| 323 |
+
parser.add_argument("--iterations", type=int, default=3)
|
| 324 |
+
parser.add_argument("--batch-size", type=int, default=32)
|
| 325 |
+
parser.add_argument("--device", type=str, default="cuda")
|
| 326 |
+
|
| 327 |
+
args = parser.parse_args()
|
| 328 |
+
|
| 329 |
+
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
| 330 |
+
|
| 331 |
+
logger.info(f"Loading sequences from {args.sequences}")
|
| 332 |
+
with open(args.sequences, 'rb') as f:
|
| 333 |
+
sequences = pickle.load(f)
|
| 334 |
+
|
| 335 |
+
if isinstance(sequences, dict):
|
| 336 |
+
sequences = list(sequences.values())
|
| 337 |
+
|
| 338 |
+
logger.info(f"Loaded {len(sequences)} sequences")
|
| 339 |
+
|
| 340 |
+
distiller = BPEIPADistiller(
|
| 341 |
+
checkpoint_path=args.checkpoint,
|
| 342 |
+
vocab_path=args.vocab,
|
| 343 |
+
ambiguity_path=args.ambiguity,
|
| 344 |
+
device=args.device,
|
| 345 |
+
threshold=args.threshold,
|
| 346 |
+
batch_size=args.batch_size,
|
| 347 |
+
)
|
| 348 |
+
|
| 349 |
+
expanded_sequences, stats = distiller.run_ipa(sequences=sequences, iterations=args.iterations)
|
| 350 |
+
|
| 351 |
+
output_path = Path(args.output)
|
| 352 |
+
output_path.parent.mkdir(parents=True, exist_ok=True)
|
| 353 |
+
|
| 354 |
+
with open(output_path, 'wb') as f:
|
| 355 |
+
pickle.dump(expanded_sequences, f)
|
| 356 |
+
|
| 357 |
+
logger.info(f"Saved {len(expanded_sequences)} expanded sequences to {output_path}")
|
| 358 |
+
|
| 359 |
+
stats_path = output_path.with_suffix('.stats.json')
|
| 360 |
+
with open(stats_path, 'w') as f:
|
| 361 |
+
json.dump(stats, f, indent=2)
|
| 362 |
+
|
| 363 |
+
print("\n" + "="*60)
|
| 364 |
+
print("BPE IPA SELF-DISTILLATION SUMMARY")
|
| 365 |
+
print("="*60)
|
| 366 |
+
print(f"Input sequences: {stats['initial']['total_sequences']}")
|
| 367 |
+
print(f"Initially ambiguous: {stats['initial']['ambiguous_sequences']} ({stats['initial']['ambiguous_percentage']:.1f}%)")
|
| 368 |
+
print(f"Ambiguous tokens: {stats['initial']['total_ambiguous_tokens']}")
|
| 369 |
+
print(f"Threshold: {stats['threshold']}")
|
| 370 |
+
print(f"Iterations run: {len(stats['iterations'])}")
|
| 371 |
+
print(f"Tokens resolved: {stats['final']['total_tokens_resolved']}")
|
| 372 |
+
print(f"Still ambiguous: {stats['final']['still_ambiguous']}")
|
| 373 |
+
print("="*60)
|
| 374 |
+
|
| 375 |
+
|
| 376 |
+
if __name__ == "__main__":
|
| 377 |
+
main()
|
releases/2026-10-02/iar_completion/runtime_snapshot/project/writing/glycangt_heldout_ipa_validation/cluster/heldout_ipa_eval.py
ADDED
|
@@ -0,0 +1,962 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""
|
| 3 |
+
Held-out IPA-style ambiguity completion evaluation for bertose_v5b_excluded.
|
| 4 |
+
|
| 5 |
+
This script turns fully specified held-out glycans into synthetic ambiguity-style
|
| 6 |
+
test cases by masking semantic WURCS-BPE spans, then evaluates whether the
|
| 7 |
+
leakage-proof Bertose checkpoint can recover the hidden truth.
|
| 8 |
+
"""
|
| 9 |
+
|
| 10 |
+
from __future__ import annotations
|
| 11 |
+
|
| 12 |
+
import argparse
|
| 13 |
+
import csv
|
| 14 |
+
import importlib.util
|
| 15 |
+
import json
|
| 16 |
+
import logging
|
| 17 |
+
import random
|
| 18 |
+
import sys
|
| 19 |
+
from collections import Counter, defaultdict
|
| 20 |
+
from dataclasses import dataclass
|
| 21 |
+
from pathlib import Path
|
| 22 |
+
from typing import Any, Dict, Iterable, List, Optional, Sequence
|
| 23 |
+
|
| 24 |
+
import torch
|
| 25 |
+
import torch.nn.functional as F
|
| 26 |
+
from tqdm import tqdm
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
LOGGER = logging.getLogger("heldout_ipa_eval")
|
| 30 |
+
|
| 31 |
+
THIS_FILE = Path(__file__).resolve()
|
| 32 |
+
ANALYSIS_ROOT = THIS_FILE.parent.parent
|
| 33 |
+
WRITING_ROOT = ANALYSIS_ROOT.parent
|
| 34 |
+
PROJECT_ROOT = WRITING_ROOT.parent
|
| 35 |
+
TOKENIZER_UTILS_ROOT = PROJECT_ROOT / "bert_training_v4" / "downstream_tasks" / "utils"
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
def first_existing_path(*candidates: Path) -> Path:
|
| 39 |
+
for candidate in candidates:
|
| 40 |
+
if candidate.exists():
|
| 41 |
+
return candidate
|
| 42 |
+
return candidates[0]
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
NATURE_CODE_ROOT = first_existing_path(
|
| 46 |
+
WRITING_ROOT / "cluster" / "nature_submission" / "code",
|
| 47 |
+
PROJECT_ROOT / "nature_submission" / "code",
|
| 48 |
+
)
|
| 49 |
+
DEFAULT_CHECKPOINT = first_existing_path(
|
| 50 |
+
WRITING_ROOT / "cluster" / "nature_submission" / "checkpoints" / "bertose_v5b_excluded.pt",
|
| 51 |
+
PROJECT_ROOT / "checkpoints_v5b_excluded" / "best_v5b_excluded_model.pt",
|
| 52 |
+
)
|
| 53 |
+
DEFAULT_VOCAB = first_existing_path(
|
| 54 |
+
WRITING_ROOT / "cluster" / "nature_submission" / "data" / "vocab" / "bpe_vocabulary_clean.json",
|
| 55 |
+
PROJECT_ROOT / "data" / "bpe_vocabulary_clean.json",
|
| 56 |
+
)
|
| 57 |
+
DEFAULT_AMBIGUITY = first_existing_path(
|
| 58 |
+
WRITING_ROOT / "cluster" / "nature_submission" / "data" / "vocab" / "bpe_ambiguity_tokens.json",
|
| 59 |
+
PROJECT_ROOT / "data" / "bpe_ambiguity_tokens.json",
|
| 60 |
+
)
|
| 61 |
+
IPA_DISTILLATION_MODULE = first_existing_path(
|
| 62 |
+
NATURE_CODE_ROOT / "training" / "ipa_bpe_distillation.py",
|
| 63 |
+
PROJECT_ROOT / "bertose" / "code" / "training" / "ipa_bpe_distillation.py",
|
| 64 |
+
PROJECT_ROOT / "bert_v5_bpe_topo" / "ipa_bpe_distillation.py",
|
| 65 |
+
)
|
| 66 |
+
WURCS_TOKENIZER_MODULE = first_existing_path(
|
| 67 |
+
TOKENIZER_UTILS_ROOT / "wurcs_bpe_tokenizer.py",
|
| 68 |
+
NATURE_CODE_ROOT / "tokenizer" / "wurcs_bpe_tokenizer.py",
|
| 69 |
+
PROJECT_ROOT / "bertose" / "code" / "tokenizer" / "wurcs_bpe_tokenizer.py",
|
| 70 |
+
)
|
| 71 |
+
|
| 72 |
+
|
| 73 |
+
def load_attr_from_module(module_path: Path, attr_name: str) -> Any:
|
| 74 |
+
spec = importlib.util.spec_from_file_location(f"heldout_dynamic_{module_path.stem}", module_path)
|
| 75 |
+
if spec is None or spec.loader is None:
|
| 76 |
+
raise ImportError(f"Could not load module spec from {module_path}")
|
| 77 |
+
module = importlib.util.module_from_spec(spec)
|
| 78 |
+
spec.loader.exec_module(module)
|
| 79 |
+
return getattr(module, attr_name)
|
| 80 |
+
|
| 81 |
+
|
| 82 |
+
BPEIPADistiller = load_attr_from_module(IPA_DISTILLATION_MODULE, "BPEIPADistiller")
|
| 83 |
+
WURCSBPETokenizer = load_attr_from_module(WURCS_TOKENIZER_MODULE, "WURCSBPETokenizer")
|
| 84 |
+
|
| 85 |
+
|
| 86 |
+
SPECIAL_TOKEN_NAMES = {
|
| 87 |
+
"[PAD]",
|
| 88 |
+
"[UNK]",
|
| 89 |
+
"[START]",
|
| 90 |
+
"[END]",
|
| 91 |
+
"[MASK]",
|
| 92 |
+
"[BRANCH_OPEN]",
|
| 93 |
+
"[BRANCH_CLOSE]",
|
| 94 |
+
"[LINK]",
|
| 95 |
+
"[MOD]",
|
| 96 |
+
"[RESIDUE_ERROR]",
|
| 97 |
+
}
|
| 98 |
+
|
| 99 |
+
|
| 100 |
+
@dataclass
|
| 101 |
+
class TokenSpan:
|
| 102 |
+
start: int
|
| 103 |
+
end: int
|
| 104 |
+
unit_type: str
|
| 105 |
+
unit_text: str
|
| 106 |
+
residue_id: int
|
| 107 |
+
token_texts: List[str]
|
| 108 |
+
|
| 109 |
+
@property
|
| 110 |
+
def positions(self) -> List[int]:
|
| 111 |
+
return list(range(self.start, self.end + 1))
|
| 112 |
+
|
| 113 |
+
|
| 114 |
+
@dataclass
|
| 115 |
+
class EvalCase:
|
| 116 |
+
case_id: str
|
| 117 |
+
glycan_index: int
|
| 118 |
+
wurcs: str
|
| 119 |
+
wurcs_length: int
|
| 120 |
+
source_membership: str
|
| 121 |
+
source_count: str
|
| 122 |
+
unit_type: str
|
| 123 |
+
unit_text: str
|
| 124 |
+
residue_id: int
|
| 125 |
+
mask_start: int
|
| 126 |
+
mask_end: int
|
| 127 |
+
positions: List[int]
|
| 128 |
+
truth_tokens: List[str]
|
| 129 |
+
truth_token_ids: List[int]
|
| 130 |
+
masked_token_ids: List[int]
|
| 131 |
+
attention_mask: List[int]
|
| 132 |
+
residue_ids: List[int]
|
| 133 |
+
branch_depths: List[int]
|
| 134 |
+
linkage_types: List[int]
|
| 135 |
+
mask_plan: str
|
| 136 |
+
|
| 137 |
+
|
| 138 |
+
class HeldoutIPAEvaluator:
|
| 139 |
+
def __init__(
|
| 140 |
+
self,
|
| 141 |
+
checkpoint: Path,
|
| 142 |
+
vocab: Path,
|
| 143 |
+
ambiguity: Path,
|
| 144 |
+
device: str,
|
| 145 |
+
threshold: float,
|
| 146 |
+
batch_size: int,
|
| 147 |
+
top_k: int,
|
| 148 |
+
max_length: int,
|
| 149 |
+
) -> None:
|
| 150 |
+
self.distiller = BPEIPADistiller(
|
| 151 |
+
checkpoint_path=str(checkpoint),
|
| 152 |
+
vocab_path=str(vocab),
|
| 153 |
+
ambiguity_path=str(ambiguity),
|
| 154 |
+
device=device,
|
| 155 |
+
threshold=threshold,
|
| 156 |
+
batch_size=batch_size,
|
| 157 |
+
)
|
| 158 |
+
self.tokenizer = WURCSBPETokenizer(str(vocab))
|
| 159 |
+
self.device = self.distiller.device
|
| 160 |
+
self.threshold = threshold
|
| 161 |
+
self.batch_size = batch_size
|
| 162 |
+
self.top_k = top_k
|
| 163 |
+
self.max_length = max_length
|
| 164 |
+
self.model = self.distiller.model
|
| 165 |
+
self.model.eval()
|
| 166 |
+
|
| 167 |
+
self.special_token_ids = {
|
| 168 |
+
self.distiller.token_to_id[name]
|
| 169 |
+
for name in SPECIAL_TOKEN_NAMES
|
| 170 |
+
if name in self.distiller.token_to_id
|
| 171 |
+
}
|
| 172 |
+
self.invalid_prediction_ids = set(self.special_token_ids) | set(self.distiller.ambiguous_token_ids)
|
| 173 |
+
|
| 174 |
+
LOGGER.info(
|
| 175 |
+
"Evaluator ready | device=%s threshold=%.2f batch_size=%d top_k=%d max_length=%d",
|
| 176 |
+
self.device,
|
| 177 |
+
self.threshold,
|
| 178 |
+
self.batch_size,
|
| 179 |
+
self.top_k,
|
| 180 |
+
self.max_length,
|
| 181 |
+
)
|
| 182 |
+
|
| 183 |
+
def build_cases(
|
| 184 |
+
self,
|
| 185 |
+
rows: Sequence[Dict[str, str]],
|
| 186 |
+
span_types: Sequence[str],
|
| 187 |
+
selection_mode: str,
|
| 188 |
+
max_cases_per_glycan: int,
|
| 189 |
+
seed: int,
|
| 190 |
+
mask_requirements: Optional[Dict[str, int]] = None,
|
| 191 |
+
) -> tuple[List[EvalCase], Dict[str, Any]]:
|
| 192 |
+
rng = random.Random(seed)
|
| 193 |
+
span_types = set(span_types)
|
| 194 |
+
mask_requirements = mask_requirements or {}
|
| 195 |
+
|
| 196 |
+
all_cases: List[EvalCase] = []
|
| 197 |
+
build_stats: Dict[str, Any] = {
|
| 198 |
+
"glycans_seen": len(rows),
|
| 199 |
+
"glycans_with_eligible_spans": 0,
|
| 200 |
+
"glycans_without_eligible_spans": 0,
|
| 201 |
+
"spans_seen_by_type": Counter(),
|
| 202 |
+
"spans_eligible_by_type": Counter(),
|
| 203 |
+
"spans_selected_by_type": Counter(),
|
| 204 |
+
"spans_skipped_truth_ambiguous": Counter(),
|
| 205 |
+
"spans_skipped_truncated": Counter(),
|
| 206 |
+
"glycans_skipped_mask_plan": 0,
|
| 207 |
+
}
|
| 208 |
+
|
| 209 |
+
for glycan_index, row in enumerate(tqdm(rows, desc="Building held-out cases")):
|
| 210 |
+
wurcs = row["wurcs"]
|
| 211 |
+
tokenized, spans, span_meta = self._tokenize_with_spans(wurcs)
|
| 212 |
+
for unit_type, count in span_meta["seen_by_type"].items():
|
| 213 |
+
build_stats["spans_seen_by_type"][unit_type] += count
|
| 214 |
+
for unit_type, count in span_meta["skipped_truncated_by_type"].items():
|
| 215 |
+
build_stats["spans_skipped_truncated"][unit_type] += count
|
| 216 |
+
|
| 217 |
+
eligible_spans: List[TokenSpan] = []
|
| 218 |
+
for span in spans:
|
| 219 |
+
if span.unit_type not in span_types:
|
| 220 |
+
continue
|
| 221 |
+
if any(token_id in self.invalid_prediction_ids for token_id in self._slice(tokenized["token_ids"], span)):
|
| 222 |
+
build_stats["spans_skipped_truth_ambiguous"][span.unit_type] += 1
|
| 223 |
+
continue
|
| 224 |
+
build_stats["spans_eligible_by_type"][span.unit_type] += 1
|
| 225 |
+
eligible_spans.append(span)
|
| 226 |
+
|
| 227 |
+
if not eligible_spans:
|
| 228 |
+
build_stats["glycans_without_eligible_spans"] += 1
|
| 229 |
+
continue
|
| 230 |
+
|
| 231 |
+
build_stats["glycans_with_eligible_spans"] += 1
|
| 232 |
+
eligible_spans_by_type: Dict[str, List[TokenSpan]] = defaultdict(list)
|
| 233 |
+
for span in eligible_spans:
|
| 234 |
+
eligible_spans_by_type[span.unit_type].append(span)
|
| 235 |
+
|
| 236 |
+
selected_spans = self._select_spans(
|
| 237 |
+
spans=eligible_spans,
|
| 238 |
+
spans_by_type=eligible_spans_by_type,
|
| 239 |
+
selection_mode=selection_mode,
|
| 240 |
+
max_cases_per_glycan=max_cases_per_glycan,
|
| 241 |
+
rng=rng,
|
| 242 |
+
mask_requirements=mask_requirements,
|
| 243 |
+
)
|
| 244 |
+
if mask_requirements and not selected_spans:
|
| 245 |
+
build_stats["glycans_skipped_mask_plan"] += 1
|
| 246 |
+
continue
|
| 247 |
+
|
| 248 |
+
for local_idx, span in enumerate(selected_spans):
|
| 249 |
+
build_stats["spans_selected_by_type"][span.unit_type] += 1
|
| 250 |
+
if mask_requirements:
|
| 251 |
+
selected_ordered = sorted(selected_spans, key=lambda item: (item.start, item.end))
|
| 252 |
+
truth_ids: List[int] = []
|
| 253 |
+
truth_tokens: List[str] = []
|
| 254 |
+
positions: List[int] = []
|
| 255 |
+
mask_start = min(span.start for span in selected_ordered)
|
| 256 |
+
mask_end = max(span.end for span in selected_ordered)
|
| 257 |
+
masked_token_ids = list(tokenized["token_ids"])
|
| 258 |
+
unit_text = " | ".join(f"{span.unit_type}:{span.unit_text}" for span in selected_ordered)
|
| 259 |
+
mask_plan = ",".join(f"{unit_type}:{count}" for unit_type, count in sorted(mask_requirements.items()))
|
| 260 |
+
case_id = f"g{glycan_index:04d}_plan_{mask_plan.replace(',', '_').replace(':', 'x')}"
|
| 261 |
+
for span in selected_ordered:
|
| 262 |
+
truth_ids.extend(self._slice(tokenized["token_ids"], span))
|
| 263 |
+
truth_tokens.extend(self._slice(tokenized["tokens"], span))
|
| 264 |
+
positions.extend(span.positions)
|
| 265 |
+
for pos in span.positions:
|
| 266 |
+
masked_token_ids[pos] = self.distiller.mask_id
|
| 267 |
+
all_cases.append(
|
| 268 |
+
EvalCase(
|
| 269 |
+
case_id=case_id,
|
| 270 |
+
glycan_index=glycan_index,
|
| 271 |
+
wurcs=wurcs,
|
| 272 |
+
wurcs_length=len(wurcs),
|
| 273 |
+
source_membership=row.get("source_membership", ""),
|
| 274 |
+
source_count=row.get("source_count", ""),
|
| 275 |
+
unit_type=mask_plan,
|
| 276 |
+
unit_text=unit_text,
|
| 277 |
+
residue_id=selected_ordered[0].residue_id,
|
| 278 |
+
mask_start=mask_start,
|
| 279 |
+
mask_end=mask_end,
|
| 280 |
+
positions=positions,
|
| 281 |
+
truth_tokens=truth_tokens,
|
| 282 |
+
truth_token_ids=truth_ids,
|
| 283 |
+
masked_token_ids=masked_token_ids,
|
| 284 |
+
attention_mask=list(tokenized["attention_mask"]),
|
| 285 |
+
residue_ids=list(tokenized["residue_ids"]),
|
| 286 |
+
branch_depths=list(tokenized["branch_depths"]),
|
| 287 |
+
linkage_types=list(tokenized["linkage_types"]),
|
| 288 |
+
mask_plan=mask_plan,
|
| 289 |
+
)
|
| 290 |
+
)
|
| 291 |
+
else:
|
| 292 |
+
for local_idx, span in enumerate(selected_spans):
|
| 293 |
+
truth_ids = self._slice(tokenized["token_ids"], span)
|
| 294 |
+
truth_tokens = self._slice(tokenized["tokens"], span)
|
| 295 |
+
masked_token_ids = list(tokenized["token_ids"])
|
| 296 |
+
for pos in span.positions:
|
| 297 |
+
masked_token_ids[pos] = self.distiller.mask_id
|
| 298 |
+
|
| 299 |
+
all_cases.append(
|
| 300 |
+
EvalCase(
|
| 301 |
+
case_id=f"g{glycan_index:04d}_s{local_idx:02d}_{span.unit_type}_{span.start}_{span.end}",
|
| 302 |
+
glycan_index=glycan_index,
|
| 303 |
+
wurcs=wurcs,
|
| 304 |
+
wurcs_length=len(wurcs),
|
| 305 |
+
source_membership=row.get("source_membership", ""),
|
| 306 |
+
source_count=row.get("source_count", ""),
|
| 307 |
+
unit_type=span.unit_type,
|
| 308 |
+
unit_text=span.unit_text,
|
| 309 |
+
residue_id=span.residue_id,
|
| 310 |
+
mask_start=span.start,
|
| 311 |
+
mask_end=span.end,
|
| 312 |
+
positions=span.positions,
|
| 313 |
+
truth_tokens=truth_tokens,
|
| 314 |
+
truth_token_ids=truth_ids,
|
| 315 |
+
masked_token_ids=masked_token_ids,
|
| 316 |
+
attention_mask=list(tokenized["attention_mask"]),
|
| 317 |
+
residue_ids=list(tokenized["residue_ids"]),
|
| 318 |
+
branch_depths=list(tokenized["branch_depths"]),
|
| 319 |
+
linkage_types=list(tokenized["linkage_types"]),
|
| 320 |
+
mask_plan=f"{span.unit_type}:1",
|
| 321 |
+
)
|
| 322 |
+
)
|
| 323 |
+
|
| 324 |
+
build_stats["num_cases"] = len(all_cases)
|
| 325 |
+
build_stats["num_masked_positions"] = sum(len(case.positions) for case in all_cases)
|
| 326 |
+
build_stats["avg_masked_positions_per_case"] = (
|
| 327 |
+
build_stats["num_masked_positions"] / len(all_cases) if all_cases else 0.0
|
| 328 |
+
)
|
| 329 |
+
build_stats["span_types"] = sorted(span_types)
|
| 330 |
+
return all_cases, self._json_ready(build_stats)
|
| 331 |
+
|
| 332 |
+
def evaluate_cases(self, cases: Sequence[EvalCase], iterations: int) -> tuple[List[Dict[str, Any]], Dict[str, Any]]:
|
| 333 |
+
if not cases:
|
| 334 |
+
return [], {}
|
| 335 |
+
|
| 336 |
+
results: List[Dict[str, Any]] = []
|
| 337 |
+
num_batches = (len(cases) + self.batch_size - 1) // self.batch_size
|
| 338 |
+
|
| 339 |
+
for batch_idx in tqdm(range(num_batches), desc="Evaluating held-out cases"):
|
| 340 |
+
start = batch_idx * self.batch_size
|
| 341 |
+
end = min(start + self.batch_size, len(cases))
|
| 342 |
+
batch_cases = list(cases[start:end])
|
| 343 |
+
batch_results = self._evaluate_batch(batch_cases=batch_cases, iterations=iterations)
|
| 344 |
+
results.extend(batch_results)
|
| 345 |
+
|
| 346 |
+
summary = self._summarize_results(results=results, iterations=iterations)
|
| 347 |
+
return results, summary
|
| 348 |
+
|
| 349 |
+
def _evaluate_batch(self, batch_cases: Sequence[EvalCase], iterations: int) -> List[Dict[str, Any]]:
|
| 350 |
+
current_token_ids = [list(case.masked_token_ids) for case in batch_cases]
|
| 351 |
+
unresolved_positions = [set(case.positions) for case in batch_cases]
|
| 352 |
+
initial_position_details: List[List[Dict[str, Any]]] = [[] for _ in batch_cases]
|
| 353 |
+
accepted_updates_per_case: List[List[Dict[str, Any]]] = [[] for _ in batch_cases]
|
| 354 |
+
|
| 355 |
+
for iteration_idx in range(iterations):
|
| 356 |
+
logits = self._forward_logits(batch_cases=batch_cases, current_token_ids=current_token_ids)
|
| 357 |
+
|
| 358 |
+
progress_this_round = 0
|
| 359 |
+
for case_idx, case in enumerate(batch_cases):
|
| 360 |
+
if not unresolved_positions[case_idx]:
|
| 361 |
+
continue
|
| 362 |
+
|
| 363 |
+
iteration_updates: List[Dict[str, Any]] = []
|
| 364 |
+
for local_pos_idx, pos in enumerate(case.positions):
|
| 365 |
+
position_logits = logits[case_idx, pos]
|
| 366 |
+
probs = F.softmax(position_logits, dim=-1)
|
| 367 |
+
top_probs, top_ids = torch.topk(probs, k=self.top_k)
|
| 368 |
+
|
| 369 |
+
top_tokens = [self.distiller.id_to_token[int(token_id)] for token_id in top_ids.tolist()]
|
| 370 |
+
detail = {
|
| 371 |
+
"position": pos,
|
| 372 |
+
"truth_token": case.truth_tokens[local_pos_idx],
|
| 373 |
+
"truth_token_id": case.truth_token_ids[local_pos_idx],
|
| 374 |
+
"top_ids": [int(token_id) for token_id in top_ids.tolist()],
|
| 375 |
+
"top_tokens": top_tokens,
|
| 376 |
+
"top_probs": [float(prob) for prob in top_probs.tolist()],
|
| 377 |
+
"top1_id": int(top_ids[0].item()),
|
| 378 |
+
"top1_token": top_tokens[0],
|
| 379 |
+
"top1_prob": float(top_probs[0].item()),
|
| 380 |
+
"top1_correct": int(top_ids[0].item()) == case.truth_token_ids[local_pos_idx],
|
| 381 |
+
"top5_contains_truth": case.truth_token_ids[local_pos_idx] in {
|
| 382 |
+
int(token_id) for token_id in top_ids.tolist()
|
| 383 |
+
},
|
| 384 |
+
}
|
| 385 |
+
|
| 386 |
+
if iteration_idx == 0:
|
| 387 |
+
initial_position_details[case_idx].append(detail)
|
| 388 |
+
|
| 389 |
+
if pos not in unresolved_positions[case_idx]:
|
| 390 |
+
continue
|
| 391 |
+
|
| 392 |
+
pred_id = detail["top1_id"]
|
| 393 |
+
pred_prob = detail["top1_prob"]
|
| 394 |
+
if pred_prob < self.threshold:
|
| 395 |
+
continue
|
| 396 |
+
if pred_id in self.invalid_prediction_ids:
|
| 397 |
+
continue
|
| 398 |
+
|
| 399 |
+
current_token_ids[case_idx][pos] = pred_id
|
| 400 |
+
unresolved_positions[case_idx].remove(pos)
|
| 401 |
+
progress_this_round += 1
|
| 402 |
+
iteration_updates.append(
|
| 403 |
+
{
|
| 404 |
+
"iteration": iteration_idx + 1,
|
| 405 |
+
"position": pos,
|
| 406 |
+
"predicted_id": pred_id,
|
| 407 |
+
"predicted_token": detail["top1_token"],
|
| 408 |
+
"confidence": pred_prob,
|
| 409 |
+
"correct": pred_id == detail["truth_token_id"],
|
| 410 |
+
}
|
| 411 |
+
)
|
| 412 |
+
|
| 413 |
+
if iteration_updates:
|
| 414 |
+
accepted_updates_per_case[case_idx].extend(iteration_updates)
|
| 415 |
+
|
| 416 |
+
if progress_this_round == 0:
|
| 417 |
+
LOGGER.info("Stopping early after iteration %d because no new positions were accepted", iteration_idx + 1)
|
| 418 |
+
break
|
| 419 |
+
|
| 420 |
+
batch_results: List[Dict[str, Any]] = []
|
| 421 |
+
for case_idx, case in enumerate(batch_cases):
|
| 422 |
+
final_token_ids = [current_token_ids[case_idx][pos] for pos in case.positions]
|
| 423 |
+
final_tokens = [self.distiller.id_to_token[token_id] for token_id in final_token_ids]
|
| 424 |
+
final_correct_flags = [
|
| 425 |
+
final_token_ids[pos_idx] == case.truth_token_ids[pos_idx]
|
| 426 |
+
for pos_idx in range(len(case.positions))
|
| 427 |
+
]
|
| 428 |
+
resolved_flags = [
|
| 429 |
+
case.positions[pos_idx] not in unresolved_positions[case_idx]
|
| 430 |
+
for pos_idx in range(len(case.positions))
|
| 431 |
+
]
|
| 432 |
+
initial_details = initial_position_details[case_idx]
|
| 433 |
+
|
| 434 |
+
batch_results.append(
|
| 435 |
+
{
|
| 436 |
+
"case_id": case.case_id,
|
| 437 |
+
"glycan_index": case.glycan_index,
|
| 438 |
+
"wurcs": case.wurcs,
|
| 439 |
+
"wurcs_length": case.wurcs_length,
|
| 440 |
+
"source_membership": case.source_membership,
|
| 441 |
+
"source_count": case.source_count,
|
| 442 |
+
"unit_type": case.unit_type,
|
| 443 |
+
"mask_plan": case.mask_plan,
|
| 444 |
+
"unit_text": case.unit_text,
|
| 445 |
+
"residue_id": case.residue_id,
|
| 446 |
+
"positions": case.positions,
|
| 447 |
+
"mask_start": case.mask_start,
|
| 448 |
+
"mask_end": case.mask_end,
|
| 449 |
+
"num_masked_positions": len(case.positions),
|
| 450 |
+
"truth_tokens": case.truth_tokens,
|
| 451 |
+
"truth_token_ids": case.truth_token_ids,
|
| 452 |
+
"initial_position_details": initial_details,
|
| 453 |
+
"accepted_updates": accepted_updates_per_case[case_idx],
|
| 454 |
+
"final_tokens": final_tokens,
|
| 455 |
+
"final_token_ids": final_token_ids,
|
| 456 |
+
"resolved_flags": resolved_flags,
|
| 457 |
+
"final_correct_flags": final_correct_flags,
|
| 458 |
+
"initial_top1_correct_count": sum(1 for item in initial_details if item["top1_correct"]),
|
| 459 |
+
"initial_top5_correct_count": sum(1 for item in initial_details if item["top5_contains_truth"]),
|
| 460 |
+
"resolved_count": sum(1 for flag in resolved_flags if flag),
|
| 461 |
+
"final_correct_count": sum(1 for flag in final_correct_flags if flag),
|
| 462 |
+
"initial_span_exact_top1": all(item["top1_correct"] for item in initial_details) if initial_details else False,
|
| 463 |
+
"initial_span_exact_top5": all(item["top5_contains_truth"] for item in initial_details) if initial_details else False,
|
| 464 |
+
"iterative_span_exact": all(final_correct_flags) if final_correct_flags else False,
|
| 465 |
+
"iterations_used": max(
|
| 466 |
+
(update["iteration"] for update in accepted_updates_per_case[case_idx]),
|
| 467 |
+
default=0,
|
| 468 |
+
),
|
| 469 |
+
}
|
| 470 |
+
)
|
| 471 |
+
|
| 472 |
+
return batch_results
|
| 473 |
+
|
| 474 |
+
def _forward_logits(
|
| 475 |
+
self,
|
| 476 |
+
batch_cases: Sequence[EvalCase],
|
| 477 |
+
current_token_ids: Sequence[List[int]],
|
| 478 |
+
) -> torch.Tensor:
|
| 479 |
+
batch_size = len(batch_cases)
|
| 480 |
+
|
| 481 |
+
seq_token_ids = torch.tensor(current_token_ids, dtype=torch.long, device=self.device)
|
| 482 |
+
seq_attention_mask = torch.tensor(
|
| 483 |
+
[case.attention_mask for case in batch_cases], dtype=torch.long, device=self.device
|
| 484 |
+
)
|
| 485 |
+
seq_residue_ids = torch.tensor(
|
| 486 |
+
[case.residue_ids for case in batch_cases], dtype=torch.long, device=self.device
|
| 487 |
+
)
|
| 488 |
+
seq_branch_depths = torch.tensor(
|
| 489 |
+
[case.branch_depths for case in batch_cases], dtype=torch.long, device=self.device
|
| 490 |
+
)
|
| 491 |
+
seq_linkage_types = torch.tensor(
|
| 492 |
+
[case.linkage_types for case in batch_cases], dtype=torch.long, device=self.device
|
| 493 |
+
)
|
| 494 |
+
|
| 495 |
+
ms_len = 150
|
| 496 |
+
struct_len = 200
|
| 497 |
+
outputs = self.model(
|
| 498 |
+
seq_token_ids=seq_token_ids,
|
| 499 |
+
seq_attention_mask=seq_attention_mask,
|
| 500 |
+
seq_residue_ids=seq_residue_ids,
|
| 501 |
+
seq_branch_depths=seq_branch_depths,
|
| 502 |
+
seq_linkage_types=seq_linkage_types,
|
| 503 |
+
ms_token_ids=torch.zeros(batch_size, ms_len, dtype=torch.long, device=self.device),
|
| 504 |
+
ms_attention_mask=torch.zeros(batch_size, ms_len, dtype=torch.long, device=self.device),
|
| 505 |
+
has_ms=torch.zeros(batch_size, dtype=torch.bool, device=self.device),
|
| 506 |
+
struct_token_ids=torch.zeros(batch_size, struct_len, dtype=torch.long, device=self.device),
|
| 507 |
+
struct_attention_mask=torch.zeros(batch_size, struct_len, dtype=torch.long, device=self.device),
|
| 508 |
+
struct_residue_ids=torch.full((batch_size, struct_len), -1, dtype=torch.long, device=self.device),
|
| 509 |
+
has_3d=torch.zeros(batch_size, dtype=torch.bool, device=self.device),
|
| 510 |
+
return_dict=True,
|
| 511 |
+
)
|
| 512 |
+
return outputs["seq_logits"]
|
| 513 |
+
|
| 514 |
+
def _tokenize_with_spans(self, wurcs: str) -> tuple[Dict[str, Any], List[TokenSpan], Dict[str, Counter]]:
|
| 515 |
+
tokenized = self.tokenizer.tokenize(wurcs, max_length=self.max_length)
|
| 516 |
+
unpadded_tokens = tokenized["tokens"][: tokenized["length"]]
|
| 517 |
+
units = self.tokenizer.pre_tokenizer.pre_tokenize(wurcs)
|
| 518 |
+
|
| 519 |
+
spans: List[TokenSpan] = []
|
| 520 |
+
raw_cursor = 0
|
| 521 |
+
span_meta = {
|
| 522 |
+
"seen_by_type": Counter(),
|
| 523 |
+
"skipped_truncated_by_type": Counter(),
|
| 524 |
+
}
|
| 525 |
+
|
| 526 |
+
for unit in units:
|
| 527 |
+
unit_tokens = [unit["text"]] if unit["type"] == "special" else self.tokenizer.apply_bpe(unit["text"])
|
| 528 |
+
span_start = raw_cursor
|
| 529 |
+
span_end = raw_cursor + len(unit_tokens) - 1
|
| 530 |
+
raw_cursor += len(unit_tokens)
|
| 531 |
+
|
| 532 |
+
if unit["type"] != "special":
|
| 533 |
+
span_meta["seen_by_type"][unit["type"]] += 1
|
| 534 |
+
|
| 535 |
+
if unit["type"] == "special":
|
| 536 |
+
continue
|
| 537 |
+
if span_end >= len(unpadded_tokens):
|
| 538 |
+
span_meta["skipped_truncated_by_type"][unit["type"]] += 1
|
| 539 |
+
continue
|
| 540 |
+
if unpadded_tokens[span_start : span_end + 1] != unit_tokens:
|
| 541 |
+
span_meta["skipped_truncated_by_type"][unit["type"]] += 1
|
| 542 |
+
continue
|
| 543 |
+
|
| 544 |
+
spans.append(
|
| 545 |
+
TokenSpan(
|
| 546 |
+
start=span_start,
|
| 547 |
+
end=span_end,
|
| 548 |
+
unit_type=unit["type"],
|
| 549 |
+
unit_text=unit["text"],
|
| 550 |
+
residue_id=unit["residue_id"],
|
| 551 |
+
token_texts=unit_tokens,
|
| 552 |
+
)
|
| 553 |
+
)
|
| 554 |
+
|
| 555 |
+
return tokenized, spans, span_meta
|
| 556 |
+
|
| 557 |
+
@staticmethod
|
| 558 |
+
def _slice(values: Sequence[Any], span: TokenSpan) -> List[Any]:
|
| 559 |
+
return list(values[span.start : span.end + 1])
|
| 560 |
+
|
| 561 |
+
@staticmethod
|
| 562 |
+
def _select_spans(
|
| 563 |
+
spans: Sequence[TokenSpan],
|
| 564 |
+
spans_by_type: Dict[str, List[TokenSpan]],
|
| 565 |
+
selection_mode: str,
|
| 566 |
+
max_cases_per_glycan: int,
|
| 567 |
+
rng: random.Random,
|
| 568 |
+
mask_requirements: Optional[Dict[str, int]] = None,
|
| 569 |
+
) -> List[TokenSpan]:
|
| 570 |
+
ordered = sorted(spans, key=lambda item: (item.start, item.end))
|
| 571 |
+
mask_requirements = mask_requirements or {}
|
| 572 |
+
if mask_requirements:
|
| 573 |
+
selected: List[TokenSpan] = []
|
| 574 |
+
for unit_type, count in sorted(mask_requirements.items()):
|
| 575 |
+
unit_spans = sorted(spans_by_type.get(unit_type, []), key=lambda item: (item.start, item.end))
|
| 576 |
+
if len(unit_spans) < count:
|
| 577 |
+
return []
|
| 578 |
+
if selection_mode == "all":
|
| 579 |
+
chosen = unit_spans[:count]
|
| 580 |
+
elif selection_mode == "first":
|
| 581 |
+
chosen = unit_spans[:count]
|
| 582 |
+
elif selection_mode == "sample":
|
| 583 |
+
chosen = sorted(rng.sample(unit_spans, count), key=lambda item: (item.start, item.end))
|
| 584 |
+
else:
|
| 585 |
+
raise ValueError(f"Unsupported selection mode: {selection_mode}")
|
| 586 |
+
selected.extend(chosen)
|
| 587 |
+
return sorted(selected, key=lambda item: (item.start, item.end))
|
| 588 |
+
if selection_mode == "all":
|
| 589 |
+
return ordered
|
| 590 |
+
if selection_mode == "first":
|
| 591 |
+
return ordered[:max_cases_per_glycan]
|
| 592 |
+
if selection_mode == "sample":
|
| 593 |
+
k = min(max_cases_per_glycan, len(ordered))
|
| 594 |
+
return sorted(rng.sample(ordered, k), key=lambda item: (item.start, item.end))
|
| 595 |
+
raise ValueError(f"Unsupported selection mode: {selection_mode}")
|
| 596 |
+
|
| 597 |
+
@staticmethod
|
| 598 |
+
def _json_ready(obj: Any) -> Any:
|
| 599 |
+
if isinstance(obj, Counter):
|
| 600 |
+
return dict(obj)
|
| 601 |
+
if isinstance(obj, defaultdict):
|
| 602 |
+
return {key: HeldoutIPAEvaluator._json_ready(value) for key, value in obj.items()}
|
| 603 |
+
if isinstance(obj, dict):
|
| 604 |
+
return {key: HeldoutIPAEvaluator._json_ready(value) for key, value in obj.items()}
|
| 605 |
+
if isinstance(obj, list):
|
| 606 |
+
return [HeldoutIPAEvaluator._json_ready(value) for value in obj]
|
| 607 |
+
return obj
|
| 608 |
+
|
| 609 |
+
def _summarize_results(self, results: Sequence[Dict[str, Any]], iterations: int) -> Dict[str, Any]:
|
| 610 |
+
total_cases = len(results)
|
| 611 |
+
total_positions = sum(result["num_masked_positions"] for result in results)
|
| 612 |
+
if total_cases == 0 or total_positions == 0:
|
| 613 |
+
return {}
|
| 614 |
+
|
| 615 |
+
overall = self._aggregate_slice(results)
|
| 616 |
+
by_unit_type = {
|
| 617 |
+
unit_type: self._aggregate_slice([result for result in results if result["unit_type"] == unit_type])
|
| 618 |
+
for unit_type in sorted({result["unit_type"] for result in results})
|
| 619 |
+
}
|
| 620 |
+
|
| 621 |
+
return {
|
| 622 |
+
"num_cases": total_cases,
|
| 623 |
+
"num_masked_positions": total_positions,
|
| 624 |
+
"iterations_requested": iterations,
|
| 625 |
+
"threshold": self.threshold,
|
| 626 |
+
"top_k": self.top_k,
|
| 627 |
+
"overall": overall,
|
| 628 |
+
"by_unit_type": by_unit_type,
|
| 629 |
+
}
|
| 630 |
+
|
| 631 |
+
@staticmethod
|
| 632 |
+
def _aggregate_slice(results: Sequence[Dict[str, Any]]) -> Dict[str, Any]:
|
| 633 |
+
total_cases = len(results)
|
| 634 |
+
total_positions = sum(result["num_masked_positions"] for result in results)
|
| 635 |
+
initial_top1_correct = sum(result["initial_top1_correct_count"] for result in results)
|
| 636 |
+
initial_top5_correct = sum(result["initial_top5_correct_count"] for result in results)
|
| 637 |
+
resolved_count = sum(result["resolved_count"] for result in results)
|
| 638 |
+
final_correct_count = sum(result["final_correct_count"] for result in results)
|
| 639 |
+
|
| 640 |
+
return {
|
| 641 |
+
"num_cases": total_cases,
|
| 642 |
+
"num_masked_positions": total_positions,
|
| 643 |
+
"avg_masked_positions_per_case": total_positions / total_cases if total_cases else 0.0,
|
| 644 |
+
"initial_top1_token_accuracy": initial_top1_correct / total_positions if total_positions else 0.0,
|
| 645 |
+
"initial_top5_token_accuracy": initial_top5_correct / total_positions if total_positions else 0.0,
|
| 646 |
+
"initial_exact_span_accuracy_top1": (
|
| 647 |
+
sum(1 for result in results if result["initial_span_exact_top1"]) / total_cases if total_cases else 0.0
|
| 648 |
+
),
|
| 649 |
+
"initial_exact_span_accuracy_top5": (
|
| 650 |
+
sum(1 for result in results if result["initial_span_exact_top5"]) / total_cases if total_cases else 0.0
|
| 651 |
+
),
|
| 652 |
+
"iterative_resolved_fraction": resolved_count / total_positions if total_positions else 0.0,
|
| 653 |
+
"iterative_accuracy_among_resolved": final_correct_count / resolved_count if resolved_count else 0.0,
|
| 654 |
+
"iterative_final_token_accuracy": final_correct_count / total_positions if total_positions else 0.0,
|
| 655 |
+
"iterative_exact_span_accuracy": (
|
| 656 |
+
sum(1 for result in results if result["iterative_span_exact"]) / total_cases if total_cases else 0.0
|
| 657 |
+
),
|
| 658 |
+
"avg_iterations_used_per_case": (
|
| 659 |
+
sum(result["iterations_used"] for result in results) / total_cases if total_cases else 0.0
|
| 660 |
+
),
|
| 661 |
+
}
|
| 662 |
+
|
| 663 |
+
|
| 664 |
+
def parse_args() -> argparse.Namespace:
|
| 665 |
+
parser = argparse.ArgumentParser(description="Held-out IPA-style evaluation for bertose_v5b_excluded")
|
| 666 |
+
parser.add_argument(
|
| 667 |
+
"--input-csv",
|
| 668 |
+
type=Path,
|
| 669 |
+
default=ANALYSIS_ROOT / "data" / "benchmark_exclusion_1392_unseen_to_bertose_v5b_excluded.csv",
|
| 670 |
+
)
|
| 671 |
+
parser.add_argument(
|
| 672 |
+
"--checkpoint",
|
| 673 |
+
type=Path,
|
| 674 |
+
default=DEFAULT_CHECKPOINT,
|
| 675 |
+
)
|
| 676 |
+
parser.add_argument(
|
| 677 |
+
"--vocab",
|
| 678 |
+
type=Path,
|
| 679 |
+
default=DEFAULT_VOCAB,
|
| 680 |
+
)
|
| 681 |
+
parser.add_argument(
|
| 682 |
+
"--ambiguity",
|
| 683 |
+
type=Path,
|
| 684 |
+
default=DEFAULT_AMBIGUITY,
|
| 685 |
+
)
|
| 686 |
+
parser.add_argument("--output-dir", type=Path, default=ANALYSIS_ROOT / "outputs")
|
| 687 |
+
parser.add_argument("--run-name", type=str, default="benchmark1392_pilot")
|
| 688 |
+
parser.add_argument("--device", type=str, default="cuda")
|
| 689 |
+
parser.add_argument("--batch-size", type=int, default=32)
|
| 690 |
+
parser.add_argument("--iterations", type=int, default=3)
|
| 691 |
+
parser.add_argument("--threshold", type=float, default=0.80)
|
| 692 |
+
parser.add_argument("--top-k", type=int, default=5)
|
| 693 |
+
parser.add_argument("--max-length", type=int, default=256)
|
| 694 |
+
parser.add_argument("--limit", type=int, default=None)
|
| 695 |
+
parser.add_argument("--seed", type=int, default=42)
|
| 696 |
+
parser.add_argument("--shuffle", action="store_true")
|
| 697 |
+
parser.add_argument("--selection-mode", choices=["sample", "first", "all"], default="sample")
|
| 698 |
+
parser.add_argument("--max-cases-per-glycan", type=int, default=1)
|
| 699 |
+
parser.add_argument("--span-types", type=str, default="residue,linkage")
|
| 700 |
+
parser.add_argument("--mask-plan", type=str, default="")
|
| 701 |
+
parser.add_argument("--log-level", type=str, default="INFO")
|
| 702 |
+
return parser.parse_args()
|
| 703 |
+
|
| 704 |
+
|
| 705 |
+
def parse_mask_plan(mask_plan: str) -> Dict[str, int]:
|
| 706 |
+
mask_plan = mask_plan.strip()
|
| 707 |
+
if not mask_plan:
|
| 708 |
+
return {}
|
| 709 |
+
requirements: Dict[str, int] = {}
|
| 710 |
+
for item in mask_plan.split(","):
|
| 711 |
+
part = item.strip()
|
| 712 |
+
if not part:
|
| 713 |
+
continue
|
| 714 |
+
if ":" not in part:
|
| 715 |
+
raise ValueError(f"Invalid mask-plan item: {part}")
|
| 716 |
+
unit_type, count_str = part.split(":", 1)
|
| 717 |
+
unit_type = unit_type.strip()
|
| 718 |
+
count = int(count_str.strip())
|
| 719 |
+
if count <= 0:
|
| 720 |
+
raise ValueError(f"Mask-plan counts must be positive: {part}")
|
| 721 |
+
requirements[unit_type] = count
|
| 722 |
+
return requirements
|
| 723 |
+
|
| 724 |
+
|
| 725 |
+
def setup_logging(level: str) -> None:
|
| 726 |
+
logging.basicConfig(
|
| 727 |
+
level=getattr(logging, level.upper(), logging.INFO),
|
| 728 |
+
format="%(asctime)s - %(levelname)s - %(message)s",
|
| 729 |
+
)
|
| 730 |
+
|
| 731 |
+
|
| 732 |
+
def load_rows(input_csv: Path, limit: Optional[int], shuffle: bool, seed: int) -> List[Dict[str, str]]:
|
| 733 |
+
with input_csv.open() as handle:
|
| 734 |
+
rows = list(csv.DictReader(handle))
|
| 735 |
+
|
| 736 |
+
if "in_reconstructed_leakage_proof_pretrain" in rows[0]:
|
| 737 |
+
not_unseen = [
|
| 738 |
+
row["wurcs"]
|
| 739 |
+
for row in rows
|
| 740 |
+
if row["in_reconstructed_leakage_proof_pretrain"].strip().lower() != "false"
|
| 741 |
+
]
|
| 742 |
+
if not_unseen:
|
| 743 |
+
raise ValueError(
|
| 744 |
+
f"Input CSV contains {len(not_unseen)} glycans that are not marked unseen to the leakage-proof model"
|
| 745 |
+
)
|
| 746 |
+
|
| 747 |
+
if shuffle:
|
| 748 |
+
rng = random.Random(seed)
|
| 749 |
+
rng.shuffle(rows)
|
| 750 |
+
|
| 751 |
+
if limit is not None:
|
| 752 |
+
rows = rows[:limit]
|
| 753 |
+
|
| 754 |
+
return rows
|
| 755 |
+
|
| 756 |
+
|
| 757 |
+
def write_json(path: Path, payload: Dict[str, Any]) -> None:
|
| 758 |
+
path.parent.mkdir(parents=True, exist_ok=True)
|
| 759 |
+
path.write_text(json.dumps(payload, indent=2))
|
| 760 |
+
|
| 761 |
+
|
| 762 |
+
def write_jsonl(path: Path, rows: Iterable[Dict[str, Any]]) -> None:
|
| 763 |
+
path.parent.mkdir(parents=True, exist_ok=True)
|
| 764 |
+
with path.open("w") as handle:
|
| 765 |
+
for row in rows:
|
| 766 |
+
handle.write(json.dumps(row) + "\n")
|
| 767 |
+
|
| 768 |
+
|
| 769 |
+
def write_case_csv(path: Path, rows: Sequence[Dict[str, Any]]) -> None:
|
| 770 |
+
flat_rows = []
|
| 771 |
+
for row in rows:
|
| 772 |
+
flat_rows.append(
|
| 773 |
+
{
|
| 774 |
+
"case_id": row["case_id"],
|
| 775 |
+
"glycan_index": row["glycan_index"],
|
| 776 |
+
"unit_type": row["unit_type"],
|
| 777 |
+
"mask_plan": row.get("mask_plan", row["unit_type"]),
|
| 778 |
+
"unit_text": row["unit_text"],
|
| 779 |
+
"mask_start": row["mask_start"],
|
| 780 |
+
"mask_end": row["mask_end"],
|
| 781 |
+
"num_masked_positions": row["num_masked_positions"],
|
| 782 |
+
"initial_top1_correct_count": row["initial_top1_correct_count"],
|
| 783 |
+
"initial_top5_correct_count": row["initial_top5_correct_count"],
|
| 784 |
+
"resolved_count": row["resolved_count"],
|
| 785 |
+
"final_correct_count": row["final_correct_count"],
|
| 786 |
+
"initial_span_exact_top1": row["initial_span_exact_top1"],
|
| 787 |
+
"initial_span_exact_top5": row["initial_span_exact_top5"],
|
| 788 |
+
"iterative_span_exact": row["iterative_span_exact"],
|
| 789 |
+
"iterations_used": row["iterations_used"],
|
| 790 |
+
"truth_tokens": "|".join(row["truth_tokens"]),
|
| 791 |
+
"final_tokens": "|".join(row["final_tokens"]),
|
| 792 |
+
"wurcs": row["wurcs"],
|
| 793 |
+
}
|
| 794 |
+
)
|
| 795 |
+
|
| 796 |
+
fieldnames = list(flat_rows[0].keys()) if flat_rows else [
|
| 797 |
+
"case_id",
|
| 798 |
+
"glycan_index",
|
| 799 |
+
"unit_type",
|
| 800 |
+
"mask_plan",
|
| 801 |
+
"unit_text",
|
| 802 |
+
"mask_start",
|
| 803 |
+
"mask_end",
|
| 804 |
+
"num_masked_positions",
|
| 805 |
+
"initial_top1_correct_count",
|
| 806 |
+
"initial_top5_correct_count",
|
| 807 |
+
"resolved_count",
|
| 808 |
+
"final_correct_count",
|
| 809 |
+
"initial_span_exact_top1",
|
| 810 |
+
"initial_span_exact_top5",
|
| 811 |
+
"iterative_span_exact",
|
| 812 |
+
"iterations_used",
|
| 813 |
+
"truth_tokens",
|
| 814 |
+
"final_tokens",
|
| 815 |
+
"wurcs",
|
| 816 |
+
]
|
| 817 |
+
|
| 818 |
+
with path.open("w", newline="") as handle:
|
| 819 |
+
writer = csv.DictWriter(handle, fieldnames=fieldnames)
|
| 820 |
+
writer.writeheader()
|
| 821 |
+
writer.writerows(flat_rows)
|
| 822 |
+
|
| 823 |
+
|
| 824 |
+
def write_summary_markdown(
|
| 825 |
+
path: Path,
|
| 826 |
+
*,
|
| 827 |
+
args: argparse.Namespace,
|
| 828 |
+
input_rows: Sequence[Dict[str, str]],
|
| 829 |
+
build_stats: Dict[str, Any],
|
| 830 |
+
summary: Dict[str, Any],
|
| 831 |
+
) -> None:
|
| 832 |
+
overall = summary.get("overall", {})
|
| 833 |
+
by_unit_type = summary.get("by_unit_type", {})
|
| 834 |
+
|
| 835 |
+
lines = [
|
| 836 |
+
"# Held-out IPA Evaluation Summary",
|
| 837 |
+
"",
|
| 838 |
+
"## Run",
|
| 839 |
+
"",
|
| 840 |
+
f"- run_name: `{args.run_name}`",
|
| 841 |
+
f"- input_csv: `{args.input_csv}`",
|
| 842 |
+
f"- checkpoint: `{args.checkpoint}`",
|
| 843 |
+
f"- vocab: `{args.vocab}`",
|
| 844 |
+
f"- ambiguity: `{args.ambiguity}`",
|
| 845 |
+
f"- device: `{args.device}`",
|
| 846 |
+
f"- threshold: `{args.threshold}`",
|
| 847 |
+
f"- iterations: `{args.iterations}`",
|
| 848 |
+
f"- top_k: `{args.top_k}`",
|
| 849 |
+
f"- selection_mode: `{args.selection_mode}`",
|
| 850 |
+
f"- max_cases_per_glycan: `{args.max_cases_per_glycan}`",
|
| 851 |
+
f"- span_types: `{args.span_types}`",
|
| 852 |
+
f"- mask_plan: `{args.mask_plan or 'single-span default'}`",
|
| 853 |
+
"",
|
| 854 |
+
"## Dataset",
|
| 855 |
+
"",
|
| 856 |
+
f"- glycans_loaded: `{len(input_rows)}`",
|
| 857 |
+
f"- cases_built: `{build_stats.get('num_cases', 0)}`",
|
| 858 |
+
f"- masked_positions: `{build_stats.get('num_masked_positions', 0)}`",
|
| 859 |
+
f"- glycans_with_eligible_spans: `{build_stats.get('glycans_with_eligible_spans', 0)}`",
|
| 860 |
+
f"- glycans_without_eligible_spans: `{build_stats.get('glycans_without_eligible_spans', 0)}`",
|
| 861 |
+
f"- glycans_skipped_mask_plan: `{build_stats.get('glycans_skipped_mask_plan', 0)}`",
|
| 862 |
+
"",
|
| 863 |
+
"## Overall Metrics",
|
| 864 |
+
"",
|
| 865 |
+
]
|
| 866 |
+
|
| 867 |
+
metric_order = [
|
| 868 |
+
"initial_top1_token_accuracy",
|
| 869 |
+
"initial_top5_token_accuracy",
|
| 870 |
+
"initial_exact_span_accuracy_top1",
|
| 871 |
+
"initial_exact_span_accuracy_top5",
|
| 872 |
+
"iterative_resolved_fraction",
|
| 873 |
+
"iterative_accuracy_among_resolved",
|
| 874 |
+
"iterative_final_token_accuracy",
|
| 875 |
+
"iterative_exact_span_accuracy",
|
| 876 |
+
"avg_iterations_used_per_case",
|
| 877 |
+
]
|
| 878 |
+
for metric in metric_order:
|
| 879 |
+
value = overall.get(metric)
|
| 880 |
+
if value is not None:
|
| 881 |
+
lines.append(f"- {metric}: `{value:.4f}`")
|
| 882 |
+
|
| 883 |
+
if by_unit_type:
|
| 884 |
+
lines.extend(["", "## By Evaluation Group", ""])
|
| 885 |
+
for unit_type, unit_metrics in by_unit_type.items():
|
| 886 |
+
lines.append(f"### {unit_type}")
|
| 887 |
+
lines.append("")
|
| 888 |
+
for metric in metric_order:
|
| 889 |
+
value = unit_metrics.get(metric)
|
| 890 |
+
if value is not None:
|
| 891 |
+
lines.append(f"- {metric}: `{value:.4f}`")
|
| 892 |
+
lines.append("")
|
| 893 |
+
|
| 894 |
+
path.write_text("\n".join(lines).rstrip() + "\n")
|
| 895 |
+
|
| 896 |
+
|
| 897 |
+
def main() -> None:
|
| 898 |
+
args = parse_args()
|
| 899 |
+
setup_logging(args.log_level)
|
| 900 |
+
|
| 901 |
+
LOGGER.info("Loading held-out rows from %s", args.input_csv)
|
| 902 |
+
rows = load_rows(input_csv=args.input_csv, limit=args.limit, shuffle=args.shuffle, seed=args.seed)
|
| 903 |
+
LOGGER.info("Loaded %d glycans", len(rows))
|
| 904 |
+
|
| 905 |
+
span_types = [item.strip() for item in args.span_types.split(",") if item.strip()]
|
| 906 |
+
mask_requirements = parse_mask_plan(args.mask_plan)
|
| 907 |
+
if mask_requirements:
|
| 908 |
+
span_types = sorted(set(span_types) | set(mask_requirements))
|
| 909 |
+
evaluator = HeldoutIPAEvaluator(
|
| 910 |
+
checkpoint=args.checkpoint,
|
| 911 |
+
vocab=args.vocab,
|
| 912 |
+
ambiguity=args.ambiguity,
|
| 913 |
+
device=args.device,
|
| 914 |
+
threshold=args.threshold,
|
| 915 |
+
batch_size=args.batch_size,
|
| 916 |
+
top_k=args.top_k,
|
| 917 |
+
max_length=args.max_length,
|
| 918 |
+
)
|
| 919 |
+
|
| 920 |
+
cases, build_stats = evaluator.build_cases(
|
| 921 |
+
rows=rows,
|
| 922 |
+
span_types=span_types,
|
| 923 |
+
selection_mode=args.selection_mode,
|
| 924 |
+
max_cases_per_glycan=args.max_cases_per_glycan,
|
| 925 |
+
seed=args.seed,
|
| 926 |
+
mask_requirements=mask_requirements,
|
| 927 |
+
)
|
| 928 |
+
LOGGER.info(
|
| 929 |
+
"Built %d evaluation cases across %d masked positions",
|
| 930 |
+
build_stats.get("num_cases", 0),
|
| 931 |
+
build_stats.get("num_masked_positions", 0),
|
| 932 |
+
)
|
| 933 |
+
|
| 934 |
+
results, summary = evaluator.evaluate_cases(cases=cases, iterations=args.iterations)
|
| 935 |
+
|
| 936 |
+
run_dir = args.output_dir / args.run_name
|
| 937 |
+
run_dir.mkdir(parents=True, exist_ok=True)
|
| 938 |
+
write_json(run_dir / "build_stats.json", build_stats)
|
| 939 |
+
write_json(run_dir / "summary.json", summary)
|
| 940 |
+
write_jsonl(run_dir / "case_details.jsonl", results)
|
| 941 |
+
write_case_csv(run_dir / "case_results.csv", results)
|
| 942 |
+
write_summary_markdown(
|
| 943 |
+
run_dir / "summary.md",
|
| 944 |
+
args=args,
|
| 945 |
+
input_rows=rows,
|
| 946 |
+
build_stats=build_stats,
|
| 947 |
+
summary=summary,
|
| 948 |
+
)
|
| 949 |
+
|
| 950 |
+
LOGGER.info("Saved outputs under %s", run_dir)
|
| 951 |
+
if summary:
|
| 952 |
+
LOGGER.info(
|
| 953 |
+
"Overall top1=%.4f top5=%.4f iterative_final=%.4f span_exact=%.4f",
|
| 954 |
+
summary["overall"]["initial_top1_token_accuracy"],
|
| 955 |
+
summary["overall"]["initial_top5_token_accuracy"],
|
| 956 |
+
summary["overall"]["iterative_final_token_accuracy"],
|
| 957 |
+
summary["overall"]["iterative_exact_span_accuracy"],
|
| 958 |
+
)
|
| 959 |
+
|
| 960 |
+
|
| 961 |
+
if __name__ == "__main__":
|
| 962 |
+
main()
|
releases/2026-10-02/iar_completion/runtime_snapshot/schema/classify.py
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Definitive classification of '|' in WURCS LIN + residue-definition sections."""
|
| 2 |
+
import re, collections, json, sys
|
| 3 |
+
sys.path.insert(0,'.')
|
| 4 |
+
from pipelib import (split_sections, _TopLevelBracket, parse_record, ALT_GROUP_RE,
|
| 5 |
+
SIDE_RE, node_index)
|
| 6 |
+
|
| 7 |
+
TOKEN_RE = re.compile(r"[A-Za-z]+[0-9?]+")
|
| 8 |
+
|
| 9 |
+
def groups_in(entry):
|
| 10 |
+
return [m.group(0) for m in ALT_GROUP_RE.finditer(entry)]
|
| 11 |
+
|
| 12 |
+
def group_kind(g):
|
| 13 |
+
members = g.split("|")
|
| 14 |
+
parsed = []
|
| 15 |
+
for m in members:
|
| 16 |
+
mm = SIDE_RE.match(m)
|
| 17 |
+
if not mm: return None
|
| 18 |
+
parsed.append((mm.group(1), mm.group(2)))
|
| 19 |
+
res = [p[0] for p in parsed]; pos = [p[1] for p in parsed]
|
| 20 |
+
ures, upos = set(res), set(pos)
|
| 21 |
+
if len(ures) == 1 and len(upos) > 1:
|
| 22 |
+
return ("P_ALT_UNK" if "?" in upos else "P_ALT"), parsed
|
| 23 |
+
if len(upos) == 1 and len(ures) > 1:
|
| 24 |
+
return ("R_ALT_UNK" if "?" in upos else "R_ALT"), parsed
|
| 25 |
+
if len(ures) == 1 and len(upos) == 1:
|
| 26 |
+
return "DEGENERATE", parsed
|
| 27 |
+
return "JOINT_ALT", parsed
|
| 28 |
+
|
| 29 |
+
# entry-level shape: is it a plain 2-sided linkage with no repeat furniture?
|
| 30 |
+
PLAIN_LINK = re.compile(r"^([A-Za-z0-9?|]+)-([A-Za-z0-9?|]+)$")
|
| 31 |
+
|
| 32 |
+
def classify_entry(entry, rec):
|
| 33 |
+
"""Returns dict describing one pipe-bearing LIN entry."""
|
| 34 |
+
out = {}
|
| 35 |
+
out["repeat"] = ("{" in entry) or ("}" in entry)
|
| 36 |
+
out["tilde"] = "~" in entry
|
| 37 |
+
out["substituent"] = "*" in entry
|
| 38 |
+
gs = groups_in(entry)
|
| 39 |
+
kinds = []
|
| 40 |
+
for g in gs:
|
| 41 |
+
k = group_kind(g)
|
| 42 |
+
kinds.append(k[0] if k else "UNPARSED")
|
| 43 |
+
out["groups"] = gs
|
| 44 |
+
out["kinds"] = kinds
|
| 45 |
+
m = PLAIN_LINK.match(entry)
|
| 46 |
+
out["plain_link"] = bool(m)
|
| 47 |
+
out["r205"] = False
|
| 48 |
+
out["r205_detail"] = None
|
| 49 |
+
if m and not out["repeat"] and not out["tilde"] and not out["substituent"]:
|
| 50 |
+
L, R = m.group(1), m.group(2)
|
| 51 |
+
for altside, fixside in ((L, R), (R, L)):
|
| 52 |
+
if "|" not in altside or "|" in fixside:
|
| 53 |
+
continue
|
| 54 |
+
k = group_kind(altside)
|
| 55 |
+
if not k or k[0] != "P_ALT":
|
| 56 |
+
continue
|
| 57 |
+
fm = SIDE_RE.match(fixside)
|
| 58 |
+
if not fm or fm.group(2) == "?":
|
| 59 |
+
continue
|
| 60 |
+
dres, dpos = fm.group(1), int(fm.group(2))
|
| 61 |
+
ares = k[1][0][0]
|
| 62 |
+
apos = sorted(int(p) for _, p in k[1])
|
| 63 |
+
try:
|
| 64 |
+
di = node_index(dres) - 1; ai = node_index(ares) - 1
|
| 65 |
+
except ValueError:
|
| 66 |
+
continue
|
| 67 |
+
if not (0 <= di < rec["nres"] and 0 <= ai < rec["nres"]):
|
| 68 |
+
continue
|
| 69 |
+
danom = rec["anom"][di]; aanom = rec["anom"][ai]
|
| 70 |
+
donor_ok = (danom is not None and danom == dpos)
|
| 71 |
+
acceptor_ok = (aanom is None) or (aanom not in apos)
|
| 72 |
+
if donor_ok and acceptor_ok:
|
| 73 |
+
out["r205"] = True
|
| 74 |
+
out["r205_detail"] = dict(donor_skel=rec["skel"][di], donor_pos=dpos,
|
| 75 |
+
acceptor_skel=rec["skel"][ai], alts=apos,
|
| 76 |
+
acceptor_subs=sorted(rec["subs"][ai]))
|
| 77 |
+
break
|
| 78 |
+
return out
|
releases/2026-10-02/iar_completion/runtime_snapshot/schema/pipelib.py
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Shared WURCS '|' classification library. Frozen-parser-faithful where it matters."""
|
| 2 |
+
import re
|
| 3 |
+
|
| 4 |
+
WURCS_RES_INDEX_ALPHABET = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
| 5 |
+
|
| 6 |
+
def node_index(label):
|
| 7 |
+
base = len(WURCS_RES_INDEX_ALPHABET)
|
| 8 |
+
value = 0
|
| 9 |
+
for ch in label:
|
| 10 |
+
d = WURCS_RES_INDEX_ALPHABET.index(ch) + 1 # raises ValueError
|
| 11 |
+
value = value * base + d
|
| 12 |
+
return value
|
| 13 |
+
|
| 14 |
+
def split_sections(wurcs):
|
| 15 |
+
"""Frozen A5WURCSPreTokenizer._split_wurcs_sections semantics."""
|
| 16 |
+
if wurcs.startswith("WURCS="):
|
| 17 |
+
body = wurcs[6:]
|
| 18 |
+
else:
|
| 19 |
+
return None
|
| 20 |
+
sections, cur, depth = [], [], 0
|
| 21 |
+
for ch in body:
|
| 22 |
+
if ch == "[":
|
| 23 |
+
depth += 1; cur.append(ch)
|
| 24 |
+
elif ch == "]":
|
| 25 |
+
if depth: depth -= 1
|
| 26 |
+
cur.append(ch)
|
| 27 |
+
elif ch == "/" and depth == 0:
|
| 28 |
+
sections.append("".join(cur)); cur = []
|
| 29 |
+
else:
|
| 30 |
+
cur.append(ch)
|
| 31 |
+
sections.append("".join(cur))
|
| 32 |
+
if len(sections) > 5:
|
| 33 |
+
sections = sections[:4] + ["/".join(sections[4:])]
|
| 34 |
+
return sections
|
| 35 |
+
|
| 36 |
+
class _TopLevelBracket:
|
| 37 |
+
@staticmethod
|
| 38 |
+
def findall(text):
|
| 39 |
+
out, depth, start = [], 0, -1
|
| 40 |
+
for i, c in enumerate(text):
|
| 41 |
+
if c == "[":
|
| 42 |
+
if depth == 0: start = i + 1
|
| 43 |
+
depth += 1
|
| 44 |
+
elif c == "]" and depth:
|
| 45 |
+
depth -= 1
|
| 46 |
+
if depth == 0 and start >= 0:
|
| 47 |
+
out.append(text[start:i]); start = -1
|
| 48 |
+
return [] if depth else out
|
| 49 |
+
|
| 50 |
+
ANOM_RE = re.compile(r"-([0-9]+)([abuxo])(?:_|$)")
|
| 51 |
+
RING_RE = re.compile(r"^(\d+)-(\d+|\?)$")
|
| 52 |
+
|
| 53 |
+
def parse_record(wurcs):
|
| 54 |
+
"""Return dict with sections, residue defs, per-instance def index, anomeric pos, LIN entries."""
|
| 55 |
+
s = split_sections(wurcs)
|
| 56 |
+
if s is None or len(s) < 4:
|
| 57 |
+
return None
|
| 58 |
+
defs = _TopLevelBracket.findall(s[2])
|
| 59 |
+
idx_list = s[3].split("-") if s[3] else []
|
| 60 |
+
lin = s[4] if len(s) > 4 else ""
|
| 61 |
+
anom, skel, ring, subs = [], [], [], []
|
| 62 |
+
for di in idx_list:
|
| 63 |
+
try:
|
| 64 |
+
d = defs[int(di) - 1]
|
| 65 |
+
except (IndexError, ValueError):
|
| 66 |
+
anom.append(None); skel.append(None); ring.append(None); subs.append(set()); continue
|
| 67 |
+
m = ANOM_RE.search(d)
|
| 68 |
+
anom.append(int(m.group(1)) if m else None)
|
| 69 |
+
parts = d.split("_")
|
| 70 |
+
skel.append(parts[0].split("-")[0])
|
| 71 |
+
r = None; sb = set()
|
| 72 |
+
for p in parts[1:]:
|
| 73 |
+
mr = RING_RE.match(p)
|
| 74 |
+
if mr:
|
| 75 |
+
r = (int(mr.group(1)), mr.group(2)); continue
|
| 76 |
+
# substituent forms like '2*NCC/3=O', '3|4*OCC/3=O', '6%?%*OC'
|
| 77 |
+
for mm in re.finditer(r"(\d+)(?:%\?%)?\*", p):
|
| 78 |
+
sb.add(int(mm.group(1)))
|
| 79 |
+
ring.append(r); subs.append(sb)
|
| 80 |
+
return dict(wurcs=wurcs, sections=s, defs=defs, idx_list=idx_list, lin=lin,
|
| 81 |
+
anom=anom, skel=skel, ring=ring, subs=subs, nres=len(idx_list))
|
| 82 |
+
|
| 83 |
+
# ---- alternation groups -------------------------------------------------
|
| 84 |
+
ALT_GROUP_RE = re.compile(r"(?:[A-Za-z]+[0-9?]+)(?:\|[A-Za-z]+[0-9?]+)+")
|
| 85 |
+
SIDE_RE = re.compile(r"^([A-Za-z]+)([0-9?]+)$")
|
| 86 |
+
|
| 87 |
+
def alt_groups(entry):
|
| 88 |
+
return [(m.group(0), m.start(), m.end()) for m in ALT_GROUP_RE.finditer(entry)]
|
| 89 |
+
|
| 90 |
+
def classify_group(text):
|
| 91 |
+
members = text.split("|")
|
| 92 |
+
parsed = []
|
| 93 |
+
for m in members:
|
| 94 |
+
mm = SIDE_RE.match(m)
|
| 95 |
+
if not mm: return None
|
| 96 |
+
parsed.append((mm.group(1), mm.group(2)))
|
| 97 |
+
residues = {p[0] for p in parsed}
|
| 98 |
+
positions = {p[1] for p in parsed}
|
| 99 |
+
n = len(parsed)
|
| 100 |
+
if len(residues) == 1 and len(positions) == n:
|
| 101 |
+
kind = "POS_ALT"
|
| 102 |
+
elif len(positions) == 1 and len(residues) == n:
|
| 103 |
+
kind = "RES_ALT_Q" if "?" in positions else "RES_ALT"
|
| 104 |
+
elif len(residues) == 1:
|
| 105 |
+
kind = "POS_ALT_DUP"
|
| 106 |
+
elif len(positions) == 1:
|
| 107 |
+
kind = "RES_ALT_DUP"
|
| 108 |
+
else:
|
| 109 |
+
kind = "JOINT_ALT"
|
| 110 |
+
return dict(kind=kind, n=n, residues=sorted(residues), positions=sorted(positions),
|
| 111 |
+
parsed=parsed, all_q=(positions == {"?"}), any_q=("?" in positions))
|
| 112 |
+
|
| 113 |
+
# split a LIN entry into left/right around the top-level '-' that separates the two sides
|
| 114 |
+
LINK_SPLIT_RE = re.compile(r"^(?P<L>[A-Za-z0-9?|%]+?)(?P<lb>\}?)-(?P<rb>\{?)(?P<R>[A-Za-z0-9?|%]+)(?P<tail>.*)$")
|
| 115 |
+
|
| 116 |
+
def split_entry(entry):
|
| 117 |
+
m = LINK_SPLIT_RE.match(entry)
|
| 118 |
+
if not m: return None
|
| 119 |
+
return m.group("L"), m.group("R"), m.group("lb"), m.group("rb"), m.group("tail")
|
releases/2026-10-02/iar_inference/README.md
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Full-checkpoint IAR inference on two recorded cases
|
| 2 |
+
|
| 3 |
+
This entry point loads the full frozen BERTose WA3 checkpoint and runs the saved 211-class linkage readout on two real, previously executed single-linkage cases. It preserves the original masked side channels, training-frequency-weighted neutral linkage embedding, input-of-`sequence_head` feature, NumPy float32 feature normalization, 0.80 acceptance threshold and maximum of three rounds. No fitting occurs.
|
| 4 |
+
|
| 5 |
+
The fixture was rebuilt with the frozen tokenizer and official WURCS helper in Slurm job 16662851. That job accepted `g8-h2` for the benchmark case and abstained on the grey-seal case. These two cases are an inference check, not an estimate of completion accuracy. The full portable forward passed in job 16683971; the earlier preparation check recorded here loaded no model.
|
| 6 |
+
|
| 7 |
+
## Files and dependencies
|
| 8 |
+
|
| 9 |
+
Keep these three released directories together, or supply the two root arguments below:
|
| 10 |
+
|
| 11 |
+
```text
|
| 12 |
+
code/
|
| 13 |
+
iar_inference/ # this runner, configuration and two-case fixtures
|
| 14 |
+
iar_completion/ # saved readout, metadata, original source and vocabulary
|
| 15 |
+
bertose_source/ # unchanged model sources and small component authorities
|
| 16 |
+
```
|
| 17 |
+
|
| 18 |
+
`config.json` pins the 14 required files under `bertose_source`, five files under `iar_completion`, copied helpers and four fixture files. The full checkpoint is supplied separately through `--checkpoint`; it is not copied here. Its required SHA-256 is `8e7d95ee492df6d843f495dd4708c97ee16a947e75b5cd8f83b23e4f4a0d6d82`.
|
| 19 |
+
|
| 20 |
+
Python 3.10 or later is required. `requirements.txt` records the PyTorch and NumPy versions used by the executed CPU reference. Use a CPU-capable PyTorch build. The runner always uses CPU float32, even on a machine with CUDA. Allow several GB of memory for the complete historical checkpoint and model. On Nova, run the full command only in a Slurm compute allocation.
|
| 21 |
+
|
| 22 |
+
## Run
|
| 23 |
+
|
| 24 |
+
Check the small files without importing PyTorch or opening the checkpoint:
|
| 25 |
+
|
| 26 |
+
```bash
|
| 27 |
+
python code/iar_inference/infer.py --preflight-only
|
| 28 |
+
```
|
| 29 |
+
|
| 30 |
+
Run the full checkpoint and compare both cases with the saved execution:
|
| 31 |
+
|
| 32 |
+
```bash
|
| 33 |
+
python code/iar_inference/infer.py \
|
| 34 |
+
--checkpoint /absolute/path/to/review_md20x6_checkpoint_best.pt \
|
| 35 |
+
--output-dir /absolute/path/to/new_iar_output \
|
| 36 |
+
--threads 4
|
| 37 |
+
```
|
| 38 |
+
|
| 39 |
+
The output directory must not exist and its parent must exist. To relocate the companion artifacts, add `--source-root /absolute/path/to/bertose_source` and `--readout-root /absolute/path/to/iar_completion`. Their internal relative layouts and bytes must remain intact. No Nova path, Java installation, training dataset or scheduler is required by this runner.
|
| 40 |
+
|
| 41 |
+
A successful full run writes `inference_report.json` and two `caseN_pre_sequence_head.npy` arrays. It must report `PASS_PORTABLE_FULL_WA3_TWO_CASE_REFERENCE_CHECK`, 505 strictly loaded state entries, 138,487,995 model parameters, 12 verified component bindings, two finite model forwards, the recorded acceptance/abstention decisions and the same ordered top-10 token IDs. Hidden vectors and probabilities must agree with the CPU reference using `atol=2e-5, rtol=2e-5`; exact equality and maximum hidden differences are reported separately. This tolerance is an explicit smoke-test criterion, not a claim of historical CUDA bitwise replay. A mismatch fails the run.
|
| 42 |
+
|
| 43 |
+
## What the loader preserves
|
| 44 |
+
|
| 45 |
+
The loader imports the byte-pinned R5 composite and MD factory from the released source tree. The factory receives the exact original composite class and module through the two attributes it uses from the training executor. It constructs the original `A111`/`A1111`, 2,114-token model with temporal size 128. It retains the unmodified production configuration validation, constructor authority checks, no-follow authority-file reads, tensor-surface validation and live model contract. It also explicitly rechecks the component authorities after strict checkpoint loading. `isolated_test_fixture` remains false.
|
| 46 |
+
|
| 47 |
+
The original R5 source pin matches the R5 executor's bound source. Its constructor independently validates the frozen R4 lineage, sequence vocabulary and tokenizer bindings, topology source and MS authority/receipt/certificate. The loader neither edits those checks nor changes their archival authorization flags. It does not invoke the training launcher, optimizer/planner authorities or the later static-release launch bootstrap. Those gates authorize a different operation: this entry point has no training path and supplies explicitly absent MS, static and MD carriers, as the executed IAR smoke did. Full checkpoint loading does not establish that active physical-modality inference is portable.
|
| 48 |
+
|
| 49 |
+
`original_inference_helpers.py` contains only eight verbatim function definitions from the final historical IAR source: the absent-carrier constructor, hook/capture utilities and forward helper, plus its failure function. Preflight compares their ASTs with that pinned source. The historical module itself is not imported because its top level changes `builtins.open` and requires a `WORK` environment variable. The saved `iar_completion/readout.py` is used unchanged. The full historical checkpoint uses `torch.load(..., weights_only=False)` only after its complete bytes match the mandatory SHA-256, through the same open file descriptor; do not replace this with untrusted checkpoint bytes.
|
| 50 |
+
|
| 51 |
+
## Scope limits
|
| 52 |
+
|
| 53 |
+
- The runner accepts only the two byte-pinned rebuilt fixture cases. Their WURCS strings and helper records are provenance; raw WURCS is not converted at runtime. Moving the fixture files does not require regenerating them, so no input export helper is needed.
|
| 54 |
+
- General glycan completion, new masking cases, residue or multi-token fallback, corpus reconstruction and full historical metrics are outside this executable interface.
|
| 55 |
+
- The complete checkpoint is loaded, but the two forwards exercise sequence inference with MS, static and MD explicitly absent. Active carrier paths, CUDA and other checkpoints are untested here.
|
| 56 |
+
- A passing small-file preflight does not establish successful checkpoint loading or numerical inference. Only a completed full-run report does so for these two cases.
|
| 57 |
+
|
| 58 |
+
The public runner passed a fresh-extraction CPU execution in Nova job 16683971: full strict loading, both hidden vectors bitwise equal to the prior reference, and unchanged ordered predictions and abstention. The receipt is in `../provenance/portable_execution_20260930/iar_portable_report.json`.
|
releases/2026-10-02/iar_inference/SHA256SUMS
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
8fc1d034d7b8a3d7c12cdfa958f1b5825be73cedabce8e96a83441e883bea0e7 README.md
|
| 2 |
+
043a38744f9fd832181d822ae8481488d954604bf615b2eb05c4c8ad29794325 config.json
|
| 3 |
+
a212cfbd49ec2f951e942c92caaac63260687a626eca588cb692d86bb1e52198 fixtures/case0_pre_sequence_head.npy
|
| 4 |
+
6ffca438526432a33168a85a0fee1158fd2a9c9f23ecb97f587235f204ae50b3 fixtures/case1_pre_sequence_head.npy
|
| 5 |
+
60ac0c0fd1b6e0ada2d847d1fccff4f6fe7c085aab3146247dc5d7bfebbabc27 fixtures/rebuilt_two_case_inputs.json
|
| 6 |
+
60dcdb6262457962da84c7b239c194fac343bd8d27db0e05f15906acb9bf5f4b fixtures/reference_smoke_report.json
|
| 7 |
+
9237b349668ea3fb5266f4696169fd958e9f997e5064ede0ab06e41859b17361 infer.py
|
| 8 |
+
87fa484e1f6105fa476dff4cf8c7e6aea71a2aac537796131a4858632f54b906 original_inference_helpers.py
|
| 9 |
+
4e36f9237dc494eb47898ff3ab9a5b1a483f5004aa933a5294af794edd0757ce preparation_validation.json
|
| 10 |
+
16e89b25a13eabc8586ba2a8ec32890ecf321f652b03f7548c63112d13cb2e62 requirements.txt
|
releases/2026-10-02/iar_inference/config.json
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"schema": "bertose_portable_two_case_iar_v1",
|
| 3 |
+
"source_root": "../bertose_source",
|
| 4 |
+
"readout_root": "../iar_completion",
|
| 5 |
+
"model_sources": {
|
| 6 |
+
"r5": "writing/review/multimodal/runtime/a5_pretraining_failclosed_integration_20260721_r5/review_a5_native_eight_composite_r5.py",
|
| 7 |
+
"md_core": "writing/review/multimodal/runtime/md_temporal_20x6_end_to_end_20260802_r3_native_intersection/review_md_temporal_20x6_core_r3.py"
|
| 8 |
+
},
|
| 9 |
+
"source_files": [
|
| 10 |
+
{
|
| 11 |
+
"path": "writing/review/multimodal/runtime/a5_pretraining_failclosed_integration_20260721_r4/review_a5_native_eight_composite_r4.py",
|
| 12 |
+
"bytes": 70358,
|
| 13 |
+
"sha256": "52a311636e7631b97711aab63aec28e2ada47a446d1aecc1a47921d584f69f9d"
|
| 14 |
+
},
|
| 15 |
+
{
|
| 16 |
+
"path": "writing/review/multimodal/runtime/a5_pretraining_failclosed_integration_20260721_r5/review_a5_native_eight_composite_r5.py",
|
| 17 |
+
"bytes": 58459,
|
| 18 |
+
"sha256": "24c35257fc61e1c9c77630d2b0075775a7f46b6500ecb5f175ef8f42bd214e0e"
|
| 19 |
+
},
|
| 20 |
+
{
|
| 21 |
+
"path": "writing/review/multimodal/runtime/md_temporal_20x6_end_to_end_20260802_r3_native_intersection/review_md_temporal_20x6_core_r3.py",
|
| 22 |
+
"bytes": 48643,
|
| 23 |
+
"sha256": "3e96d8092239c2c21f217ad5bae4ee7e07dbe0f7630b213bad468d6b08d3b1c1"
|
| 24 |
+
},
|
| 25 |
+
{
|
| 26 |
+
"path": "writing/review/multimodal/runtime/a5_pretraining_failclosed_integration_20260721_r5/review_a5_native_eight_r4_lineage_receipt_r1.json",
|
| 27 |
+
"bytes": 1716,
|
| 28 |
+
"sha256": "b5fbdff168de23676208484ccccc3cc32f613ea411d193e6d8930456e8edeeef"
|
| 29 |
+
},
|
| 30 |
+
{
|
| 31 |
+
"path": "writing/review/multimodal/outputs/review_a5_official_ragged_sequence_topology_runtime_20260721_r3/review_a5_topology_loss_v2.py",
|
| 32 |
+
"bytes": 8067,
|
| 33 |
+
"sha256": "64eaf9174f523ae909c84987049d071bf3869ca8e83919f14f0572ef77b0530e"
|
| 34 |
+
},
|
| 35 |
+
{
|
| 36 |
+
"path": "writing/review/multimodal/runtime/a5_ms_acquisition_top30_v3_20260721_r3/review_a5_ms_acquisition_top30_runtime_v3.py",
|
| 37 |
+
"bytes": 43711,
|
| 38 |
+
"sha256": "68c0d543c5411276ef56c7072bded4ebda886f46b9fa4ebf3c95c1e54c1a08c6"
|
| 39 |
+
},
|
| 40 |
+
{
|
| 41 |
+
"path": "data/review_sequences_a5_non_iar_later_role_official_array_v4_20260721_r1/review_sequence_package_receipt.json",
|
| 42 |
+
"bytes": 5797,
|
| 43 |
+
"sha256": "399df3de2b6c4d5e88aa442c8326214ab9cff2e8f0411e6921762bbade1475ba"
|
| 44 |
+
},
|
| 45 |
+
{
|
| 46 |
+
"path": "data/review_sequences_a5_non_iar_later_role_official_array_v4_20260721_r1/review_sequence_package_summary.json",
|
| 47 |
+
"bytes": 7777,
|
| 48 |
+
"sha256": "93ed219d807d4a7735be96bf7cf6a59a0bd407619925ee194aed6d473048cdf0"
|
| 49 |
+
},
|
| 50 |
+
{
|
| 51 |
+
"path": "data/review_sequences_a5_non_iar_later_role_official_array_v4_20260721_r1/review_bpe_vocabulary.json",
|
| 52 |
+
"bytes": 138150,
|
| 53 |
+
"sha256": "918c73a55adeb603614112d75bb02033e5823fd9c8a70d43f6c0a4a9c78e360b"
|
| 54 |
+
},
|
| 55 |
+
{
|
| 56 |
+
"path": "data/review_sequences_a5_non_iar_later_role_official_array_v4_20260721_r1/review_frozen_training_a5_wurcs_bpe.py",
|
| 57 |
+
"bytes": 14161,
|
| 58 |
+
"sha256": "6591b854962c278dc797981c942e114c18a26e97af43029c1d539bae3badb2f4"
|
| 59 |
+
},
|
| 60 |
+
{
|
| 61 |
+
"path": "data/review_sequences_a5_non_iar_later_role_official_array_v4_20260721_r1/review_frozen_sequence_tree_runtime.py",
|
| 62 |
+
"bytes": 11405,
|
| 63 |
+
"sha256": "10ca4b121d2f22d7a64208e4f05172e7a756b653d0828c9dcc49dd8ea1a5ad04"
|
| 64 |
+
},
|
| 65 |
+
{
|
| 66 |
+
"path": "data/review_ms_acquisition_top30_runtime_20260721_r3/review_a5_ms_acquisition_top30_runtime_authority.json",
|
| 67 |
+
"bytes": 20541,
|
| 68 |
+
"sha256": "48914855c4e458ff02452ad4db3743a4fbef12221e0313584db4c2b1bd684cd4"
|
| 69 |
+
},
|
| 70 |
+
{
|
| 71 |
+
"path": "data/review_ms_acquisition_top30_runtime_20260721_r3/review_a5_ms_acquisition_top30_runtime_receipt.json",
|
| 72 |
+
"bytes": 6260,
|
| 73 |
+
"sha256": "f654177eb6fde7289b6755812c2be298084697cf0d85159b3ec9da310fe3d4b4"
|
| 74 |
+
},
|
| 75 |
+
{
|
| 76 |
+
"path": "data/review_ms_acquisition_top30_runtime_20260721_r3/review_a5_ms_acquisition_top30_runtime_independent_certificate.json",
|
| 77 |
+
"bytes": 19121,
|
| 78 |
+
"sha256": "53098620a5c22dafdc951ba743515b4b10b1673c02f0aa4d881db669584902fa"
|
| 79 |
+
}
|
| 80 |
+
],
|
| 81 |
+
"readout_files": [
|
| 82 |
+
{
|
| 83 |
+
"path": "readout.py",
|
| 84 |
+
"bytes": 5515,
|
| 85 |
+
"sha256": "42464d76c743a302bae79ced6b09af9657444c6f977535b5de49dcf59a5a8a90"
|
| 86 |
+
},
|
| 87 |
+
{
|
| 88 |
+
"path": "model_metadata.json",
|
| 89 |
+
"bytes": 3132,
|
| 90 |
+
"sha256": "bbf016ce2f1a7dc82940be28397cbe8083da7ad0f5f525b1cf7345fd42a5758d"
|
| 91 |
+
},
|
| 92 |
+
{
|
| 93 |
+
"path": "assets/linkage_readout.pt",
|
| 94 |
+
"bytes": 663845,
|
| 95 |
+
"sha256": "a03990a02a1737de05a7fa1739164e84fa6a0a4170ebaa65317a9f3c2f16c0b0"
|
| 96 |
+
},
|
| 97 |
+
{
|
| 98 |
+
"path": "originals/wa3_final_iar_readout_all.py",
|
| 99 |
+
"bytes": 82622,
|
| 100 |
+
"sha256": "72f8583bf32799ba29c09829d138900c0cbb589f73bd278f389da6fa8a786730"
|
| 101 |
+
},
|
| 102 |
+
{
|
| 103 |
+
"path": "runtime_snapshot/project/data/review_sequences_a5_non_iar_later_role_official_array_v4_20260721_r1/review_bpe_vocabulary.json",
|
| 104 |
+
"bytes": 138150,
|
| 105 |
+
"sha256": "918c73a55adeb603614112d75bb02033e5823fd9c8a70d43f6c0a4a9c78e360b"
|
| 106 |
+
}
|
| 107 |
+
],
|
| 108 |
+
"local_files": [
|
| 109 |
+
{
|
| 110 |
+
"path": "original_inference_helpers.py",
|
| 111 |
+
"bytes": 4608,
|
| 112 |
+
"sha256": "87fa484e1f6105fa476dff4cf8c7e6aea71a2aac537796131a4858632f54b906"
|
| 113 |
+
},
|
| 114 |
+
{
|
| 115 |
+
"path": "fixtures/case0_pre_sequence_head.npy",
|
| 116 |
+
"bytes": 3200,
|
| 117 |
+
"sha256": "a212cfbd49ec2f951e942c92caaac63260687a626eca588cb692d86bb1e52198"
|
| 118 |
+
},
|
| 119 |
+
{
|
| 120 |
+
"path": "fixtures/case1_pre_sequence_head.npy",
|
| 121 |
+
"bytes": 3200,
|
| 122 |
+
"sha256": "6ffca438526432a33168a85a0fee1158fd2a9c9f23ecb97f587235f204ae50b3"
|
| 123 |
+
},
|
| 124 |
+
{
|
| 125 |
+
"path": "fixtures/rebuilt_two_case_inputs.json",
|
| 126 |
+
"bytes": 42915,
|
| 127 |
+
"sha256": "60ac0c0fd1b6e0ada2d847d1fccff4f6fe7c085aab3146247dc5d7bfebbabc27"
|
| 128 |
+
},
|
| 129 |
+
{
|
| 130 |
+
"path": "fixtures/reference_smoke_report.json",
|
| 131 |
+
"bytes": 7532,
|
| 132 |
+
"sha256": "60dcdb6262457962da84c7b239c194fac343bd8d27db0e05f15906acb9bf5f4b"
|
| 133 |
+
}
|
| 134 |
+
],
|
| 135 |
+
"original_helper_functions": [
|
| 136 |
+
"fail",
|
| 137 |
+
"all_absent",
|
| 138 |
+
"_linkage_hook",
|
| 139 |
+
"find_linkage_embedding",
|
| 140 |
+
"_cap_hook",
|
| 141 |
+
"find_lm_projection",
|
| 142 |
+
"_gather_h",
|
| 143 |
+
"_forward"
|
| 144 |
+
],
|
| 145 |
+
"checkpoint": {
|
| 146 |
+
"sha256": "8e7d95ee492df6d843f495dd4708c97ee16a947e75b5cd8f83b23e4f4a0d6d82",
|
| 147 |
+
"md_cell_id": "A1111",
|
| 148 |
+
"base_cell_id": "A111",
|
| 149 |
+
"best_epoch": 58,
|
| 150 |
+
"state_entries": 505,
|
| 151 |
+
"parameter_count": 138487995,
|
| 152 |
+
"vocabulary_size": 2114,
|
| 153 |
+
"md_temporal_size": 128
|
| 154 |
+
},
|
| 155 |
+
"inference": {
|
| 156 |
+
"device": "cpu",
|
| 157 |
+
"dtype": "float32",
|
| 158 |
+
"threshold": 0.8,
|
| 159 |
+
"maximum_rounds": 3,
|
| 160 |
+
"neutral_module": "sequence_embeddings.linkage_embeddings",
|
| 161 |
+
"hidden_module": "sequence_head",
|
| 162 |
+
"neutral_training_counts": [
|
| 163 |
+
97966,
|
| 164 |
+
150442,
|
| 165 |
+
219104,
|
| 166 |
+
95827,
|
| 167 |
+
13486,
|
| 168 |
+
11976,
|
| 169 |
+
23,
|
| 170 |
+
36422
|
| 171 |
+
],
|
| 172 |
+
"hidden_allclose_atol": 2e-05,
|
| 173 |
+
"hidden_allclose_rtol": 2e-05,
|
| 174 |
+
"probability_allclose_atol": 2e-05,
|
| 175 |
+
"probability_allclose_rtol": 2e-05
|
| 176 |
+
},
|
| 177 |
+
"scope": "The two byte-pinned, official-helper-rebuilt single-linkage cases only; physical modalities explicitly absent. No refit, raw-WURCS conversion, fallback, corpus metrics or training authorization."
|
| 178 |
+
}
|
releases/2026-10-02/iar_inference/fixtures/case0_pre_sequence_head.npy
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:a212cfbd49ec2f951e942c92caaac63260687a626eca588cb692d86bb1e52198
|
| 3 |
+
size 3200
|
releases/2026-10-02/iar_inference/fixtures/case1_pre_sequence_head.npy
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:6ffca438526432a33168a85a0fee1158fd2a9c9f23ecb97f587235f204ae50b3
|
| 3 |
+
size 3200
|
releases/2026-10-02/iar_inference/fixtures/rebuilt_two_case_inputs.json
ADDED
|
@@ -0,0 +1,3718 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[
|
| 2 |
+
{
|
| 3 |
+
"dataset": "bench1392",
|
| 4 |
+
"source_case_id": "g0000_s00_linkage_38_38",
|
| 5 |
+
"recorded_source_sha256": "124effa978c07bab00e7056c41d4c727a2a4c7d766d8d2a510c11a0fc52d3721",
|
| 6 |
+
"official_helper": {
|
| 7 |
+
"rooted": true,
|
| 8 |
+
"depths": [
|
| 9 |
+
0,
|
| 10 |
+
1,
|
| 11 |
+
2,
|
| 12 |
+
3,
|
| 13 |
+
4,
|
| 14 |
+
5,
|
| 15 |
+
6,
|
| 16 |
+
7,
|
| 17 |
+
8,
|
| 18 |
+
9
|
| 19 |
+
],
|
| 20 |
+
"parents": [
|
| 21 |
+
-1,
|
| 22 |
+
0,
|
| 23 |
+
1,
|
| 24 |
+
2,
|
| 25 |
+
3,
|
| 26 |
+
4,
|
| 27 |
+
5,
|
| 28 |
+
6,
|
| 29 |
+
7,
|
| 30 |
+
8
|
| 31 |
+
],
|
| 32 |
+
"helper_error": false
|
| 33 |
+
},
|
| 34 |
+
"rebuilt_case": {
|
| 35 |
+
"case_id": "g0000_s00_linkage_38_38",
|
| 36 |
+
"glycan_index": 0,
|
| 37 |
+
"wurcs": "WURCS=2.0/2,10,9/[AUd21122h_5*NCC/3=O][Aad21122h-2a_2-6_5*NCC/3=O]/1-2-2-2-2-2-2-2-2-2/a8-b2_b8-c2_c8-d2_d8-e2_e8-f2_f8-g2_g8-h2_h8-i2_i8-j2",
|
| 38 |
+
"mask_plan": "linkage:1",
|
| 39 |
+
"units": [
|
| 40 |
+
{
|
| 41 |
+
"g": 35,
|
| 42 |
+
"unit_type": "linkage",
|
| 43 |
+
"unit_text": "g8-h2"
|
| 44 |
+
}
|
| 45 |
+
],
|
| 46 |
+
"wa0_iterative_span_exact": true,
|
| 47 |
+
"wa0_initial_span_exact_top1": true,
|
| 48 |
+
"unit_text": "linkage:g8-h2",
|
| 49 |
+
"positions": [
|
| 50 |
+
43
|
| 51 |
+
],
|
| 52 |
+
"truth_ids": [
|
| 53 |
+
1720
|
| 54 |
+
],
|
| 55 |
+
"masked_ids": [
|
| 56 |
+
2,
|
| 57 |
+
316,
|
| 58 |
+
225,
|
| 59 |
+
254,
|
| 60 |
+
208,
|
| 61 |
+
225,
|
| 62 |
+
254,
|
| 63 |
+
208,
|
| 64 |
+
225,
|
| 65 |
+
254,
|
| 66 |
+
208,
|
| 67 |
+
225,
|
| 68 |
+
254,
|
| 69 |
+
208,
|
| 70 |
+
225,
|
| 71 |
+
254,
|
| 72 |
+
208,
|
| 73 |
+
225,
|
| 74 |
+
254,
|
| 75 |
+
208,
|
| 76 |
+
225,
|
| 77 |
+
254,
|
| 78 |
+
208,
|
| 79 |
+
225,
|
| 80 |
+
254,
|
| 81 |
+
208,
|
| 82 |
+
225,
|
| 83 |
+
254,
|
| 84 |
+
208,
|
| 85 |
+
225,
|
| 86 |
+
1283,
|
| 87 |
+
568,
|
| 88 |
+
72,
|
| 89 |
+
557,
|
| 90 |
+
436,
|
| 91 |
+
1484,
|
| 92 |
+
2015,
|
| 93 |
+
75,
|
| 94 |
+
557,
|
| 95 |
+
619,
|
| 96 |
+
76,
|
| 97 |
+
557,
|
| 98 |
+
348,
|
| 99 |
+
4,
|
| 100 |
+
1380,
|
| 101 |
+
79,
|
| 102 |
+
557,
|
| 103 |
+
585,
|
| 104 |
+
3,
|
| 105 |
+
0,
|
| 106 |
+
0,
|
| 107 |
+
0,
|
| 108 |
+
0,
|
| 109 |
+
0,
|
| 110 |
+
0,
|
| 111 |
+
0,
|
| 112 |
+
0,
|
| 113 |
+
0,
|
| 114 |
+
0,
|
| 115 |
+
0,
|
| 116 |
+
0,
|
| 117 |
+
0,
|
| 118 |
+
0,
|
| 119 |
+
0,
|
| 120 |
+
0,
|
| 121 |
+
0,
|
| 122 |
+
0,
|
| 123 |
+
0,
|
| 124 |
+
0,
|
| 125 |
+
0,
|
| 126 |
+
0,
|
| 127 |
+
0,
|
| 128 |
+
0,
|
| 129 |
+
0,
|
| 130 |
+
0,
|
| 131 |
+
0,
|
| 132 |
+
0,
|
| 133 |
+
0,
|
| 134 |
+
0,
|
| 135 |
+
0,
|
| 136 |
+
0,
|
| 137 |
+
0,
|
| 138 |
+
0,
|
| 139 |
+
0,
|
| 140 |
+
0,
|
| 141 |
+
0,
|
| 142 |
+
0,
|
| 143 |
+
0,
|
| 144 |
+
0,
|
| 145 |
+
0,
|
| 146 |
+
0,
|
| 147 |
+
0,
|
| 148 |
+
0,
|
| 149 |
+
0,
|
| 150 |
+
0,
|
| 151 |
+
0,
|
| 152 |
+
0,
|
| 153 |
+
0,
|
| 154 |
+
0,
|
| 155 |
+
0,
|
| 156 |
+
0,
|
| 157 |
+
0,
|
| 158 |
+
0,
|
| 159 |
+
0,
|
| 160 |
+
0,
|
| 161 |
+
0,
|
| 162 |
+
0,
|
| 163 |
+
0,
|
| 164 |
+
0,
|
| 165 |
+
0,
|
| 166 |
+
0,
|
| 167 |
+
0,
|
| 168 |
+
0,
|
| 169 |
+
0,
|
| 170 |
+
0,
|
| 171 |
+
0,
|
| 172 |
+
0,
|
| 173 |
+
0,
|
| 174 |
+
0,
|
| 175 |
+
0,
|
| 176 |
+
0,
|
| 177 |
+
0,
|
| 178 |
+
0,
|
| 179 |
+
0,
|
| 180 |
+
0,
|
| 181 |
+
0,
|
| 182 |
+
0,
|
| 183 |
+
0,
|
| 184 |
+
0,
|
| 185 |
+
0,
|
| 186 |
+
0,
|
| 187 |
+
0,
|
| 188 |
+
0,
|
| 189 |
+
0,
|
| 190 |
+
0,
|
| 191 |
+
0,
|
| 192 |
+
0,
|
| 193 |
+
0,
|
| 194 |
+
0,
|
| 195 |
+
0,
|
| 196 |
+
0,
|
| 197 |
+
0,
|
| 198 |
+
0,
|
| 199 |
+
0,
|
| 200 |
+
0,
|
| 201 |
+
0,
|
| 202 |
+
0,
|
| 203 |
+
0,
|
| 204 |
+
0,
|
| 205 |
+
0,
|
| 206 |
+
0,
|
| 207 |
+
0,
|
| 208 |
+
0,
|
| 209 |
+
0,
|
| 210 |
+
0,
|
| 211 |
+
0,
|
| 212 |
+
0,
|
| 213 |
+
0,
|
| 214 |
+
0,
|
| 215 |
+
0,
|
| 216 |
+
0,
|
| 217 |
+
0,
|
| 218 |
+
0,
|
| 219 |
+
0,
|
| 220 |
+
0,
|
| 221 |
+
0,
|
| 222 |
+
0,
|
| 223 |
+
0,
|
| 224 |
+
0,
|
| 225 |
+
0,
|
| 226 |
+
0,
|
| 227 |
+
0,
|
| 228 |
+
0,
|
| 229 |
+
0,
|
| 230 |
+
0,
|
| 231 |
+
0,
|
| 232 |
+
0,
|
| 233 |
+
0,
|
| 234 |
+
0,
|
| 235 |
+
0,
|
| 236 |
+
0,
|
| 237 |
+
0,
|
| 238 |
+
0,
|
| 239 |
+
0,
|
| 240 |
+
0,
|
| 241 |
+
0,
|
| 242 |
+
0,
|
| 243 |
+
0,
|
| 244 |
+
0,
|
| 245 |
+
0,
|
| 246 |
+
0,
|
| 247 |
+
0,
|
| 248 |
+
0,
|
| 249 |
+
0,
|
| 250 |
+
0,
|
| 251 |
+
0,
|
| 252 |
+
0,
|
| 253 |
+
0,
|
| 254 |
+
0,
|
| 255 |
+
0,
|
| 256 |
+
0,
|
| 257 |
+
0,
|
| 258 |
+
0,
|
| 259 |
+
0,
|
| 260 |
+
0,
|
| 261 |
+
0,
|
| 262 |
+
0,
|
| 263 |
+
0,
|
| 264 |
+
0,
|
| 265 |
+
0,
|
| 266 |
+
0,
|
| 267 |
+
0,
|
| 268 |
+
0,
|
| 269 |
+
0,
|
| 270 |
+
0,
|
| 271 |
+
0,
|
| 272 |
+
0,
|
| 273 |
+
0,
|
| 274 |
+
0,
|
| 275 |
+
0,
|
| 276 |
+
0,
|
| 277 |
+
0,
|
| 278 |
+
0,
|
| 279 |
+
0,
|
| 280 |
+
0,
|
| 281 |
+
0,
|
| 282 |
+
0,
|
| 283 |
+
0,
|
| 284 |
+
0,
|
| 285 |
+
0,
|
| 286 |
+
0,
|
| 287 |
+
0,
|
| 288 |
+
0,
|
| 289 |
+
0,
|
| 290 |
+
0,
|
| 291 |
+
0,
|
| 292 |
+
0,
|
| 293 |
+
0,
|
| 294 |
+
0,
|
| 295 |
+
0,
|
| 296 |
+
0,
|
| 297 |
+
0,
|
| 298 |
+
0,
|
| 299 |
+
0,
|
| 300 |
+
0,
|
| 301 |
+
0,
|
| 302 |
+
0,
|
| 303 |
+
0,
|
| 304 |
+
0,
|
| 305 |
+
0,
|
| 306 |
+
0,
|
| 307 |
+
0,
|
| 308 |
+
0,
|
| 309 |
+
0,
|
| 310 |
+
0,
|
| 311 |
+
0
|
| 312 |
+
],
|
| 313 |
+
"attention_mask": [
|
| 314 |
+
1,
|
| 315 |
+
1,
|
| 316 |
+
1,
|
| 317 |
+
1,
|
| 318 |
+
1,
|
| 319 |
+
1,
|
| 320 |
+
1,
|
| 321 |
+
1,
|
| 322 |
+
1,
|
| 323 |
+
1,
|
| 324 |
+
1,
|
| 325 |
+
1,
|
| 326 |
+
1,
|
| 327 |
+
1,
|
| 328 |
+
1,
|
| 329 |
+
1,
|
| 330 |
+
1,
|
| 331 |
+
1,
|
| 332 |
+
1,
|
| 333 |
+
1,
|
| 334 |
+
1,
|
| 335 |
+
1,
|
| 336 |
+
1,
|
| 337 |
+
1,
|
| 338 |
+
1,
|
| 339 |
+
1,
|
| 340 |
+
1,
|
| 341 |
+
1,
|
| 342 |
+
1,
|
| 343 |
+
1,
|
| 344 |
+
1,
|
| 345 |
+
1,
|
| 346 |
+
1,
|
| 347 |
+
1,
|
| 348 |
+
1,
|
| 349 |
+
1,
|
| 350 |
+
1,
|
| 351 |
+
1,
|
| 352 |
+
1,
|
| 353 |
+
1,
|
| 354 |
+
1,
|
| 355 |
+
1,
|
| 356 |
+
1,
|
| 357 |
+
1,
|
| 358 |
+
1,
|
| 359 |
+
1,
|
| 360 |
+
1,
|
| 361 |
+
1,
|
| 362 |
+
1,
|
| 363 |
+
0,
|
| 364 |
+
0,
|
| 365 |
+
0,
|
| 366 |
+
0,
|
| 367 |
+
0,
|
| 368 |
+
0,
|
| 369 |
+
0,
|
| 370 |
+
0,
|
| 371 |
+
0,
|
| 372 |
+
0,
|
| 373 |
+
0,
|
| 374 |
+
0,
|
| 375 |
+
0,
|
| 376 |
+
0,
|
| 377 |
+
0,
|
| 378 |
+
0,
|
| 379 |
+
0,
|
| 380 |
+
0,
|
| 381 |
+
0,
|
| 382 |
+
0,
|
| 383 |
+
0,
|
| 384 |
+
0,
|
| 385 |
+
0,
|
| 386 |
+
0,
|
| 387 |
+
0,
|
| 388 |
+
0,
|
| 389 |
+
0,
|
| 390 |
+
0,
|
| 391 |
+
0,
|
| 392 |
+
0,
|
| 393 |
+
0,
|
| 394 |
+
0,
|
| 395 |
+
0,
|
| 396 |
+
0,
|
| 397 |
+
0,
|
| 398 |
+
0,
|
| 399 |
+
0,
|
| 400 |
+
0,
|
| 401 |
+
0,
|
| 402 |
+
0,
|
| 403 |
+
0,
|
| 404 |
+
0,
|
| 405 |
+
0,
|
| 406 |
+
0,
|
| 407 |
+
0,
|
| 408 |
+
0,
|
| 409 |
+
0,
|
| 410 |
+
0,
|
| 411 |
+
0,
|
| 412 |
+
0,
|
| 413 |
+
0,
|
| 414 |
+
0,
|
| 415 |
+
0,
|
| 416 |
+
0,
|
| 417 |
+
0,
|
| 418 |
+
0,
|
| 419 |
+
0,
|
| 420 |
+
0,
|
| 421 |
+
0,
|
| 422 |
+
0,
|
| 423 |
+
0,
|
| 424 |
+
0,
|
| 425 |
+
0,
|
| 426 |
+
0,
|
| 427 |
+
0,
|
| 428 |
+
0,
|
| 429 |
+
0,
|
| 430 |
+
0,
|
| 431 |
+
0,
|
| 432 |
+
0,
|
| 433 |
+
0,
|
| 434 |
+
0,
|
| 435 |
+
0,
|
| 436 |
+
0,
|
| 437 |
+
0,
|
| 438 |
+
0,
|
| 439 |
+
0,
|
| 440 |
+
0,
|
| 441 |
+
0,
|
| 442 |
+
0,
|
| 443 |
+
0,
|
| 444 |
+
0,
|
| 445 |
+
0,
|
| 446 |
+
0,
|
| 447 |
+
0,
|
| 448 |
+
0,
|
| 449 |
+
0,
|
| 450 |
+
0,
|
| 451 |
+
0,
|
| 452 |
+
0,
|
| 453 |
+
0,
|
| 454 |
+
0,
|
| 455 |
+
0,
|
| 456 |
+
0,
|
| 457 |
+
0,
|
| 458 |
+
0,
|
| 459 |
+
0,
|
| 460 |
+
0,
|
| 461 |
+
0,
|
| 462 |
+
0,
|
| 463 |
+
0,
|
| 464 |
+
0,
|
| 465 |
+
0,
|
| 466 |
+
0,
|
| 467 |
+
0,
|
| 468 |
+
0,
|
| 469 |
+
0,
|
| 470 |
+
0,
|
| 471 |
+
0,
|
| 472 |
+
0,
|
| 473 |
+
0,
|
| 474 |
+
0,
|
| 475 |
+
0,
|
| 476 |
+
0,
|
| 477 |
+
0,
|
| 478 |
+
0,
|
| 479 |
+
0,
|
| 480 |
+
0,
|
| 481 |
+
0,
|
| 482 |
+
0,
|
| 483 |
+
0,
|
| 484 |
+
0,
|
| 485 |
+
0,
|
| 486 |
+
0,
|
| 487 |
+
0,
|
| 488 |
+
0,
|
| 489 |
+
0,
|
| 490 |
+
0,
|
| 491 |
+
0,
|
| 492 |
+
0,
|
| 493 |
+
0,
|
| 494 |
+
0,
|
| 495 |
+
0,
|
| 496 |
+
0,
|
| 497 |
+
0,
|
| 498 |
+
0,
|
| 499 |
+
0,
|
| 500 |
+
0,
|
| 501 |
+
0,
|
| 502 |
+
0,
|
| 503 |
+
0,
|
| 504 |
+
0,
|
| 505 |
+
0,
|
| 506 |
+
0,
|
| 507 |
+
0,
|
| 508 |
+
0,
|
| 509 |
+
0,
|
| 510 |
+
0,
|
| 511 |
+
0,
|
| 512 |
+
0,
|
| 513 |
+
0,
|
| 514 |
+
0,
|
| 515 |
+
0,
|
| 516 |
+
0,
|
| 517 |
+
0,
|
| 518 |
+
0,
|
| 519 |
+
0,
|
| 520 |
+
0,
|
| 521 |
+
0,
|
| 522 |
+
0,
|
| 523 |
+
0,
|
| 524 |
+
0,
|
| 525 |
+
0,
|
| 526 |
+
0,
|
| 527 |
+
0,
|
| 528 |
+
0,
|
| 529 |
+
0,
|
| 530 |
+
0,
|
| 531 |
+
0,
|
| 532 |
+
0,
|
| 533 |
+
0,
|
| 534 |
+
0,
|
| 535 |
+
0,
|
| 536 |
+
0,
|
| 537 |
+
0,
|
| 538 |
+
0,
|
| 539 |
+
0,
|
| 540 |
+
0,
|
| 541 |
+
0,
|
| 542 |
+
0,
|
| 543 |
+
0,
|
| 544 |
+
0,
|
| 545 |
+
0,
|
| 546 |
+
0,
|
| 547 |
+
0,
|
| 548 |
+
0,
|
| 549 |
+
0,
|
| 550 |
+
0,
|
| 551 |
+
0,
|
| 552 |
+
0,
|
| 553 |
+
0,
|
| 554 |
+
0,
|
| 555 |
+
0,
|
| 556 |
+
0,
|
| 557 |
+
0,
|
| 558 |
+
0,
|
| 559 |
+
0,
|
| 560 |
+
0,
|
| 561 |
+
0,
|
| 562 |
+
0,
|
| 563 |
+
0,
|
| 564 |
+
0,
|
| 565 |
+
0,
|
| 566 |
+
0,
|
| 567 |
+
0,
|
| 568 |
+
0,
|
| 569 |
+
0
|
| 570 |
+
],
|
| 571 |
+
"residue_ids": [
|
| 572 |
+
-1,
|
| 573 |
+
0,
|
| 574 |
+
0,
|
| 575 |
+
1,
|
| 576 |
+
1,
|
| 577 |
+
1,
|
| 578 |
+
2,
|
| 579 |
+
2,
|
| 580 |
+
2,
|
| 581 |
+
3,
|
| 582 |
+
3,
|
| 583 |
+
3,
|
| 584 |
+
4,
|
| 585 |
+
4,
|
| 586 |
+
4,
|
| 587 |
+
5,
|
| 588 |
+
5,
|
| 589 |
+
5,
|
| 590 |
+
6,
|
| 591 |
+
6,
|
| 592 |
+
6,
|
| 593 |
+
7,
|
| 594 |
+
7,
|
| 595 |
+
7,
|
| 596 |
+
8,
|
| 597 |
+
8,
|
| 598 |
+
8,
|
| 599 |
+
9,
|
| 600 |
+
9,
|
| 601 |
+
9,
|
| 602 |
+
-2,
|
| 603 |
+
-2,
|
| 604 |
+
-2,
|
| 605 |
+
-2,
|
| 606 |
+
-2,
|
| 607 |
+
-2,
|
| 608 |
+
-2,
|
| 609 |
+
-2,
|
| 610 |
+
-2,
|
| 611 |
+
-2,
|
| 612 |
+
-2,
|
| 613 |
+
-2,
|
| 614 |
+
-2,
|
| 615 |
+
-2,
|
| 616 |
+
-2,
|
| 617 |
+
-2,
|
| 618 |
+
-2,
|
| 619 |
+
-2,
|
| 620 |
+
-1,
|
| 621 |
+
-1,
|
| 622 |
+
-1,
|
| 623 |
+
-1,
|
| 624 |
+
-1,
|
| 625 |
+
-1,
|
| 626 |
+
-1,
|
| 627 |
+
-1,
|
| 628 |
+
-1,
|
| 629 |
+
-1,
|
| 630 |
+
-1,
|
| 631 |
+
-1,
|
| 632 |
+
-1,
|
| 633 |
+
-1,
|
| 634 |
+
-1,
|
| 635 |
+
-1,
|
| 636 |
+
-1,
|
| 637 |
+
-1,
|
| 638 |
+
-1,
|
| 639 |
+
-1,
|
| 640 |
+
-1,
|
| 641 |
+
-1,
|
| 642 |
+
-1,
|
| 643 |
+
-1,
|
| 644 |
+
-1,
|
| 645 |
+
-1,
|
| 646 |
+
-1,
|
| 647 |
+
-1,
|
| 648 |
+
-1,
|
| 649 |
+
-1,
|
| 650 |
+
-1,
|
| 651 |
+
-1,
|
| 652 |
+
-1,
|
| 653 |
+
-1,
|
| 654 |
+
-1,
|
| 655 |
+
-1,
|
| 656 |
+
-1,
|
| 657 |
+
-1,
|
| 658 |
+
-1,
|
| 659 |
+
-1,
|
| 660 |
+
-1,
|
| 661 |
+
-1,
|
| 662 |
+
-1,
|
| 663 |
+
-1,
|
| 664 |
+
-1,
|
| 665 |
+
-1,
|
| 666 |
+
-1,
|
| 667 |
+
-1,
|
| 668 |
+
-1,
|
| 669 |
+
-1,
|
| 670 |
+
-1,
|
| 671 |
+
-1,
|
| 672 |
+
-1,
|
| 673 |
+
-1,
|
| 674 |
+
-1,
|
| 675 |
+
-1,
|
| 676 |
+
-1,
|
| 677 |
+
-1,
|
| 678 |
+
-1,
|
| 679 |
+
-1,
|
| 680 |
+
-1,
|
| 681 |
+
-1,
|
| 682 |
+
-1,
|
| 683 |
+
-1,
|
| 684 |
+
-1,
|
| 685 |
+
-1,
|
| 686 |
+
-1,
|
| 687 |
+
-1,
|
| 688 |
+
-1,
|
| 689 |
+
-1,
|
| 690 |
+
-1,
|
| 691 |
+
-1,
|
| 692 |
+
-1,
|
| 693 |
+
-1,
|
| 694 |
+
-1,
|
| 695 |
+
-1,
|
| 696 |
+
-1,
|
| 697 |
+
-1,
|
| 698 |
+
-1,
|
| 699 |
+
-1,
|
| 700 |
+
-1,
|
| 701 |
+
-1,
|
| 702 |
+
-1,
|
| 703 |
+
-1,
|
| 704 |
+
-1,
|
| 705 |
+
-1,
|
| 706 |
+
-1,
|
| 707 |
+
-1,
|
| 708 |
+
-1,
|
| 709 |
+
-1,
|
| 710 |
+
-1,
|
| 711 |
+
-1,
|
| 712 |
+
-1,
|
| 713 |
+
-1,
|
| 714 |
+
-1,
|
| 715 |
+
-1,
|
| 716 |
+
-1,
|
| 717 |
+
-1,
|
| 718 |
+
-1,
|
| 719 |
+
-1,
|
| 720 |
+
-1,
|
| 721 |
+
-1,
|
| 722 |
+
-1,
|
| 723 |
+
-1,
|
| 724 |
+
-1,
|
| 725 |
+
-1,
|
| 726 |
+
-1,
|
| 727 |
+
-1,
|
| 728 |
+
-1,
|
| 729 |
+
-1,
|
| 730 |
+
-1,
|
| 731 |
+
-1,
|
| 732 |
+
-1,
|
| 733 |
+
-1,
|
| 734 |
+
-1,
|
| 735 |
+
-1,
|
| 736 |
+
-1,
|
| 737 |
+
-1,
|
| 738 |
+
-1,
|
| 739 |
+
-1,
|
| 740 |
+
-1,
|
| 741 |
+
-1,
|
| 742 |
+
-1,
|
| 743 |
+
-1,
|
| 744 |
+
-1,
|
| 745 |
+
-1,
|
| 746 |
+
-1,
|
| 747 |
+
-1,
|
| 748 |
+
-1,
|
| 749 |
+
-1,
|
| 750 |
+
-1,
|
| 751 |
+
-1,
|
| 752 |
+
-1,
|
| 753 |
+
-1,
|
| 754 |
+
-1,
|
| 755 |
+
-1,
|
| 756 |
+
-1,
|
| 757 |
+
-1,
|
| 758 |
+
-1,
|
| 759 |
+
-1,
|
| 760 |
+
-1,
|
| 761 |
+
-1,
|
| 762 |
+
-1,
|
| 763 |
+
-1,
|
| 764 |
+
-1,
|
| 765 |
+
-1,
|
| 766 |
+
-1,
|
| 767 |
+
-1,
|
| 768 |
+
-1,
|
| 769 |
+
-1,
|
| 770 |
+
-1,
|
| 771 |
+
-1,
|
| 772 |
+
-1,
|
| 773 |
+
-1,
|
| 774 |
+
-1,
|
| 775 |
+
-1,
|
| 776 |
+
-1,
|
| 777 |
+
-1,
|
| 778 |
+
-1,
|
| 779 |
+
-1,
|
| 780 |
+
-1,
|
| 781 |
+
-1,
|
| 782 |
+
-1,
|
| 783 |
+
-1,
|
| 784 |
+
-1,
|
| 785 |
+
-1,
|
| 786 |
+
-1,
|
| 787 |
+
-1,
|
| 788 |
+
-1,
|
| 789 |
+
-1,
|
| 790 |
+
-1,
|
| 791 |
+
-1,
|
| 792 |
+
-1,
|
| 793 |
+
-1,
|
| 794 |
+
-1,
|
| 795 |
+
-1,
|
| 796 |
+
-1,
|
| 797 |
+
-1,
|
| 798 |
+
-1,
|
| 799 |
+
-1,
|
| 800 |
+
-1,
|
| 801 |
+
-1,
|
| 802 |
+
-1,
|
| 803 |
+
-1,
|
| 804 |
+
-1,
|
| 805 |
+
-1,
|
| 806 |
+
-1,
|
| 807 |
+
-1,
|
| 808 |
+
-1,
|
| 809 |
+
-1,
|
| 810 |
+
-1,
|
| 811 |
+
-1,
|
| 812 |
+
-1,
|
| 813 |
+
-1,
|
| 814 |
+
-1,
|
| 815 |
+
-1,
|
| 816 |
+
-1,
|
| 817 |
+
-1,
|
| 818 |
+
-1,
|
| 819 |
+
-1,
|
| 820 |
+
-1,
|
| 821 |
+
-1,
|
| 822 |
+
-1,
|
| 823 |
+
-1,
|
| 824 |
+
-1,
|
| 825 |
+
-1,
|
| 826 |
+
-1,
|
| 827 |
+
-1
|
| 828 |
+
],
|
| 829 |
+
"branch_depths": [
|
| 830 |
+
0,
|
| 831 |
+
0,
|
| 832 |
+
0,
|
| 833 |
+
1,
|
| 834 |
+
1,
|
| 835 |
+
1,
|
| 836 |
+
2,
|
| 837 |
+
2,
|
| 838 |
+
2,
|
| 839 |
+
3,
|
| 840 |
+
3,
|
| 841 |
+
3,
|
| 842 |
+
4,
|
| 843 |
+
4,
|
| 844 |
+
4,
|
| 845 |
+
5,
|
| 846 |
+
5,
|
| 847 |
+
5,
|
| 848 |
+
6,
|
| 849 |
+
6,
|
| 850 |
+
6,
|
| 851 |
+
7,
|
| 852 |
+
7,
|
| 853 |
+
7,
|
| 854 |
+
8,
|
| 855 |
+
8,
|
| 856 |
+
8,
|
| 857 |
+
9,
|
| 858 |
+
9,
|
| 859 |
+
9,
|
| 860 |
+
0,
|
| 861 |
+
0,
|
| 862 |
+
0,
|
| 863 |
+
0,
|
| 864 |
+
0,
|
| 865 |
+
0,
|
| 866 |
+
0,
|
| 867 |
+
0,
|
| 868 |
+
0,
|
| 869 |
+
0,
|
| 870 |
+
0,
|
| 871 |
+
0,
|
| 872 |
+
0,
|
| 873 |
+
0,
|
| 874 |
+
0,
|
| 875 |
+
0,
|
| 876 |
+
0,
|
| 877 |
+
0,
|
| 878 |
+
0,
|
| 879 |
+
0,
|
| 880 |
+
0,
|
| 881 |
+
0,
|
| 882 |
+
0,
|
| 883 |
+
0,
|
| 884 |
+
0,
|
| 885 |
+
0,
|
| 886 |
+
0,
|
| 887 |
+
0,
|
| 888 |
+
0,
|
| 889 |
+
0,
|
| 890 |
+
0,
|
| 891 |
+
0,
|
| 892 |
+
0,
|
| 893 |
+
0,
|
| 894 |
+
0,
|
| 895 |
+
0,
|
| 896 |
+
0,
|
| 897 |
+
0,
|
| 898 |
+
0,
|
| 899 |
+
0,
|
| 900 |
+
0,
|
| 901 |
+
0,
|
| 902 |
+
0,
|
| 903 |
+
0,
|
| 904 |
+
0,
|
| 905 |
+
0,
|
| 906 |
+
0,
|
| 907 |
+
0,
|
| 908 |
+
0,
|
| 909 |
+
0,
|
| 910 |
+
0,
|
| 911 |
+
0,
|
| 912 |
+
0,
|
| 913 |
+
0,
|
| 914 |
+
0,
|
| 915 |
+
0,
|
| 916 |
+
0,
|
| 917 |
+
0,
|
| 918 |
+
0,
|
| 919 |
+
0,
|
| 920 |
+
0,
|
| 921 |
+
0,
|
| 922 |
+
0,
|
| 923 |
+
0,
|
| 924 |
+
0,
|
| 925 |
+
0,
|
| 926 |
+
0,
|
| 927 |
+
0,
|
| 928 |
+
0,
|
| 929 |
+
0,
|
| 930 |
+
0,
|
| 931 |
+
0,
|
| 932 |
+
0,
|
| 933 |
+
0,
|
| 934 |
+
0,
|
| 935 |
+
0,
|
| 936 |
+
0,
|
| 937 |
+
0,
|
| 938 |
+
0,
|
| 939 |
+
0,
|
| 940 |
+
0,
|
| 941 |
+
0,
|
| 942 |
+
0,
|
| 943 |
+
0,
|
| 944 |
+
0,
|
| 945 |
+
0,
|
| 946 |
+
0,
|
| 947 |
+
0,
|
| 948 |
+
0,
|
| 949 |
+
0,
|
| 950 |
+
0,
|
| 951 |
+
0,
|
| 952 |
+
0,
|
| 953 |
+
0,
|
| 954 |
+
0,
|
| 955 |
+
0,
|
| 956 |
+
0,
|
| 957 |
+
0,
|
| 958 |
+
0,
|
| 959 |
+
0,
|
| 960 |
+
0,
|
| 961 |
+
0,
|
| 962 |
+
0,
|
| 963 |
+
0,
|
| 964 |
+
0,
|
| 965 |
+
0,
|
| 966 |
+
0,
|
| 967 |
+
0,
|
| 968 |
+
0,
|
| 969 |
+
0,
|
| 970 |
+
0,
|
| 971 |
+
0,
|
| 972 |
+
0,
|
| 973 |
+
0,
|
| 974 |
+
0,
|
| 975 |
+
0,
|
| 976 |
+
0,
|
| 977 |
+
0,
|
| 978 |
+
0,
|
| 979 |
+
0,
|
| 980 |
+
0,
|
| 981 |
+
0,
|
| 982 |
+
0,
|
| 983 |
+
0,
|
| 984 |
+
0,
|
| 985 |
+
0,
|
| 986 |
+
0,
|
| 987 |
+
0,
|
| 988 |
+
0,
|
| 989 |
+
0,
|
| 990 |
+
0,
|
| 991 |
+
0,
|
| 992 |
+
0,
|
| 993 |
+
0,
|
| 994 |
+
0,
|
| 995 |
+
0,
|
| 996 |
+
0,
|
| 997 |
+
0,
|
| 998 |
+
0,
|
| 999 |
+
0,
|
| 1000 |
+
0,
|
| 1001 |
+
0,
|
| 1002 |
+
0,
|
| 1003 |
+
0,
|
| 1004 |
+
0,
|
| 1005 |
+
0,
|
| 1006 |
+
0,
|
| 1007 |
+
0,
|
| 1008 |
+
0,
|
| 1009 |
+
0,
|
| 1010 |
+
0,
|
| 1011 |
+
0,
|
| 1012 |
+
0,
|
| 1013 |
+
0,
|
| 1014 |
+
0,
|
| 1015 |
+
0,
|
| 1016 |
+
0,
|
| 1017 |
+
0,
|
| 1018 |
+
0,
|
| 1019 |
+
0,
|
| 1020 |
+
0,
|
| 1021 |
+
0,
|
| 1022 |
+
0,
|
| 1023 |
+
0,
|
| 1024 |
+
0,
|
| 1025 |
+
0,
|
| 1026 |
+
0,
|
| 1027 |
+
0,
|
| 1028 |
+
0,
|
| 1029 |
+
0,
|
| 1030 |
+
0,
|
| 1031 |
+
0,
|
| 1032 |
+
0,
|
| 1033 |
+
0,
|
| 1034 |
+
0,
|
| 1035 |
+
0,
|
| 1036 |
+
0,
|
| 1037 |
+
0,
|
| 1038 |
+
0,
|
| 1039 |
+
0,
|
| 1040 |
+
0,
|
| 1041 |
+
0,
|
| 1042 |
+
0,
|
| 1043 |
+
0,
|
| 1044 |
+
0,
|
| 1045 |
+
0,
|
| 1046 |
+
0,
|
| 1047 |
+
0,
|
| 1048 |
+
0,
|
| 1049 |
+
0,
|
| 1050 |
+
0,
|
| 1051 |
+
0,
|
| 1052 |
+
0,
|
| 1053 |
+
0,
|
| 1054 |
+
0,
|
| 1055 |
+
0,
|
| 1056 |
+
0,
|
| 1057 |
+
0,
|
| 1058 |
+
0,
|
| 1059 |
+
0,
|
| 1060 |
+
0,
|
| 1061 |
+
0,
|
| 1062 |
+
0,
|
| 1063 |
+
0,
|
| 1064 |
+
0,
|
| 1065 |
+
0,
|
| 1066 |
+
0,
|
| 1067 |
+
0,
|
| 1068 |
+
0,
|
| 1069 |
+
0,
|
| 1070 |
+
0,
|
| 1071 |
+
0,
|
| 1072 |
+
0,
|
| 1073 |
+
0,
|
| 1074 |
+
0,
|
| 1075 |
+
0,
|
| 1076 |
+
0,
|
| 1077 |
+
0,
|
| 1078 |
+
0,
|
| 1079 |
+
0,
|
| 1080 |
+
0,
|
| 1081 |
+
0,
|
| 1082 |
+
0,
|
| 1083 |
+
0,
|
| 1084 |
+
0,
|
| 1085 |
+
0
|
| 1086 |
+
],
|
| 1087 |
+
"linkage_types": [
|
| 1088 |
+
0,
|
| 1089 |
+
0,
|
| 1090 |
+
0,
|
| 1091 |
+
0,
|
| 1092 |
+
0,
|
| 1093 |
+
0,
|
| 1094 |
+
0,
|
| 1095 |
+
0,
|
| 1096 |
+
0,
|
| 1097 |
+
0,
|
| 1098 |
+
0,
|
| 1099 |
+
0,
|
| 1100 |
+
0,
|
| 1101 |
+
0,
|
| 1102 |
+
0,
|
| 1103 |
+
0,
|
| 1104 |
+
0,
|
| 1105 |
+
0,
|
| 1106 |
+
0,
|
| 1107 |
+
0,
|
| 1108 |
+
0,
|
| 1109 |
+
0,
|
| 1110 |
+
0,
|
| 1111 |
+
0,
|
| 1112 |
+
0,
|
| 1113 |
+
0,
|
| 1114 |
+
0,
|
| 1115 |
+
0,
|
| 1116 |
+
0,
|
| 1117 |
+
0,
|
| 1118 |
+
8,
|
| 1119 |
+
8,
|
| 1120 |
+
8,
|
| 1121 |
+
8,
|
| 1122 |
+
8,
|
| 1123 |
+
8,
|
| 1124 |
+
8,
|
| 1125 |
+
8,
|
| 1126 |
+
8,
|
| 1127 |
+
8,
|
| 1128 |
+
8,
|
| 1129 |
+
8,
|
| 1130 |
+
8,
|
| 1131 |
+
8,
|
| 1132 |
+
8,
|
| 1133 |
+
8,
|
| 1134 |
+
8,
|
| 1135 |
+
8,
|
| 1136 |
+
0,
|
| 1137 |
+
0,
|
| 1138 |
+
0,
|
| 1139 |
+
0,
|
| 1140 |
+
0,
|
| 1141 |
+
0,
|
| 1142 |
+
0,
|
| 1143 |
+
0,
|
| 1144 |
+
0,
|
| 1145 |
+
0,
|
| 1146 |
+
0,
|
| 1147 |
+
0,
|
| 1148 |
+
0,
|
| 1149 |
+
0,
|
| 1150 |
+
0,
|
| 1151 |
+
0,
|
| 1152 |
+
0,
|
| 1153 |
+
0,
|
| 1154 |
+
0,
|
| 1155 |
+
0,
|
| 1156 |
+
0,
|
| 1157 |
+
0,
|
| 1158 |
+
0,
|
| 1159 |
+
0,
|
| 1160 |
+
0,
|
| 1161 |
+
0,
|
| 1162 |
+
0,
|
| 1163 |
+
0,
|
| 1164 |
+
0,
|
| 1165 |
+
0,
|
| 1166 |
+
0,
|
| 1167 |
+
0,
|
| 1168 |
+
0,
|
| 1169 |
+
0,
|
| 1170 |
+
0,
|
| 1171 |
+
0,
|
| 1172 |
+
0,
|
| 1173 |
+
0,
|
| 1174 |
+
0,
|
| 1175 |
+
0,
|
| 1176 |
+
0,
|
| 1177 |
+
0,
|
| 1178 |
+
0,
|
| 1179 |
+
0,
|
| 1180 |
+
0,
|
| 1181 |
+
0,
|
| 1182 |
+
0,
|
| 1183 |
+
0,
|
| 1184 |
+
0,
|
| 1185 |
+
0,
|
| 1186 |
+
0,
|
| 1187 |
+
0,
|
| 1188 |
+
0,
|
| 1189 |
+
0,
|
| 1190 |
+
0,
|
| 1191 |
+
0,
|
| 1192 |
+
0,
|
| 1193 |
+
0,
|
| 1194 |
+
0,
|
| 1195 |
+
0,
|
| 1196 |
+
0,
|
| 1197 |
+
0,
|
| 1198 |
+
0,
|
| 1199 |
+
0,
|
| 1200 |
+
0,
|
| 1201 |
+
0,
|
| 1202 |
+
0,
|
| 1203 |
+
0,
|
| 1204 |
+
0,
|
| 1205 |
+
0,
|
| 1206 |
+
0,
|
| 1207 |
+
0,
|
| 1208 |
+
0,
|
| 1209 |
+
0,
|
| 1210 |
+
0,
|
| 1211 |
+
0,
|
| 1212 |
+
0,
|
| 1213 |
+
0,
|
| 1214 |
+
0,
|
| 1215 |
+
0,
|
| 1216 |
+
0,
|
| 1217 |
+
0,
|
| 1218 |
+
0,
|
| 1219 |
+
0,
|
| 1220 |
+
0,
|
| 1221 |
+
0,
|
| 1222 |
+
0,
|
| 1223 |
+
0,
|
| 1224 |
+
0,
|
| 1225 |
+
0,
|
| 1226 |
+
0,
|
| 1227 |
+
0,
|
| 1228 |
+
0,
|
| 1229 |
+
0,
|
| 1230 |
+
0,
|
| 1231 |
+
0,
|
| 1232 |
+
0,
|
| 1233 |
+
0,
|
| 1234 |
+
0,
|
| 1235 |
+
0,
|
| 1236 |
+
0,
|
| 1237 |
+
0,
|
| 1238 |
+
0,
|
| 1239 |
+
0,
|
| 1240 |
+
0,
|
| 1241 |
+
0,
|
| 1242 |
+
0,
|
| 1243 |
+
0,
|
| 1244 |
+
0,
|
| 1245 |
+
0,
|
| 1246 |
+
0,
|
| 1247 |
+
0,
|
| 1248 |
+
0,
|
| 1249 |
+
0,
|
| 1250 |
+
0,
|
| 1251 |
+
0,
|
| 1252 |
+
0,
|
| 1253 |
+
0,
|
| 1254 |
+
0,
|
| 1255 |
+
0,
|
| 1256 |
+
0,
|
| 1257 |
+
0,
|
| 1258 |
+
0,
|
| 1259 |
+
0,
|
| 1260 |
+
0,
|
| 1261 |
+
0,
|
| 1262 |
+
0,
|
| 1263 |
+
0,
|
| 1264 |
+
0,
|
| 1265 |
+
0,
|
| 1266 |
+
0,
|
| 1267 |
+
0,
|
| 1268 |
+
0,
|
| 1269 |
+
0,
|
| 1270 |
+
0,
|
| 1271 |
+
0,
|
| 1272 |
+
0,
|
| 1273 |
+
0,
|
| 1274 |
+
0,
|
| 1275 |
+
0,
|
| 1276 |
+
0,
|
| 1277 |
+
0,
|
| 1278 |
+
0,
|
| 1279 |
+
0,
|
| 1280 |
+
0,
|
| 1281 |
+
0,
|
| 1282 |
+
0,
|
| 1283 |
+
0,
|
| 1284 |
+
0,
|
| 1285 |
+
0,
|
| 1286 |
+
0,
|
| 1287 |
+
0,
|
| 1288 |
+
0,
|
| 1289 |
+
0,
|
| 1290 |
+
0,
|
| 1291 |
+
0,
|
| 1292 |
+
0,
|
| 1293 |
+
0,
|
| 1294 |
+
0,
|
| 1295 |
+
0,
|
| 1296 |
+
0,
|
| 1297 |
+
0,
|
| 1298 |
+
0,
|
| 1299 |
+
0,
|
| 1300 |
+
0,
|
| 1301 |
+
0,
|
| 1302 |
+
0,
|
| 1303 |
+
0,
|
| 1304 |
+
0,
|
| 1305 |
+
0,
|
| 1306 |
+
0,
|
| 1307 |
+
0,
|
| 1308 |
+
0,
|
| 1309 |
+
0,
|
| 1310 |
+
0,
|
| 1311 |
+
0,
|
| 1312 |
+
0,
|
| 1313 |
+
0,
|
| 1314 |
+
0,
|
| 1315 |
+
0,
|
| 1316 |
+
0,
|
| 1317 |
+
0,
|
| 1318 |
+
0,
|
| 1319 |
+
0,
|
| 1320 |
+
0,
|
| 1321 |
+
0,
|
| 1322 |
+
0,
|
| 1323 |
+
0,
|
| 1324 |
+
0,
|
| 1325 |
+
0,
|
| 1326 |
+
0,
|
| 1327 |
+
0,
|
| 1328 |
+
0,
|
| 1329 |
+
0,
|
| 1330 |
+
0,
|
| 1331 |
+
0,
|
| 1332 |
+
0,
|
| 1333 |
+
0,
|
| 1334 |
+
0,
|
| 1335 |
+
0,
|
| 1336 |
+
0,
|
| 1337 |
+
0,
|
| 1338 |
+
0,
|
| 1339 |
+
0,
|
| 1340 |
+
0,
|
| 1341 |
+
0,
|
| 1342 |
+
0,
|
| 1343 |
+
0
|
| 1344 |
+
],
|
| 1345 |
+
"branch_depths_blank": [
|
| 1346 |
+
0,
|
| 1347 |
+
0,
|
| 1348 |
+
0,
|
| 1349 |
+
1,
|
| 1350 |
+
1,
|
| 1351 |
+
1,
|
| 1352 |
+
2,
|
| 1353 |
+
2,
|
| 1354 |
+
2,
|
| 1355 |
+
3,
|
| 1356 |
+
3,
|
| 1357 |
+
3,
|
| 1358 |
+
4,
|
| 1359 |
+
4,
|
| 1360 |
+
4,
|
| 1361 |
+
5,
|
| 1362 |
+
5,
|
| 1363 |
+
5,
|
| 1364 |
+
6,
|
| 1365 |
+
6,
|
| 1366 |
+
6,
|
| 1367 |
+
7,
|
| 1368 |
+
7,
|
| 1369 |
+
7,
|
| 1370 |
+
8,
|
| 1371 |
+
8,
|
| 1372 |
+
8,
|
| 1373 |
+
9,
|
| 1374 |
+
9,
|
| 1375 |
+
9,
|
| 1376 |
+
0,
|
| 1377 |
+
0,
|
| 1378 |
+
0,
|
| 1379 |
+
0,
|
| 1380 |
+
0,
|
| 1381 |
+
0,
|
| 1382 |
+
0,
|
| 1383 |
+
0,
|
| 1384 |
+
0,
|
| 1385 |
+
0,
|
| 1386 |
+
0,
|
| 1387 |
+
0,
|
| 1388 |
+
0,
|
| 1389 |
+
0,
|
| 1390 |
+
0,
|
| 1391 |
+
0,
|
| 1392 |
+
0,
|
| 1393 |
+
0,
|
| 1394 |
+
0,
|
| 1395 |
+
0,
|
| 1396 |
+
0,
|
| 1397 |
+
0,
|
| 1398 |
+
0,
|
| 1399 |
+
0,
|
| 1400 |
+
0,
|
| 1401 |
+
0,
|
| 1402 |
+
0,
|
| 1403 |
+
0,
|
| 1404 |
+
0,
|
| 1405 |
+
0,
|
| 1406 |
+
0,
|
| 1407 |
+
0,
|
| 1408 |
+
0,
|
| 1409 |
+
0,
|
| 1410 |
+
0,
|
| 1411 |
+
0,
|
| 1412 |
+
0,
|
| 1413 |
+
0,
|
| 1414 |
+
0,
|
| 1415 |
+
0,
|
| 1416 |
+
0,
|
| 1417 |
+
0,
|
| 1418 |
+
0,
|
| 1419 |
+
0,
|
| 1420 |
+
0,
|
| 1421 |
+
0,
|
| 1422 |
+
0,
|
| 1423 |
+
0,
|
| 1424 |
+
0,
|
| 1425 |
+
0,
|
| 1426 |
+
0,
|
| 1427 |
+
0,
|
| 1428 |
+
0,
|
| 1429 |
+
0,
|
| 1430 |
+
0,
|
| 1431 |
+
0,
|
| 1432 |
+
0,
|
| 1433 |
+
0,
|
| 1434 |
+
0,
|
| 1435 |
+
0,
|
| 1436 |
+
0,
|
| 1437 |
+
0,
|
| 1438 |
+
0,
|
| 1439 |
+
0,
|
| 1440 |
+
0,
|
| 1441 |
+
0,
|
| 1442 |
+
0,
|
| 1443 |
+
0,
|
| 1444 |
+
0,
|
| 1445 |
+
0,
|
| 1446 |
+
0,
|
| 1447 |
+
0,
|
| 1448 |
+
0,
|
| 1449 |
+
0,
|
| 1450 |
+
0,
|
| 1451 |
+
0,
|
| 1452 |
+
0,
|
| 1453 |
+
0,
|
| 1454 |
+
0,
|
| 1455 |
+
0,
|
| 1456 |
+
0,
|
| 1457 |
+
0,
|
| 1458 |
+
0,
|
| 1459 |
+
0,
|
| 1460 |
+
0,
|
| 1461 |
+
0,
|
| 1462 |
+
0,
|
| 1463 |
+
0,
|
| 1464 |
+
0,
|
| 1465 |
+
0,
|
| 1466 |
+
0,
|
| 1467 |
+
0,
|
| 1468 |
+
0,
|
| 1469 |
+
0,
|
| 1470 |
+
0,
|
| 1471 |
+
0,
|
| 1472 |
+
0,
|
| 1473 |
+
0,
|
| 1474 |
+
0,
|
| 1475 |
+
0,
|
| 1476 |
+
0,
|
| 1477 |
+
0,
|
| 1478 |
+
0,
|
| 1479 |
+
0,
|
| 1480 |
+
0,
|
| 1481 |
+
0,
|
| 1482 |
+
0,
|
| 1483 |
+
0,
|
| 1484 |
+
0,
|
| 1485 |
+
0,
|
| 1486 |
+
0,
|
| 1487 |
+
0,
|
| 1488 |
+
0,
|
| 1489 |
+
0,
|
| 1490 |
+
0,
|
| 1491 |
+
0,
|
| 1492 |
+
0,
|
| 1493 |
+
0,
|
| 1494 |
+
0,
|
| 1495 |
+
0,
|
| 1496 |
+
0,
|
| 1497 |
+
0,
|
| 1498 |
+
0,
|
| 1499 |
+
0,
|
| 1500 |
+
0,
|
| 1501 |
+
0,
|
| 1502 |
+
0,
|
| 1503 |
+
0,
|
| 1504 |
+
0,
|
| 1505 |
+
0,
|
| 1506 |
+
0,
|
| 1507 |
+
0,
|
| 1508 |
+
0,
|
| 1509 |
+
0,
|
| 1510 |
+
0,
|
| 1511 |
+
0,
|
| 1512 |
+
0,
|
| 1513 |
+
0,
|
| 1514 |
+
0,
|
| 1515 |
+
0,
|
| 1516 |
+
0,
|
| 1517 |
+
0,
|
| 1518 |
+
0,
|
| 1519 |
+
0,
|
| 1520 |
+
0,
|
| 1521 |
+
0,
|
| 1522 |
+
0,
|
| 1523 |
+
0,
|
| 1524 |
+
0,
|
| 1525 |
+
0,
|
| 1526 |
+
0,
|
| 1527 |
+
0,
|
| 1528 |
+
0,
|
| 1529 |
+
0,
|
| 1530 |
+
0,
|
| 1531 |
+
0,
|
| 1532 |
+
0,
|
| 1533 |
+
0,
|
| 1534 |
+
0,
|
| 1535 |
+
0,
|
| 1536 |
+
0,
|
| 1537 |
+
0,
|
| 1538 |
+
0,
|
| 1539 |
+
0,
|
| 1540 |
+
0,
|
| 1541 |
+
0,
|
| 1542 |
+
0,
|
| 1543 |
+
0,
|
| 1544 |
+
0,
|
| 1545 |
+
0,
|
| 1546 |
+
0,
|
| 1547 |
+
0,
|
| 1548 |
+
0,
|
| 1549 |
+
0,
|
| 1550 |
+
0,
|
| 1551 |
+
0,
|
| 1552 |
+
0,
|
| 1553 |
+
0,
|
| 1554 |
+
0,
|
| 1555 |
+
0,
|
| 1556 |
+
0,
|
| 1557 |
+
0,
|
| 1558 |
+
0,
|
| 1559 |
+
0,
|
| 1560 |
+
0,
|
| 1561 |
+
0,
|
| 1562 |
+
0,
|
| 1563 |
+
0,
|
| 1564 |
+
0,
|
| 1565 |
+
0,
|
| 1566 |
+
0,
|
| 1567 |
+
0,
|
| 1568 |
+
0,
|
| 1569 |
+
0,
|
| 1570 |
+
0,
|
| 1571 |
+
0,
|
| 1572 |
+
0,
|
| 1573 |
+
0,
|
| 1574 |
+
0,
|
| 1575 |
+
0,
|
| 1576 |
+
0,
|
| 1577 |
+
0,
|
| 1578 |
+
0,
|
| 1579 |
+
0,
|
| 1580 |
+
0,
|
| 1581 |
+
0,
|
| 1582 |
+
0,
|
| 1583 |
+
0,
|
| 1584 |
+
0,
|
| 1585 |
+
0,
|
| 1586 |
+
0,
|
| 1587 |
+
0,
|
| 1588 |
+
0,
|
| 1589 |
+
0,
|
| 1590 |
+
0,
|
| 1591 |
+
0,
|
| 1592 |
+
0,
|
| 1593 |
+
0,
|
| 1594 |
+
0,
|
| 1595 |
+
0,
|
| 1596 |
+
0,
|
| 1597 |
+
0,
|
| 1598 |
+
0,
|
| 1599 |
+
0,
|
| 1600 |
+
0,
|
| 1601 |
+
0
|
| 1602 |
+
],
|
| 1603 |
+
"linkage_types_blank": [
|
| 1604 |
+
0,
|
| 1605 |
+
0,
|
| 1606 |
+
0,
|
| 1607 |
+
0,
|
| 1608 |
+
0,
|
| 1609 |
+
0,
|
| 1610 |
+
0,
|
| 1611 |
+
0,
|
| 1612 |
+
0,
|
| 1613 |
+
0,
|
| 1614 |
+
0,
|
| 1615 |
+
0,
|
| 1616 |
+
0,
|
| 1617 |
+
0,
|
| 1618 |
+
0,
|
| 1619 |
+
0,
|
| 1620 |
+
0,
|
| 1621 |
+
0,
|
| 1622 |
+
0,
|
| 1623 |
+
0,
|
| 1624 |
+
0,
|
| 1625 |
+
0,
|
| 1626 |
+
0,
|
| 1627 |
+
0,
|
| 1628 |
+
0,
|
| 1629 |
+
0,
|
| 1630 |
+
0,
|
| 1631 |
+
0,
|
| 1632 |
+
0,
|
| 1633 |
+
0,
|
| 1634 |
+
8,
|
| 1635 |
+
8,
|
| 1636 |
+
8,
|
| 1637 |
+
8,
|
| 1638 |
+
8,
|
| 1639 |
+
8,
|
| 1640 |
+
8,
|
| 1641 |
+
8,
|
| 1642 |
+
8,
|
| 1643 |
+
8,
|
| 1644 |
+
8,
|
| 1645 |
+
8,
|
| 1646 |
+
8,
|
| 1647 |
+
9,
|
| 1648 |
+
8,
|
| 1649 |
+
8,
|
| 1650 |
+
8,
|
| 1651 |
+
8,
|
| 1652 |
+
0,
|
| 1653 |
+
0,
|
| 1654 |
+
0,
|
| 1655 |
+
0,
|
| 1656 |
+
0,
|
| 1657 |
+
0,
|
| 1658 |
+
0,
|
| 1659 |
+
0,
|
| 1660 |
+
0,
|
| 1661 |
+
0,
|
| 1662 |
+
0,
|
| 1663 |
+
0,
|
| 1664 |
+
0,
|
| 1665 |
+
0,
|
| 1666 |
+
0,
|
| 1667 |
+
0,
|
| 1668 |
+
0,
|
| 1669 |
+
0,
|
| 1670 |
+
0,
|
| 1671 |
+
0,
|
| 1672 |
+
0,
|
| 1673 |
+
0,
|
| 1674 |
+
0,
|
| 1675 |
+
0,
|
| 1676 |
+
0,
|
| 1677 |
+
0,
|
| 1678 |
+
0,
|
| 1679 |
+
0,
|
| 1680 |
+
0,
|
| 1681 |
+
0,
|
| 1682 |
+
0,
|
| 1683 |
+
0,
|
| 1684 |
+
0,
|
| 1685 |
+
0,
|
| 1686 |
+
0,
|
| 1687 |
+
0,
|
| 1688 |
+
0,
|
| 1689 |
+
0,
|
| 1690 |
+
0,
|
| 1691 |
+
0,
|
| 1692 |
+
0,
|
| 1693 |
+
0,
|
| 1694 |
+
0,
|
| 1695 |
+
0,
|
| 1696 |
+
0,
|
| 1697 |
+
0,
|
| 1698 |
+
0,
|
| 1699 |
+
0,
|
| 1700 |
+
0,
|
| 1701 |
+
0,
|
| 1702 |
+
0,
|
| 1703 |
+
0,
|
| 1704 |
+
0,
|
| 1705 |
+
0,
|
| 1706 |
+
0,
|
| 1707 |
+
0,
|
| 1708 |
+
0,
|
| 1709 |
+
0,
|
| 1710 |
+
0,
|
| 1711 |
+
0,
|
| 1712 |
+
0,
|
| 1713 |
+
0,
|
| 1714 |
+
0,
|
| 1715 |
+
0,
|
| 1716 |
+
0,
|
| 1717 |
+
0,
|
| 1718 |
+
0,
|
| 1719 |
+
0,
|
| 1720 |
+
0,
|
| 1721 |
+
0,
|
| 1722 |
+
0,
|
| 1723 |
+
0,
|
| 1724 |
+
0,
|
| 1725 |
+
0,
|
| 1726 |
+
0,
|
| 1727 |
+
0,
|
| 1728 |
+
0,
|
| 1729 |
+
0,
|
| 1730 |
+
0,
|
| 1731 |
+
0,
|
| 1732 |
+
0,
|
| 1733 |
+
0,
|
| 1734 |
+
0,
|
| 1735 |
+
0,
|
| 1736 |
+
0,
|
| 1737 |
+
0,
|
| 1738 |
+
0,
|
| 1739 |
+
0,
|
| 1740 |
+
0,
|
| 1741 |
+
0,
|
| 1742 |
+
0,
|
| 1743 |
+
0,
|
| 1744 |
+
0,
|
| 1745 |
+
0,
|
| 1746 |
+
0,
|
| 1747 |
+
0,
|
| 1748 |
+
0,
|
| 1749 |
+
0,
|
| 1750 |
+
0,
|
| 1751 |
+
0,
|
| 1752 |
+
0,
|
| 1753 |
+
0,
|
| 1754 |
+
0,
|
| 1755 |
+
0,
|
| 1756 |
+
0,
|
| 1757 |
+
0,
|
| 1758 |
+
0,
|
| 1759 |
+
0,
|
| 1760 |
+
0,
|
| 1761 |
+
0,
|
| 1762 |
+
0,
|
| 1763 |
+
0,
|
| 1764 |
+
0,
|
| 1765 |
+
0,
|
| 1766 |
+
0,
|
| 1767 |
+
0,
|
| 1768 |
+
0,
|
| 1769 |
+
0,
|
| 1770 |
+
0,
|
| 1771 |
+
0,
|
| 1772 |
+
0,
|
| 1773 |
+
0,
|
| 1774 |
+
0,
|
| 1775 |
+
0,
|
| 1776 |
+
0,
|
| 1777 |
+
0,
|
| 1778 |
+
0,
|
| 1779 |
+
0,
|
| 1780 |
+
0,
|
| 1781 |
+
0,
|
| 1782 |
+
0,
|
| 1783 |
+
0,
|
| 1784 |
+
0,
|
| 1785 |
+
0,
|
| 1786 |
+
0,
|
| 1787 |
+
0,
|
| 1788 |
+
0,
|
| 1789 |
+
0,
|
| 1790 |
+
0,
|
| 1791 |
+
0,
|
| 1792 |
+
0,
|
| 1793 |
+
0,
|
| 1794 |
+
0,
|
| 1795 |
+
0,
|
| 1796 |
+
0,
|
| 1797 |
+
0,
|
| 1798 |
+
0,
|
| 1799 |
+
0,
|
| 1800 |
+
0,
|
| 1801 |
+
0,
|
| 1802 |
+
0,
|
| 1803 |
+
0,
|
| 1804 |
+
0,
|
| 1805 |
+
0,
|
| 1806 |
+
0,
|
| 1807 |
+
0,
|
| 1808 |
+
0,
|
| 1809 |
+
0,
|
| 1810 |
+
0,
|
| 1811 |
+
0,
|
| 1812 |
+
0,
|
| 1813 |
+
0,
|
| 1814 |
+
0,
|
| 1815 |
+
0,
|
| 1816 |
+
0,
|
| 1817 |
+
0,
|
| 1818 |
+
0,
|
| 1819 |
+
0,
|
| 1820 |
+
0,
|
| 1821 |
+
0,
|
| 1822 |
+
0,
|
| 1823 |
+
0,
|
| 1824 |
+
0,
|
| 1825 |
+
0,
|
| 1826 |
+
0,
|
| 1827 |
+
0,
|
| 1828 |
+
0,
|
| 1829 |
+
0,
|
| 1830 |
+
0,
|
| 1831 |
+
0,
|
| 1832 |
+
0,
|
| 1833 |
+
0,
|
| 1834 |
+
0,
|
| 1835 |
+
0,
|
| 1836 |
+
0,
|
| 1837 |
+
0,
|
| 1838 |
+
0,
|
| 1839 |
+
0,
|
| 1840 |
+
0,
|
| 1841 |
+
0,
|
| 1842 |
+
0,
|
| 1843 |
+
0,
|
| 1844 |
+
0,
|
| 1845 |
+
0,
|
| 1846 |
+
0,
|
| 1847 |
+
0,
|
| 1848 |
+
0,
|
| 1849 |
+
0,
|
| 1850 |
+
0,
|
| 1851 |
+
0,
|
| 1852 |
+
0,
|
| 1853 |
+
0,
|
| 1854 |
+
0,
|
| 1855 |
+
0,
|
| 1856 |
+
0,
|
| 1857 |
+
0,
|
| 1858 |
+
0,
|
| 1859 |
+
0
|
| 1860 |
+
],
|
| 1861 |
+
"enumerated_alternative": false,
|
| 1862 |
+
"unknown_question_mark": false,
|
| 1863 |
+
"wa3_truth_uses_invalid_token": false,
|
| 1864 |
+
"single_answer": true
|
| 1865 |
+
}
|
| 1866 |
+
},
|
| 1867 |
+
{
|
| 1868 |
+
"dataset": "seal162",
|
| 1869 |
+
"source_case_id": "g0000_s00_linkage_9_9",
|
| 1870 |
+
"recorded_source_sha256": "86b08c4b8c5081ee90eef3401ae5b0a09595c301f6c79f3d892521b3ea3e33d1",
|
| 1871 |
+
"official_helper": {
|
| 1872 |
+
"rooted": true,
|
| 1873 |
+
"depths": [
|
| 1874 |
+
0,
|
| 1875 |
+
1,
|
| 1876 |
+
2
|
| 1877 |
+
],
|
| 1878 |
+
"parents": [
|
| 1879 |
+
-1,
|
| 1880 |
+
0,
|
| 1881 |
+
1
|
| 1882 |
+
],
|
| 1883 |
+
"helper_error": false
|
| 1884 |
+
},
|
| 1885 |
+
"rebuilt_case": {
|
| 1886 |
+
"case_id": "g0000_s00_linkage_9_9",
|
| 1887 |
+
"glycan_index": 0,
|
| 1888 |
+
"wurcs": "WURCS=2.0/3,3,2/[h2122h_2*NCC/3=O][a2112h-1b_1-5][a2122h-1b_1-5_2*NCC/3=O_6*OSO/3=O/3=O]/1-2-3/a4-b1_b3-c1",
|
| 1889 |
+
"mask_plan": "linkage:1",
|
| 1890 |
+
"units": [
|
| 1891 |
+
{
|
| 1892 |
+
"g": 8,
|
| 1893 |
+
"unit_type": "linkage",
|
| 1894 |
+
"unit_text": "a4-b1"
|
| 1895 |
+
}
|
| 1896 |
+
],
|
| 1897 |
+
"wa0_iterative_span_exact": true,
|
| 1898 |
+
"wa0_initial_span_exact_top1": true,
|
| 1899 |
+
"unit_text": "linkage:a4-b1",
|
| 1900 |
+
"positions": [
|
| 1901 |
+
9
|
| 1902 |
+
],
|
| 1903 |
+
"truth_ids": [
|
| 1904 |
+
228
|
| 1905 |
+
],
|
| 1906 |
+
"masked_ids": [
|
| 1907 |
+
2,
|
| 1908 |
+
525,
|
| 1909 |
+
139,
|
| 1910 |
+
190,
|
| 1911 |
+
119,
|
| 1912 |
+
177,
|
| 1913 |
+
119,
|
| 1914 |
+
139,
|
| 1915 |
+
333,
|
| 1916 |
+
4,
|
| 1917 |
+
291,
|
| 1918 |
+
3,
|
| 1919 |
+
0,
|
| 1920 |
+
0,
|
| 1921 |
+
0,
|
| 1922 |
+
0,
|
| 1923 |
+
0,
|
| 1924 |
+
0,
|
| 1925 |
+
0,
|
| 1926 |
+
0,
|
| 1927 |
+
0,
|
| 1928 |
+
0,
|
| 1929 |
+
0,
|
| 1930 |
+
0,
|
| 1931 |
+
0,
|
| 1932 |
+
0,
|
| 1933 |
+
0,
|
| 1934 |
+
0,
|
| 1935 |
+
0,
|
| 1936 |
+
0,
|
| 1937 |
+
0,
|
| 1938 |
+
0,
|
| 1939 |
+
0,
|
| 1940 |
+
0,
|
| 1941 |
+
0,
|
| 1942 |
+
0,
|
| 1943 |
+
0,
|
| 1944 |
+
0,
|
| 1945 |
+
0,
|
| 1946 |
+
0,
|
| 1947 |
+
0,
|
| 1948 |
+
0,
|
| 1949 |
+
0,
|
| 1950 |
+
0,
|
| 1951 |
+
0,
|
| 1952 |
+
0,
|
| 1953 |
+
0,
|
| 1954 |
+
0,
|
| 1955 |
+
0,
|
| 1956 |
+
0,
|
| 1957 |
+
0,
|
| 1958 |
+
0,
|
| 1959 |
+
0,
|
| 1960 |
+
0,
|
| 1961 |
+
0,
|
| 1962 |
+
0,
|
| 1963 |
+
0,
|
| 1964 |
+
0,
|
| 1965 |
+
0,
|
| 1966 |
+
0,
|
| 1967 |
+
0,
|
| 1968 |
+
0,
|
| 1969 |
+
0,
|
| 1970 |
+
0,
|
| 1971 |
+
0,
|
| 1972 |
+
0,
|
| 1973 |
+
0,
|
| 1974 |
+
0,
|
| 1975 |
+
0,
|
| 1976 |
+
0,
|
| 1977 |
+
0,
|
| 1978 |
+
0,
|
| 1979 |
+
0,
|
| 1980 |
+
0,
|
| 1981 |
+
0,
|
| 1982 |
+
0,
|
| 1983 |
+
0,
|
| 1984 |
+
0,
|
| 1985 |
+
0,
|
| 1986 |
+
0,
|
| 1987 |
+
0,
|
| 1988 |
+
0,
|
| 1989 |
+
0,
|
| 1990 |
+
0,
|
| 1991 |
+
0,
|
| 1992 |
+
0,
|
| 1993 |
+
0,
|
| 1994 |
+
0,
|
| 1995 |
+
0,
|
| 1996 |
+
0,
|
| 1997 |
+
0,
|
| 1998 |
+
0,
|
| 1999 |
+
0,
|
| 2000 |
+
0,
|
| 2001 |
+
0,
|
| 2002 |
+
0,
|
| 2003 |
+
0,
|
| 2004 |
+
0,
|
| 2005 |
+
0,
|
| 2006 |
+
0,
|
| 2007 |
+
0,
|
| 2008 |
+
0,
|
| 2009 |
+
0,
|
| 2010 |
+
0,
|
| 2011 |
+
0,
|
| 2012 |
+
0,
|
| 2013 |
+
0,
|
| 2014 |
+
0,
|
| 2015 |
+
0,
|
| 2016 |
+
0,
|
| 2017 |
+
0,
|
| 2018 |
+
0,
|
| 2019 |
+
0,
|
| 2020 |
+
0,
|
| 2021 |
+
0,
|
| 2022 |
+
0,
|
| 2023 |
+
0,
|
| 2024 |
+
0,
|
| 2025 |
+
0,
|
| 2026 |
+
0,
|
| 2027 |
+
0,
|
| 2028 |
+
0,
|
| 2029 |
+
0,
|
| 2030 |
+
0,
|
| 2031 |
+
0,
|
| 2032 |
+
0,
|
| 2033 |
+
0,
|
| 2034 |
+
0,
|
| 2035 |
+
0,
|
| 2036 |
+
0,
|
| 2037 |
+
0,
|
| 2038 |
+
0,
|
| 2039 |
+
0,
|
| 2040 |
+
0,
|
| 2041 |
+
0,
|
| 2042 |
+
0,
|
| 2043 |
+
0,
|
| 2044 |
+
0,
|
| 2045 |
+
0,
|
| 2046 |
+
0,
|
| 2047 |
+
0,
|
| 2048 |
+
0,
|
| 2049 |
+
0,
|
| 2050 |
+
0,
|
| 2051 |
+
0,
|
| 2052 |
+
0,
|
| 2053 |
+
0,
|
| 2054 |
+
0,
|
| 2055 |
+
0,
|
| 2056 |
+
0,
|
| 2057 |
+
0,
|
| 2058 |
+
0,
|
| 2059 |
+
0,
|
| 2060 |
+
0,
|
| 2061 |
+
0,
|
| 2062 |
+
0,
|
| 2063 |
+
0,
|
| 2064 |
+
0,
|
| 2065 |
+
0,
|
| 2066 |
+
0,
|
| 2067 |
+
0,
|
| 2068 |
+
0,
|
| 2069 |
+
0,
|
| 2070 |
+
0,
|
| 2071 |
+
0,
|
| 2072 |
+
0,
|
| 2073 |
+
0,
|
| 2074 |
+
0,
|
| 2075 |
+
0,
|
| 2076 |
+
0,
|
| 2077 |
+
0,
|
| 2078 |
+
0,
|
| 2079 |
+
0,
|
| 2080 |
+
0,
|
| 2081 |
+
0,
|
| 2082 |
+
0,
|
| 2083 |
+
0,
|
| 2084 |
+
0,
|
| 2085 |
+
0,
|
| 2086 |
+
0,
|
| 2087 |
+
0,
|
| 2088 |
+
0,
|
| 2089 |
+
0,
|
| 2090 |
+
0,
|
| 2091 |
+
0,
|
| 2092 |
+
0,
|
| 2093 |
+
0,
|
| 2094 |
+
0,
|
| 2095 |
+
0,
|
| 2096 |
+
0,
|
| 2097 |
+
0,
|
| 2098 |
+
0,
|
| 2099 |
+
0,
|
| 2100 |
+
0,
|
| 2101 |
+
0,
|
| 2102 |
+
0,
|
| 2103 |
+
0,
|
| 2104 |
+
0,
|
| 2105 |
+
0,
|
| 2106 |
+
0,
|
| 2107 |
+
0,
|
| 2108 |
+
0,
|
| 2109 |
+
0,
|
| 2110 |
+
0,
|
| 2111 |
+
0,
|
| 2112 |
+
0,
|
| 2113 |
+
0,
|
| 2114 |
+
0,
|
| 2115 |
+
0,
|
| 2116 |
+
0,
|
| 2117 |
+
0,
|
| 2118 |
+
0,
|
| 2119 |
+
0,
|
| 2120 |
+
0,
|
| 2121 |
+
0,
|
| 2122 |
+
0,
|
| 2123 |
+
0,
|
| 2124 |
+
0,
|
| 2125 |
+
0,
|
| 2126 |
+
0,
|
| 2127 |
+
0,
|
| 2128 |
+
0,
|
| 2129 |
+
0,
|
| 2130 |
+
0,
|
| 2131 |
+
0,
|
| 2132 |
+
0,
|
| 2133 |
+
0,
|
| 2134 |
+
0,
|
| 2135 |
+
0,
|
| 2136 |
+
0,
|
| 2137 |
+
0,
|
| 2138 |
+
0,
|
| 2139 |
+
0,
|
| 2140 |
+
0,
|
| 2141 |
+
0,
|
| 2142 |
+
0,
|
| 2143 |
+
0,
|
| 2144 |
+
0,
|
| 2145 |
+
0,
|
| 2146 |
+
0,
|
| 2147 |
+
0,
|
| 2148 |
+
0,
|
| 2149 |
+
0,
|
| 2150 |
+
0,
|
| 2151 |
+
0,
|
| 2152 |
+
0,
|
| 2153 |
+
0,
|
| 2154 |
+
0,
|
| 2155 |
+
0,
|
| 2156 |
+
0,
|
| 2157 |
+
0,
|
| 2158 |
+
0,
|
| 2159 |
+
0,
|
| 2160 |
+
0,
|
| 2161 |
+
0,
|
| 2162 |
+
0
|
| 2163 |
+
],
|
| 2164 |
+
"attention_mask": [
|
| 2165 |
+
1,
|
| 2166 |
+
1,
|
| 2167 |
+
1,
|
| 2168 |
+
1,
|
| 2169 |
+
1,
|
| 2170 |
+
1,
|
| 2171 |
+
1,
|
| 2172 |
+
1,
|
| 2173 |
+
1,
|
| 2174 |
+
1,
|
| 2175 |
+
1,
|
| 2176 |
+
1,
|
| 2177 |
+
0,
|
| 2178 |
+
0,
|
| 2179 |
+
0,
|
| 2180 |
+
0,
|
| 2181 |
+
0,
|
| 2182 |
+
0,
|
| 2183 |
+
0,
|
| 2184 |
+
0,
|
| 2185 |
+
0,
|
| 2186 |
+
0,
|
| 2187 |
+
0,
|
| 2188 |
+
0,
|
| 2189 |
+
0,
|
| 2190 |
+
0,
|
| 2191 |
+
0,
|
| 2192 |
+
0,
|
| 2193 |
+
0,
|
| 2194 |
+
0,
|
| 2195 |
+
0,
|
| 2196 |
+
0,
|
| 2197 |
+
0,
|
| 2198 |
+
0,
|
| 2199 |
+
0,
|
| 2200 |
+
0,
|
| 2201 |
+
0,
|
| 2202 |
+
0,
|
| 2203 |
+
0,
|
| 2204 |
+
0,
|
| 2205 |
+
0,
|
| 2206 |
+
0,
|
| 2207 |
+
0,
|
| 2208 |
+
0,
|
| 2209 |
+
0,
|
| 2210 |
+
0,
|
| 2211 |
+
0,
|
| 2212 |
+
0,
|
| 2213 |
+
0,
|
| 2214 |
+
0,
|
| 2215 |
+
0,
|
| 2216 |
+
0,
|
| 2217 |
+
0,
|
| 2218 |
+
0,
|
| 2219 |
+
0,
|
| 2220 |
+
0,
|
| 2221 |
+
0,
|
| 2222 |
+
0,
|
| 2223 |
+
0,
|
| 2224 |
+
0,
|
| 2225 |
+
0,
|
| 2226 |
+
0,
|
| 2227 |
+
0,
|
| 2228 |
+
0,
|
| 2229 |
+
0,
|
| 2230 |
+
0,
|
| 2231 |
+
0,
|
| 2232 |
+
0,
|
| 2233 |
+
0,
|
| 2234 |
+
0,
|
| 2235 |
+
0,
|
| 2236 |
+
0,
|
| 2237 |
+
0,
|
| 2238 |
+
0,
|
| 2239 |
+
0,
|
| 2240 |
+
0,
|
| 2241 |
+
0,
|
| 2242 |
+
0,
|
| 2243 |
+
0,
|
| 2244 |
+
0,
|
| 2245 |
+
0,
|
| 2246 |
+
0,
|
| 2247 |
+
0,
|
| 2248 |
+
0,
|
| 2249 |
+
0,
|
| 2250 |
+
0,
|
| 2251 |
+
0,
|
| 2252 |
+
0,
|
| 2253 |
+
0,
|
| 2254 |
+
0,
|
| 2255 |
+
0,
|
| 2256 |
+
0,
|
| 2257 |
+
0,
|
| 2258 |
+
0,
|
| 2259 |
+
0,
|
| 2260 |
+
0,
|
| 2261 |
+
0,
|
| 2262 |
+
0,
|
| 2263 |
+
0,
|
| 2264 |
+
0,
|
| 2265 |
+
0,
|
| 2266 |
+
0,
|
| 2267 |
+
0,
|
| 2268 |
+
0,
|
| 2269 |
+
0,
|
| 2270 |
+
0,
|
| 2271 |
+
0,
|
| 2272 |
+
0,
|
| 2273 |
+
0,
|
| 2274 |
+
0,
|
| 2275 |
+
0,
|
| 2276 |
+
0,
|
| 2277 |
+
0,
|
| 2278 |
+
0,
|
| 2279 |
+
0,
|
| 2280 |
+
0,
|
| 2281 |
+
0,
|
| 2282 |
+
0,
|
| 2283 |
+
0,
|
| 2284 |
+
0,
|
| 2285 |
+
0,
|
| 2286 |
+
0,
|
| 2287 |
+
0,
|
| 2288 |
+
0,
|
| 2289 |
+
0,
|
| 2290 |
+
0,
|
| 2291 |
+
0,
|
| 2292 |
+
0,
|
| 2293 |
+
0,
|
| 2294 |
+
0,
|
| 2295 |
+
0,
|
| 2296 |
+
0,
|
| 2297 |
+
0,
|
| 2298 |
+
0,
|
| 2299 |
+
0,
|
| 2300 |
+
0,
|
| 2301 |
+
0,
|
| 2302 |
+
0,
|
| 2303 |
+
0,
|
| 2304 |
+
0,
|
| 2305 |
+
0,
|
| 2306 |
+
0,
|
| 2307 |
+
0,
|
| 2308 |
+
0,
|
| 2309 |
+
0,
|
| 2310 |
+
0,
|
| 2311 |
+
0,
|
| 2312 |
+
0,
|
| 2313 |
+
0,
|
| 2314 |
+
0,
|
| 2315 |
+
0,
|
| 2316 |
+
0,
|
| 2317 |
+
0,
|
| 2318 |
+
0,
|
| 2319 |
+
0,
|
| 2320 |
+
0,
|
| 2321 |
+
0,
|
| 2322 |
+
0,
|
| 2323 |
+
0,
|
| 2324 |
+
0,
|
| 2325 |
+
0,
|
| 2326 |
+
0,
|
| 2327 |
+
0,
|
| 2328 |
+
0,
|
| 2329 |
+
0,
|
| 2330 |
+
0,
|
| 2331 |
+
0,
|
| 2332 |
+
0,
|
| 2333 |
+
0,
|
| 2334 |
+
0,
|
| 2335 |
+
0,
|
| 2336 |
+
0,
|
| 2337 |
+
0,
|
| 2338 |
+
0,
|
| 2339 |
+
0,
|
| 2340 |
+
0,
|
| 2341 |
+
0,
|
| 2342 |
+
0,
|
| 2343 |
+
0,
|
| 2344 |
+
0,
|
| 2345 |
+
0,
|
| 2346 |
+
0,
|
| 2347 |
+
0,
|
| 2348 |
+
0,
|
| 2349 |
+
0,
|
| 2350 |
+
0,
|
| 2351 |
+
0,
|
| 2352 |
+
0,
|
| 2353 |
+
0,
|
| 2354 |
+
0,
|
| 2355 |
+
0,
|
| 2356 |
+
0,
|
| 2357 |
+
0,
|
| 2358 |
+
0,
|
| 2359 |
+
0,
|
| 2360 |
+
0,
|
| 2361 |
+
0,
|
| 2362 |
+
0,
|
| 2363 |
+
0,
|
| 2364 |
+
0,
|
| 2365 |
+
0,
|
| 2366 |
+
0,
|
| 2367 |
+
0,
|
| 2368 |
+
0,
|
| 2369 |
+
0,
|
| 2370 |
+
0,
|
| 2371 |
+
0,
|
| 2372 |
+
0,
|
| 2373 |
+
0,
|
| 2374 |
+
0,
|
| 2375 |
+
0,
|
| 2376 |
+
0,
|
| 2377 |
+
0,
|
| 2378 |
+
0,
|
| 2379 |
+
0,
|
| 2380 |
+
0,
|
| 2381 |
+
0,
|
| 2382 |
+
0,
|
| 2383 |
+
0,
|
| 2384 |
+
0,
|
| 2385 |
+
0,
|
| 2386 |
+
0,
|
| 2387 |
+
0,
|
| 2388 |
+
0,
|
| 2389 |
+
0,
|
| 2390 |
+
0,
|
| 2391 |
+
0,
|
| 2392 |
+
0,
|
| 2393 |
+
0,
|
| 2394 |
+
0,
|
| 2395 |
+
0,
|
| 2396 |
+
0,
|
| 2397 |
+
0,
|
| 2398 |
+
0,
|
| 2399 |
+
0,
|
| 2400 |
+
0,
|
| 2401 |
+
0,
|
| 2402 |
+
0,
|
| 2403 |
+
0,
|
| 2404 |
+
0,
|
| 2405 |
+
0,
|
| 2406 |
+
0,
|
| 2407 |
+
0,
|
| 2408 |
+
0,
|
| 2409 |
+
0,
|
| 2410 |
+
0,
|
| 2411 |
+
0,
|
| 2412 |
+
0,
|
| 2413 |
+
0,
|
| 2414 |
+
0,
|
| 2415 |
+
0,
|
| 2416 |
+
0,
|
| 2417 |
+
0,
|
| 2418 |
+
0,
|
| 2419 |
+
0,
|
| 2420 |
+
0
|
| 2421 |
+
],
|
| 2422 |
+
"residue_ids": [
|
| 2423 |
+
-1,
|
| 2424 |
+
0,
|
| 2425 |
+
0,
|
| 2426 |
+
1,
|
| 2427 |
+
1,
|
| 2428 |
+
2,
|
| 2429 |
+
2,
|
| 2430 |
+
2,
|
| 2431 |
+
2,
|
| 2432 |
+
-2,
|
| 2433 |
+
-2,
|
| 2434 |
+
-1,
|
| 2435 |
+
-1,
|
| 2436 |
+
-1,
|
| 2437 |
+
-1,
|
| 2438 |
+
-1,
|
| 2439 |
+
-1,
|
| 2440 |
+
-1,
|
| 2441 |
+
-1,
|
| 2442 |
+
-1,
|
| 2443 |
+
-1,
|
| 2444 |
+
-1,
|
| 2445 |
+
-1,
|
| 2446 |
+
-1,
|
| 2447 |
+
-1,
|
| 2448 |
+
-1,
|
| 2449 |
+
-1,
|
| 2450 |
+
-1,
|
| 2451 |
+
-1,
|
| 2452 |
+
-1,
|
| 2453 |
+
-1,
|
| 2454 |
+
-1,
|
| 2455 |
+
-1,
|
| 2456 |
+
-1,
|
| 2457 |
+
-1,
|
| 2458 |
+
-1,
|
| 2459 |
+
-1,
|
| 2460 |
+
-1,
|
| 2461 |
+
-1,
|
| 2462 |
+
-1,
|
| 2463 |
+
-1,
|
| 2464 |
+
-1,
|
| 2465 |
+
-1,
|
| 2466 |
+
-1,
|
| 2467 |
+
-1,
|
| 2468 |
+
-1,
|
| 2469 |
+
-1,
|
| 2470 |
+
-1,
|
| 2471 |
+
-1,
|
| 2472 |
+
-1,
|
| 2473 |
+
-1,
|
| 2474 |
+
-1,
|
| 2475 |
+
-1,
|
| 2476 |
+
-1,
|
| 2477 |
+
-1,
|
| 2478 |
+
-1,
|
| 2479 |
+
-1,
|
| 2480 |
+
-1,
|
| 2481 |
+
-1,
|
| 2482 |
+
-1,
|
| 2483 |
+
-1,
|
| 2484 |
+
-1,
|
| 2485 |
+
-1,
|
| 2486 |
+
-1,
|
| 2487 |
+
-1,
|
| 2488 |
+
-1,
|
| 2489 |
+
-1,
|
| 2490 |
+
-1,
|
| 2491 |
+
-1,
|
| 2492 |
+
-1,
|
| 2493 |
+
-1,
|
| 2494 |
+
-1,
|
| 2495 |
+
-1,
|
| 2496 |
+
-1,
|
| 2497 |
+
-1,
|
| 2498 |
+
-1,
|
| 2499 |
+
-1,
|
| 2500 |
+
-1,
|
| 2501 |
+
-1,
|
| 2502 |
+
-1,
|
| 2503 |
+
-1,
|
| 2504 |
+
-1,
|
| 2505 |
+
-1,
|
| 2506 |
+
-1,
|
| 2507 |
+
-1,
|
| 2508 |
+
-1,
|
| 2509 |
+
-1,
|
| 2510 |
+
-1,
|
| 2511 |
+
-1,
|
| 2512 |
+
-1,
|
| 2513 |
+
-1,
|
| 2514 |
+
-1,
|
| 2515 |
+
-1,
|
| 2516 |
+
-1,
|
| 2517 |
+
-1,
|
| 2518 |
+
-1,
|
| 2519 |
+
-1,
|
| 2520 |
+
-1,
|
| 2521 |
+
-1,
|
| 2522 |
+
-1,
|
| 2523 |
+
-1,
|
| 2524 |
+
-1,
|
| 2525 |
+
-1,
|
| 2526 |
+
-1,
|
| 2527 |
+
-1,
|
| 2528 |
+
-1,
|
| 2529 |
+
-1,
|
| 2530 |
+
-1,
|
| 2531 |
+
-1,
|
| 2532 |
+
-1,
|
| 2533 |
+
-1,
|
| 2534 |
+
-1,
|
| 2535 |
+
-1,
|
| 2536 |
+
-1,
|
| 2537 |
+
-1,
|
| 2538 |
+
-1,
|
| 2539 |
+
-1,
|
| 2540 |
+
-1,
|
| 2541 |
+
-1,
|
| 2542 |
+
-1,
|
| 2543 |
+
-1,
|
| 2544 |
+
-1,
|
| 2545 |
+
-1,
|
| 2546 |
+
-1,
|
| 2547 |
+
-1,
|
| 2548 |
+
-1,
|
| 2549 |
+
-1,
|
| 2550 |
+
-1,
|
| 2551 |
+
-1,
|
| 2552 |
+
-1,
|
| 2553 |
+
-1,
|
| 2554 |
+
-1,
|
| 2555 |
+
-1,
|
| 2556 |
+
-1,
|
| 2557 |
+
-1,
|
| 2558 |
+
-1,
|
| 2559 |
+
-1,
|
| 2560 |
+
-1,
|
| 2561 |
+
-1,
|
| 2562 |
+
-1,
|
| 2563 |
+
-1,
|
| 2564 |
+
-1,
|
| 2565 |
+
-1,
|
| 2566 |
+
-1,
|
| 2567 |
+
-1,
|
| 2568 |
+
-1,
|
| 2569 |
+
-1,
|
| 2570 |
+
-1,
|
| 2571 |
+
-1,
|
| 2572 |
+
-1,
|
| 2573 |
+
-1,
|
| 2574 |
+
-1,
|
| 2575 |
+
-1,
|
| 2576 |
+
-1,
|
| 2577 |
+
-1,
|
| 2578 |
+
-1,
|
| 2579 |
+
-1,
|
| 2580 |
+
-1,
|
| 2581 |
+
-1,
|
| 2582 |
+
-1,
|
| 2583 |
+
-1,
|
| 2584 |
+
-1,
|
| 2585 |
+
-1,
|
| 2586 |
+
-1,
|
| 2587 |
+
-1,
|
| 2588 |
+
-1,
|
| 2589 |
+
-1,
|
| 2590 |
+
-1,
|
| 2591 |
+
-1,
|
| 2592 |
+
-1,
|
| 2593 |
+
-1,
|
| 2594 |
+
-1,
|
| 2595 |
+
-1,
|
| 2596 |
+
-1,
|
| 2597 |
+
-1,
|
| 2598 |
+
-1,
|
| 2599 |
+
-1,
|
| 2600 |
+
-1,
|
| 2601 |
+
-1,
|
| 2602 |
+
-1,
|
| 2603 |
+
-1,
|
| 2604 |
+
-1,
|
| 2605 |
+
-1,
|
| 2606 |
+
-1,
|
| 2607 |
+
-1,
|
| 2608 |
+
-1,
|
| 2609 |
+
-1,
|
| 2610 |
+
-1,
|
| 2611 |
+
-1,
|
| 2612 |
+
-1,
|
| 2613 |
+
-1,
|
| 2614 |
+
-1,
|
| 2615 |
+
-1,
|
| 2616 |
+
-1,
|
| 2617 |
+
-1,
|
| 2618 |
+
-1,
|
| 2619 |
+
-1,
|
| 2620 |
+
-1,
|
| 2621 |
+
-1,
|
| 2622 |
+
-1,
|
| 2623 |
+
-1,
|
| 2624 |
+
-1,
|
| 2625 |
+
-1,
|
| 2626 |
+
-1,
|
| 2627 |
+
-1,
|
| 2628 |
+
-1,
|
| 2629 |
+
-1,
|
| 2630 |
+
-1,
|
| 2631 |
+
-1,
|
| 2632 |
+
-1,
|
| 2633 |
+
-1,
|
| 2634 |
+
-1,
|
| 2635 |
+
-1,
|
| 2636 |
+
-1,
|
| 2637 |
+
-1,
|
| 2638 |
+
-1,
|
| 2639 |
+
-1,
|
| 2640 |
+
-1,
|
| 2641 |
+
-1,
|
| 2642 |
+
-1,
|
| 2643 |
+
-1,
|
| 2644 |
+
-1,
|
| 2645 |
+
-1,
|
| 2646 |
+
-1,
|
| 2647 |
+
-1,
|
| 2648 |
+
-1,
|
| 2649 |
+
-1,
|
| 2650 |
+
-1,
|
| 2651 |
+
-1,
|
| 2652 |
+
-1,
|
| 2653 |
+
-1,
|
| 2654 |
+
-1,
|
| 2655 |
+
-1,
|
| 2656 |
+
-1,
|
| 2657 |
+
-1,
|
| 2658 |
+
-1,
|
| 2659 |
+
-1,
|
| 2660 |
+
-1,
|
| 2661 |
+
-1,
|
| 2662 |
+
-1,
|
| 2663 |
+
-1,
|
| 2664 |
+
-1,
|
| 2665 |
+
-1,
|
| 2666 |
+
-1,
|
| 2667 |
+
-1,
|
| 2668 |
+
-1,
|
| 2669 |
+
-1,
|
| 2670 |
+
-1,
|
| 2671 |
+
-1,
|
| 2672 |
+
-1,
|
| 2673 |
+
-1,
|
| 2674 |
+
-1,
|
| 2675 |
+
-1,
|
| 2676 |
+
-1,
|
| 2677 |
+
-1,
|
| 2678 |
+
-1
|
| 2679 |
+
],
|
| 2680 |
+
"branch_depths": [
|
| 2681 |
+
0,
|
| 2682 |
+
0,
|
| 2683 |
+
0,
|
| 2684 |
+
1,
|
| 2685 |
+
1,
|
| 2686 |
+
2,
|
| 2687 |
+
2,
|
| 2688 |
+
2,
|
| 2689 |
+
2,
|
| 2690 |
+
0,
|
| 2691 |
+
0,
|
| 2692 |
+
0,
|
| 2693 |
+
0,
|
| 2694 |
+
0,
|
| 2695 |
+
0,
|
| 2696 |
+
0,
|
| 2697 |
+
0,
|
| 2698 |
+
0,
|
| 2699 |
+
0,
|
| 2700 |
+
0,
|
| 2701 |
+
0,
|
| 2702 |
+
0,
|
| 2703 |
+
0,
|
| 2704 |
+
0,
|
| 2705 |
+
0,
|
| 2706 |
+
0,
|
| 2707 |
+
0,
|
| 2708 |
+
0,
|
| 2709 |
+
0,
|
| 2710 |
+
0,
|
| 2711 |
+
0,
|
| 2712 |
+
0,
|
| 2713 |
+
0,
|
| 2714 |
+
0,
|
| 2715 |
+
0,
|
| 2716 |
+
0,
|
| 2717 |
+
0,
|
| 2718 |
+
0,
|
| 2719 |
+
0,
|
| 2720 |
+
0,
|
| 2721 |
+
0,
|
| 2722 |
+
0,
|
| 2723 |
+
0,
|
| 2724 |
+
0,
|
| 2725 |
+
0,
|
| 2726 |
+
0,
|
| 2727 |
+
0,
|
| 2728 |
+
0,
|
| 2729 |
+
0,
|
| 2730 |
+
0,
|
| 2731 |
+
0,
|
| 2732 |
+
0,
|
| 2733 |
+
0,
|
| 2734 |
+
0,
|
| 2735 |
+
0,
|
| 2736 |
+
0,
|
| 2737 |
+
0,
|
| 2738 |
+
0,
|
| 2739 |
+
0,
|
| 2740 |
+
0,
|
| 2741 |
+
0,
|
| 2742 |
+
0,
|
| 2743 |
+
0,
|
| 2744 |
+
0,
|
| 2745 |
+
0,
|
| 2746 |
+
0,
|
| 2747 |
+
0,
|
| 2748 |
+
0,
|
| 2749 |
+
0,
|
| 2750 |
+
0,
|
| 2751 |
+
0,
|
| 2752 |
+
0,
|
| 2753 |
+
0,
|
| 2754 |
+
0,
|
| 2755 |
+
0,
|
| 2756 |
+
0,
|
| 2757 |
+
0,
|
| 2758 |
+
0,
|
| 2759 |
+
0,
|
| 2760 |
+
0,
|
| 2761 |
+
0,
|
| 2762 |
+
0,
|
| 2763 |
+
0,
|
| 2764 |
+
0,
|
| 2765 |
+
0,
|
| 2766 |
+
0,
|
| 2767 |
+
0,
|
| 2768 |
+
0,
|
| 2769 |
+
0,
|
| 2770 |
+
0,
|
| 2771 |
+
0,
|
| 2772 |
+
0,
|
| 2773 |
+
0,
|
| 2774 |
+
0,
|
| 2775 |
+
0,
|
| 2776 |
+
0,
|
| 2777 |
+
0,
|
| 2778 |
+
0,
|
| 2779 |
+
0,
|
| 2780 |
+
0,
|
| 2781 |
+
0,
|
| 2782 |
+
0,
|
| 2783 |
+
0,
|
| 2784 |
+
0,
|
| 2785 |
+
0,
|
| 2786 |
+
0,
|
| 2787 |
+
0,
|
| 2788 |
+
0,
|
| 2789 |
+
0,
|
| 2790 |
+
0,
|
| 2791 |
+
0,
|
| 2792 |
+
0,
|
| 2793 |
+
0,
|
| 2794 |
+
0,
|
| 2795 |
+
0,
|
| 2796 |
+
0,
|
| 2797 |
+
0,
|
| 2798 |
+
0,
|
| 2799 |
+
0,
|
| 2800 |
+
0,
|
| 2801 |
+
0,
|
| 2802 |
+
0,
|
| 2803 |
+
0,
|
| 2804 |
+
0,
|
| 2805 |
+
0,
|
| 2806 |
+
0,
|
| 2807 |
+
0,
|
| 2808 |
+
0,
|
| 2809 |
+
0,
|
| 2810 |
+
0,
|
| 2811 |
+
0,
|
| 2812 |
+
0,
|
| 2813 |
+
0,
|
| 2814 |
+
0,
|
| 2815 |
+
0,
|
| 2816 |
+
0,
|
| 2817 |
+
0,
|
| 2818 |
+
0,
|
| 2819 |
+
0,
|
| 2820 |
+
0,
|
| 2821 |
+
0,
|
| 2822 |
+
0,
|
| 2823 |
+
0,
|
| 2824 |
+
0,
|
| 2825 |
+
0,
|
| 2826 |
+
0,
|
| 2827 |
+
0,
|
| 2828 |
+
0,
|
| 2829 |
+
0,
|
| 2830 |
+
0,
|
| 2831 |
+
0,
|
| 2832 |
+
0,
|
| 2833 |
+
0,
|
| 2834 |
+
0,
|
| 2835 |
+
0,
|
| 2836 |
+
0,
|
| 2837 |
+
0,
|
| 2838 |
+
0,
|
| 2839 |
+
0,
|
| 2840 |
+
0,
|
| 2841 |
+
0,
|
| 2842 |
+
0,
|
| 2843 |
+
0,
|
| 2844 |
+
0,
|
| 2845 |
+
0,
|
| 2846 |
+
0,
|
| 2847 |
+
0,
|
| 2848 |
+
0,
|
| 2849 |
+
0,
|
| 2850 |
+
0,
|
| 2851 |
+
0,
|
| 2852 |
+
0,
|
| 2853 |
+
0,
|
| 2854 |
+
0,
|
| 2855 |
+
0,
|
| 2856 |
+
0,
|
| 2857 |
+
0,
|
| 2858 |
+
0,
|
| 2859 |
+
0,
|
| 2860 |
+
0,
|
| 2861 |
+
0,
|
| 2862 |
+
0,
|
| 2863 |
+
0,
|
| 2864 |
+
0,
|
| 2865 |
+
0,
|
| 2866 |
+
0,
|
| 2867 |
+
0,
|
| 2868 |
+
0,
|
| 2869 |
+
0,
|
| 2870 |
+
0,
|
| 2871 |
+
0,
|
| 2872 |
+
0,
|
| 2873 |
+
0,
|
| 2874 |
+
0,
|
| 2875 |
+
0,
|
| 2876 |
+
0,
|
| 2877 |
+
0,
|
| 2878 |
+
0,
|
| 2879 |
+
0,
|
| 2880 |
+
0,
|
| 2881 |
+
0,
|
| 2882 |
+
0,
|
| 2883 |
+
0,
|
| 2884 |
+
0,
|
| 2885 |
+
0,
|
| 2886 |
+
0,
|
| 2887 |
+
0,
|
| 2888 |
+
0,
|
| 2889 |
+
0,
|
| 2890 |
+
0,
|
| 2891 |
+
0,
|
| 2892 |
+
0,
|
| 2893 |
+
0,
|
| 2894 |
+
0,
|
| 2895 |
+
0,
|
| 2896 |
+
0,
|
| 2897 |
+
0,
|
| 2898 |
+
0,
|
| 2899 |
+
0,
|
| 2900 |
+
0,
|
| 2901 |
+
0,
|
| 2902 |
+
0,
|
| 2903 |
+
0,
|
| 2904 |
+
0,
|
| 2905 |
+
0,
|
| 2906 |
+
0,
|
| 2907 |
+
0,
|
| 2908 |
+
0,
|
| 2909 |
+
0,
|
| 2910 |
+
0,
|
| 2911 |
+
0,
|
| 2912 |
+
0,
|
| 2913 |
+
0,
|
| 2914 |
+
0,
|
| 2915 |
+
0,
|
| 2916 |
+
0,
|
| 2917 |
+
0,
|
| 2918 |
+
0,
|
| 2919 |
+
0,
|
| 2920 |
+
0,
|
| 2921 |
+
0,
|
| 2922 |
+
0,
|
| 2923 |
+
0,
|
| 2924 |
+
0,
|
| 2925 |
+
0,
|
| 2926 |
+
0,
|
| 2927 |
+
0,
|
| 2928 |
+
0,
|
| 2929 |
+
0,
|
| 2930 |
+
0,
|
| 2931 |
+
0,
|
| 2932 |
+
0,
|
| 2933 |
+
0,
|
| 2934 |
+
0,
|
| 2935 |
+
0,
|
| 2936 |
+
0
|
| 2937 |
+
],
|
| 2938 |
+
"linkage_types": [
|
| 2939 |
+
0,
|
| 2940 |
+
0,
|
| 2941 |
+
0,
|
| 2942 |
+
0,
|
| 2943 |
+
0,
|
| 2944 |
+
0,
|
| 2945 |
+
0,
|
| 2946 |
+
0,
|
| 2947 |
+
0,
|
| 2948 |
+
3,
|
| 2949 |
+
2,
|
| 2950 |
+
0,
|
| 2951 |
+
0,
|
| 2952 |
+
0,
|
| 2953 |
+
0,
|
| 2954 |
+
0,
|
| 2955 |
+
0,
|
| 2956 |
+
0,
|
| 2957 |
+
0,
|
| 2958 |
+
0,
|
| 2959 |
+
0,
|
| 2960 |
+
0,
|
| 2961 |
+
0,
|
| 2962 |
+
0,
|
| 2963 |
+
0,
|
| 2964 |
+
0,
|
| 2965 |
+
0,
|
| 2966 |
+
0,
|
| 2967 |
+
0,
|
| 2968 |
+
0,
|
| 2969 |
+
0,
|
| 2970 |
+
0,
|
| 2971 |
+
0,
|
| 2972 |
+
0,
|
| 2973 |
+
0,
|
| 2974 |
+
0,
|
| 2975 |
+
0,
|
| 2976 |
+
0,
|
| 2977 |
+
0,
|
| 2978 |
+
0,
|
| 2979 |
+
0,
|
| 2980 |
+
0,
|
| 2981 |
+
0,
|
| 2982 |
+
0,
|
| 2983 |
+
0,
|
| 2984 |
+
0,
|
| 2985 |
+
0,
|
| 2986 |
+
0,
|
| 2987 |
+
0,
|
| 2988 |
+
0,
|
| 2989 |
+
0,
|
| 2990 |
+
0,
|
| 2991 |
+
0,
|
| 2992 |
+
0,
|
| 2993 |
+
0,
|
| 2994 |
+
0,
|
| 2995 |
+
0,
|
| 2996 |
+
0,
|
| 2997 |
+
0,
|
| 2998 |
+
0,
|
| 2999 |
+
0,
|
| 3000 |
+
0,
|
| 3001 |
+
0,
|
| 3002 |
+
0,
|
| 3003 |
+
0,
|
| 3004 |
+
0,
|
| 3005 |
+
0,
|
| 3006 |
+
0,
|
| 3007 |
+
0,
|
| 3008 |
+
0,
|
| 3009 |
+
0,
|
| 3010 |
+
0,
|
| 3011 |
+
0,
|
| 3012 |
+
0,
|
| 3013 |
+
0,
|
| 3014 |
+
0,
|
| 3015 |
+
0,
|
| 3016 |
+
0,
|
| 3017 |
+
0,
|
| 3018 |
+
0,
|
| 3019 |
+
0,
|
| 3020 |
+
0,
|
| 3021 |
+
0,
|
| 3022 |
+
0,
|
| 3023 |
+
0,
|
| 3024 |
+
0,
|
| 3025 |
+
0,
|
| 3026 |
+
0,
|
| 3027 |
+
0,
|
| 3028 |
+
0,
|
| 3029 |
+
0,
|
| 3030 |
+
0,
|
| 3031 |
+
0,
|
| 3032 |
+
0,
|
| 3033 |
+
0,
|
| 3034 |
+
0,
|
| 3035 |
+
0,
|
| 3036 |
+
0,
|
| 3037 |
+
0,
|
| 3038 |
+
0,
|
| 3039 |
+
0,
|
| 3040 |
+
0,
|
| 3041 |
+
0,
|
| 3042 |
+
0,
|
| 3043 |
+
0,
|
| 3044 |
+
0,
|
| 3045 |
+
0,
|
| 3046 |
+
0,
|
| 3047 |
+
0,
|
| 3048 |
+
0,
|
| 3049 |
+
0,
|
| 3050 |
+
0,
|
| 3051 |
+
0,
|
| 3052 |
+
0,
|
| 3053 |
+
0,
|
| 3054 |
+
0,
|
| 3055 |
+
0,
|
| 3056 |
+
0,
|
| 3057 |
+
0,
|
| 3058 |
+
0,
|
| 3059 |
+
0,
|
| 3060 |
+
0,
|
| 3061 |
+
0,
|
| 3062 |
+
0,
|
| 3063 |
+
0,
|
| 3064 |
+
0,
|
| 3065 |
+
0,
|
| 3066 |
+
0,
|
| 3067 |
+
0,
|
| 3068 |
+
0,
|
| 3069 |
+
0,
|
| 3070 |
+
0,
|
| 3071 |
+
0,
|
| 3072 |
+
0,
|
| 3073 |
+
0,
|
| 3074 |
+
0,
|
| 3075 |
+
0,
|
| 3076 |
+
0,
|
| 3077 |
+
0,
|
| 3078 |
+
0,
|
| 3079 |
+
0,
|
| 3080 |
+
0,
|
| 3081 |
+
0,
|
| 3082 |
+
0,
|
| 3083 |
+
0,
|
| 3084 |
+
0,
|
| 3085 |
+
0,
|
| 3086 |
+
0,
|
| 3087 |
+
0,
|
| 3088 |
+
0,
|
| 3089 |
+
0,
|
| 3090 |
+
0,
|
| 3091 |
+
0,
|
| 3092 |
+
0,
|
| 3093 |
+
0,
|
| 3094 |
+
0,
|
| 3095 |
+
0,
|
| 3096 |
+
0,
|
| 3097 |
+
0,
|
| 3098 |
+
0,
|
| 3099 |
+
0,
|
| 3100 |
+
0,
|
| 3101 |
+
0,
|
| 3102 |
+
0,
|
| 3103 |
+
0,
|
| 3104 |
+
0,
|
| 3105 |
+
0,
|
| 3106 |
+
0,
|
| 3107 |
+
0,
|
| 3108 |
+
0,
|
| 3109 |
+
0,
|
| 3110 |
+
0,
|
| 3111 |
+
0,
|
| 3112 |
+
0,
|
| 3113 |
+
0,
|
| 3114 |
+
0,
|
| 3115 |
+
0,
|
| 3116 |
+
0,
|
| 3117 |
+
0,
|
| 3118 |
+
0,
|
| 3119 |
+
0,
|
| 3120 |
+
0,
|
| 3121 |
+
0,
|
| 3122 |
+
0,
|
| 3123 |
+
0,
|
| 3124 |
+
0,
|
| 3125 |
+
0,
|
| 3126 |
+
0,
|
| 3127 |
+
0,
|
| 3128 |
+
0,
|
| 3129 |
+
0,
|
| 3130 |
+
0,
|
| 3131 |
+
0,
|
| 3132 |
+
0,
|
| 3133 |
+
0,
|
| 3134 |
+
0,
|
| 3135 |
+
0,
|
| 3136 |
+
0,
|
| 3137 |
+
0,
|
| 3138 |
+
0,
|
| 3139 |
+
0,
|
| 3140 |
+
0,
|
| 3141 |
+
0,
|
| 3142 |
+
0,
|
| 3143 |
+
0,
|
| 3144 |
+
0,
|
| 3145 |
+
0,
|
| 3146 |
+
0,
|
| 3147 |
+
0,
|
| 3148 |
+
0,
|
| 3149 |
+
0,
|
| 3150 |
+
0,
|
| 3151 |
+
0,
|
| 3152 |
+
0,
|
| 3153 |
+
0,
|
| 3154 |
+
0,
|
| 3155 |
+
0,
|
| 3156 |
+
0,
|
| 3157 |
+
0,
|
| 3158 |
+
0,
|
| 3159 |
+
0,
|
| 3160 |
+
0,
|
| 3161 |
+
0,
|
| 3162 |
+
0,
|
| 3163 |
+
0,
|
| 3164 |
+
0,
|
| 3165 |
+
0,
|
| 3166 |
+
0,
|
| 3167 |
+
0,
|
| 3168 |
+
0,
|
| 3169 |
+
0,
|
| 3170 |
+
0,
|
| 3171 |
+
0,
|
| 3172 |
+
0,
|
| 3173 |
+
0,
|
| 3174 |
+
0,
|
| 3175 |
+
0,
|
| 3176 |
+
0,
|
| 3177 |
+
0,
|
| 3178 |
+
0,
|
| 3179 |
+
0,
|
| 3180 |
+
0,
|
| 3181 |
+
0,
|
| 3182 |
+
0,
|
| 3183 |
+
0,
|
| 3184 |
+
0,
|
| 3185 |
+
0,
|
| 3186 |
+
0,
|
| 3187 |
+
0,
|
| 3188 |
+
0,
|
| 3189 |
+
0,
|
| 3190 |
+
0,
|
| 3191 |
+
0,
|
| 3192 |
+
0,
|
| 3193 |
+
0,
|
| 3194 |
+
0
|
| 3195 |
+
],
|
| 3196 |
+
"branch_depths_blank": [
|
| 3197 |
+
0,
|
| 3198 |
+
0,
|
| 3199 |
+
0,
|
| 3200 |
+
1,
|
| 3201 |
+
1,
|
| 3202 |
+
2,
|
| 3203 |
+
2,
|
| 3204 |
+
2,
|
| 3205 |
+
2,
|
| 3206 |
+
0,
|
| 3207 |
+
0,
|
| 3208 |
+
0,
|
| 3209 |
+
0,
|
| 3210 |
+
0,
|
| 3211 |
+
0,
|
| 3212 |
+
0,
|
| 3213 |
+
0,
|
| 3214 |
+
0,
|
| 3215 |
+
0,
|
| 3216 |
+
0,
|
| 3217 |
+
0,
|
| 3218 |
+
0,
|
| 3219 |
+
0,
|
| 3220 |
+
0,
|
| 3221 |
+
0,
|
| 3222 |
+
0,
|
| 3223 |
+
0,
|
| 3224 |
+
0,
|
| 3225 |
+
0,
|
| 3226 |
+
0,
|
| 3227 |
+
0,
|
| 3228 |
+
0,
|
| 3229 |
+
0,
|
| 3230 |
+
0,
|
| 3231 |
+
0,
|
| 3232 |
+
0,
|
| 3233 |
+
0,
|
| 3234 |
+
0,
|
| 3235 |
+
0,
|
| 3236 |
+
0,
|
| 3237 |
+
0,
|
| 3238 |
+
0,
|
| 3239 |
+
0,
|
| 3240 |
+
0,
|
| 3241 |
+
0,
|
| 3242 |
+
0,
|
| 3243 |
+
0,
|
| 3244 |
+
0,
|
| 3245 |
+
0,
|
| 3246 |
+
0,
|
| 3247 |
+
0,
|
| 3248 |
+
0,
|
| 3249 |
+
0,
|
| 3250 |
+
0,
|
| 3251 |
+
0,
|
| 3252 |
+
0,
|
| 3253 |
+
0,
|
| 3254 |
+
0,
|
| 3255 |
+
0,
|
| 3256 |
+
0,
|
| 3257 |
+
0,
|
| 3258 |
+
0,
|
| 3259 |
+
0,
|
| 3260 |
+
0,
|
| 3261 |
+
0,
|
| 3262 |
+
0,
|
| 3263 |
+
0,
|
| 3264 |
+
0,
|
| 3265 |
+
0,
|
| 3266 |
+
0,
|
| 3267 |
+
0,
|
| 3268 |
+
0,
|
| 3269 |
+
0,
|
| 3270 |
+
0,
|
| 3271 |
+
0,
|
| 3272 |
+
0,
|
| 3273 |
+
0,
|
| 3274 |
+
0,
|
| 3275 |
+
0,
|
| 3276 |
+
0,
|
| 3277 |
+
0,
|
| 3278 |
+
0,
|
| 3279 |
+
0,
|
| 3280 |
+
0,
|
| 3281 |
+
0,
|
| 3282 |
+
0,
|
| 3283 |
+
0,
|
| 3284 |
+
0,
|
| 3285 |
+
0,
|
| 3286 |
+
0,
|
| 3287 |
+
0,
|
| 3288 |
+
0,
|
| 3289 |
+
0,
|
| 3290 |
+
0,
|
| 3291 |
+
0,
|
| 3292 |
+
0,
|
| 3293 |
+
0,
|
| 3294 |
+
0,
|
| 3295 |
+
0,
|
| 3296 |
+
0,
|
| 3297 |
+
0,
|
| 3298 |
+
0,
|
| 3299 |
+
0,
|
| 3300 |
+
0,
|
| 3301 |
+
0,
|
| 3302 |
+
0,
|
| 3303 |
+
0,
|
| 3304 |
+
0,
|
| 3305 |
+
0,
|
| 3306 |
+
0,
|
| 3307 |
+
0,
|
| 3308 |
+
0,
|
| 3309 |
+
0,
|
| 3310 |
+
0,
|
| 3311 |
+
0,
|
| 3312 |
+
0,
|
| 3313 |
+
0,
|
| 3314 |
+
0,
|
| 3315 |
+
0,
|
| 3316 |
+
0,
|
| 3317 |
+
0,
|
| 3318 |
+
0,
|
| 3319 |
+
0,
|
| 3320 |
+
0,
|
| 3321 |
+
0,
|
| 3322 |
+
0,
|
| 3323 |
+
0,
|
| 3324 |
+
0,
|
| 3325 |
+
0,
|
| 3326 |
+
0,
|
| 3327 |
+
0,
|
| 3328 |
+
0,
|
| 3329 |
+
0,
|
| 3330 |
+
0,
|
| 3331 |
+
0,
|
| 3332 |
+
0,
|
| 3333 |
+
0,
|
| 3334 |
+
0,
|
| 3335 |
+
0,
|
| 3336 |
+
0,
|
| 3337 |
+
0,
|
| 3338 |
+
0,
|
| 3339 |
+
0,
|
| 3340 |
+
0,
|
| 3341 |
+
0,
|
| 3342 |
+
0,
|
| 3343 |
+
0,
|
| 3344 |
+
0,
|
| 3345 |
+
0,
|
| 3346 |
+
0,
|
| 3347 |
+
0,
|
| 3348 |
+
0,
|
| 3349 |
+
0,
|
| 3350 |
+
0,
|
| 3351 |
+
0,
|
| 3352 |
+
0,
|
| 3353 |
+
0,
|
| 3354 |
+
0,
|
| 3355 |
+
0,
|
| 3356 |
+
0,
|
| 3357 |
+
0,
|
| 3358 |
+
0,
|
| 3359 |
+
0,
|
| 3360 |
+
0,
|
| 3361 |
+
0,
|
| 3362 |
+
0,
|
| 3363 |
+
0,
|
| 3364 |
+
0,
|
| 3365 |
+
0,
|
| 3366 |
+
0,
|
| 3367 |
+
0,
|
| 3368 |
+
0,
|
| 3369 |
+
0,
|
| 3370 |
+
0,
|
| 3371 |
+
0,
|
| 3372 |
+
0,
|
| 3373 |
+
0,
|
| 3374 |
+
0,
|
| 3375 |
+
0,
|
| 3376 |
+
0,
|
| 3377 |
+
0,
|
| 3378 |
+
0,
|
| 3379 |
+
0,
|
| 3380 |
+
0,
|
| 3381 |
+
0,
|
| 3382 |
+
0,
|
| 3383 |
+
0,
|
| 3384 |
+
0,
|
| 3385 |
+
0,
|
| 3386 |
+
0,
|
| 3387 |
+
0,
|
| 3388 |
+
0,
|
| 3389 |
+
0,
|
| 3390 |
+
0,
|
| 3391 |
+
0,
|
| 3392 |
+
0,
|
| 3393 |
+
0,
|
| 3394 |
+
0,
|
| 3395 |
+
0,
|
| 3396 |
+
0,
|
| 3397 |
+
0,
|
| 3398 |
+
0,
|
| 3399 |
+
0,
|
| 3400 |
+
0,
|
| 3401 |
+
0,
|
| 3402 |
+
0,
|
| 3403 |
+
0,
|
| 3404 |
+
0,
|
| 3405 |
+
0,
|
| 3406 |
+
0,
|
| 3407 |
+
0,
|
| 3408 |
+
0,
|
| 3409 |
+
0,
|
| 3410 |
+
0,
|
| 3411 |
+
0,
|
| 3412 |
+
0,
|
| 3413 |
+
0,
|
| 3414 |
+
0,
|
| 3415 |
+
0,
|
| 3416 |
+
0,
|
| 3417 |
+
0,
|
| 3418 |
+
0,
|
| 3419 |
+
0,
|
| 3420 |
+
0,
|
| 3421 |
+
0,
|
| 3422 |
+
0,
|
| 3423 |
+
0,
|
| 3424 |
+
0,
|
| 3425 |
+
0,
|
| 3426 |
+
0,
|
| 3427 |
+
0,
|
| 3428 |
+
0,
|
| 3429 |
+
0,
|
| 3430 |
+
0,
|
| 3431 |
+
0,
|
| 3432 |
+
0,
|
| 3433 |
+
0,
|
| 3434 |
+
0,
|
| 3435 |
+
0,
|
| 3436 |
+
0,
|
| 3437 |
+
0,
|
| 3438 |
+
0,
|
| 3439 |
+
0,
|
| 3440 |
+
0,
|
| 3441 |
+
0,
|
| 3442 |
+
0,
|
| 3443 |
+
0,
|
| 3444 |
+
0,
|
| 3445 |
+
0,
|
| 3446 |
+
0,
|
| 3447 |
+
0,
|
| 3448 |
+
0,
|
| 3449 |
+
0,
|
| 3450 |
+
0,
|
| 3451 |
+
0,
|
| 3452 |
+
0
|
| 3453 |
+
],
|
| 3454 |
+
"linkage_types_blank": [
|
| 3455 |
+
0,
|
| 3456 |
+
0,
|
| 3457 |
+
0,
|
| 3458 |
+
0,
|
| 3459 |
+
0,
|
| 3460 |
+
0,
|
| 3461 |
+
0,
|
| 3462 |
+
0,
|
| 3463 |
+
0,
|
| 3464 |
+
9,
|
| 3465 |
+
2,
|
| 3466 |
+
0,
|
| 3467 |
+
0,
|
| 3468 |
+
0,
|
| 3469 |
+
0,
|
| 3470 |
+
0,
|
| 3471 |
+
0,
|
| 3472 |
+
0,
|
| 3473 |
+
0,
|
| 3474 |
+
0,
|
| 3475 |
+
0,
|
| 3476 |
+
0,
|
| 3477 |
+
0,
|
| 3478 |
+
0,
|
| 3479 |
+
0,
|
| 3480 |
+
0,
|
| 3481 |
+
0,
|
| 3482 |
+
0,
|
| 3483 |
+
0,
|
| 3484 |
+
0,
|
| 3485 |
+
0,
|
| 3486 |
+
0,
|
| 3487 |
+
0,
|
| 3488 |
+
0,
|
| 3489 |
+
0,
|
| 3490 |
+
0,
|
| 3491 |
+
0,
|
| 3492 |
+
0,
|
| 3493 |
+
0,
|
| 3494 |
+
0,
|
| 3495 |
+
0,
|
| 3496 |
+
0,
|
| 3497 |
+
0,
|
| 3498 |
+
0,
|
| 3499 |
+
0,
|
| 3500 |
+
0,
|
| 3501 |
+
0,
|
| 3502 |
+
0,
|
| 3503 |
+
0,
|
| 3504 |
+
0,
|
| 3505 |
+
0,
|
| 3506 |
+
0,
|
| 3507 |
+
0,
|
| 3508 |
+
0,
|
| 3509 |
+
0,
|
| 3510 |
+
0,
|
| 3511 |
+
0,
|
| 3512 |
+
0,
|
| 3513 |
+
0,
|
| 3514 |
+
0,
|
| 3515 |
+
0,
|
| 3516 |
+
0,
|
| 3517 |
+
0,
|
| 3518 |
+
0,
|
| 3519 |
+
0,
|
| 3520 |
+
0,
|
| 3521 |
+
0,
|
| 3522 |
+
0,
|
| 3523 |
+
0,
|
| 3524 |
+
0,
|
| 3525 |
+
0,
|
| 3526 |
+
0,
|
| 3527 |
+
0,
|
| 3528 |
+
0,
|
| 3529 |
+
0,
|
| 3530 |
+
0,
|
| 3531 |
+
0,
|
| 3532 |
+
0,
|
| 3533 |
+
0,
|
| 3534 |
+
0,
|
| 3535 |
+
0,
|
| 3536 |
+
0,
|
| 3537 |
+
0,
|
| 3538 |
+
0,
|
| 3539 |
+
0,
|
| 3540 |
+
0,
|
| 3541 |
+
0,
|
| 3542 |
+
0,
|
| 3543 |
+
0,
|
| 3544 |
+
0,
|
| 3545 |
+
0,
|
| 3546 |
+
0,
|
| 3547 |
+
0,
|
| 3548 |
+
0,
|
| 3549 |
+
0,
|
| 3550 |
+
0,
|
| 3551 |
+
0,
|
| 3552 |
+
0,
|
| 3553 |
+
0,
|
| 3554 |
+
0,
|
| 3555 |
+
0,
|
| 3556 |
+
0,
|
| 3557 |
+
0,
|
| 3558 |
+
0,
|
| 3559 |
+
0,
|
| 3560 |
+
0,
|
| 3561 |
+
0,
|
| 3562 |
+
0,
|
| 3563 |
+
0,
|
| 3564 |
+
0,
|
| 3565 |
+
0,
|
| 3566 |
+
0,
|
| 3567 |
+
0,
|
| 3568 |
+
0,
|
| 3569 |
+
0,
|
| 3570 |
+
0,
|
| 3571 |
+
0,
|
| 3572 |
+
0,
|
| 3573 |
+
0,
|
| 3574 |
+
0,
|
| 3575 |
+
0,
|
| 3576 |
+
0,
|
| 3577 |
+
0,
|
| 3578 |
+
0,
|
| 3579 |
+
0,
|
| 3580 |
+
0,
|
| 3581 |
+
0,
|
| 3582 |
+
0,
|
| 3583 |
+
0,
|
| 3584 |
+
0,
|
| 3585 |
+
0,
|
| 3586 |
+
0,
|
| 3587 |
+
0,
|
| 3588 |
+
0,
|
| 3589 |
+
0,
|
| 3590 |
+
0,
|
| 3591 |
+
0,
|
| 3592 |
+
0,
|
| 3593 |
+
0,
|
| 3594 |
+
0,
|
| 3595 |
+
0,
|
| 3596 |
+
0,
|
| 3597 |
+
0,
|
| 3598 |
+
0,
|
| 3599 |
+
0,
|
| 3600 |
+
0,
|
| 3601 |
+
0,
|
| 3602 |
+
0,
|
| 3603 |
+
0,
|
| 3604 |
+
0,
|
| 3605 |
+
0,
|
| 3606 |
+
0,
|
| 3607 |
+
0,
|
| 3608 |
+
0,
|
| 3609 |
+
0,
|
| 3610 |
+
0,
|
| 3611 |
+
0,
|
| 3612 |
+
0,
|
| 3613 |
+
0,
|
| 3614 |
+
0,
|
| 3615 |
+
0,
|
| 3616 |
+
0,
|
| 3617 |
+
0,
|
| 3618 |
+
0,
|
| 3619 |
+
0,
|
| 3620 |
+
0,
|
| 3621 |
+
0,
|
| 3622 |
+
0,
|
| 3623 |
+
0,
|
| 3624 |
+
0,
|
| 3625 |
+
0,
|
| 3626 |
+
0,
|
| 3627 |
+
0,
|
| 3628 |
+
0,
|
| 3629 |
+
0,
|
| 3630 |
+
0,
|
| 3631 |
+
0,
|
| 3632 |
+
0,
|
| 3633 |
+
0,
|
| 3634 |
+
0,
|
| 3635 |
+
0,
|
| 3636 |
+
0,
|
| 3637 |
+
0,
|
| 3638 |
+
0,
|
| 3639 |
+
0,
|
| 3640 |
+
0,
|
| 3641 |
+
0,
|
| 3642 |
+
0,
|
| 3643 |
+
0,
|
| 3644 |
+
0,
|
| 3645 |
+
0,
|
| 3646 |
+
0,
|
| 3647 |
+
0,
|
| 3648 |
+
0,
|
| 3649 |
+
0,
|
| 3650 |
+
0,
|
| 3651 |
+
0,
|
| 3652 |
+
0,
|
| 3653 |
+
0,
|
| 3654 |
+
0,
|
| 3655 |
+
0,
|
| 3656 |
+
0,
|
| 3657 |
+
0,
|
| 3658 |
+
0,
|
| 3659 |
+
0,
|
| 3660 |
+
0,
|
| 3661 |
+
0,
|
| 3662 |
+
0,
|
| 3663 |
+
0,
|
| 3664 |
+
0,
|
| 3665 |
+
0,
|
| 3666 |
+
0,
|
| 3667 |
+
0,
|
| 3668 |
+
0,
|
| 3669 |
+
0,
|
| 3670 |
+
0,
|
| 3671 |
+
0,
|
| 3672 |
+
0,
|
| 3673 |
+
0,
|
| 3674 |
+
0,
|
| 3675 |
+
0,
|
| 3676 |
+
0,
|
| 3677 |
+
0,
|
| 3678 |
+
0,
|
| 3679 |
+
0,
|
| 3680 |
+
0,
|
| 3681 |
+
0,
|
| 3682 |
+
0,
|
| 3683 |
+
0,
|
| 3684 |
+
0,
|
| 3685 |
+
0,
|
| 3686 |
+
0,
|
| 3687 |
+
0,
|
| 3688 |
+
0,
|
| 3689 |
+
0,
|
| 3690 |
+
0,
|
| 3691 |
+
0,
|
| 3692 |
+
0,
|
| 3693 |
+
0,
|
| 3694 |
+
0,
|
| 3695 |
+
0,
|
| 3696 |
+
0,
|
| 3697 |
+
0,
|
| 3698 |
+
0,
|
| 3699 |
+
0,
|
| 3700 |
+
0,
|
| 3701 |
+
0,
|
| 3702 |
+
0,
|
| 3703 |
+
0,
|
| 3704 |
+
0,
|
| 3705 |
+
0,
|
| 3706 |
+
0,
|
| 3707 |
+
0,
|
| 3708 |
+
0,
|
| 3709 |
+
0,
|
| 3710 |
+
0
|
| 3711 |
+
],
|
| 3712 |
+
"enumerated_alternative": false,
|
| 3713 |
+
"unknown_question_mark": false,
|
| 3714 |
+
"wa3_truth_uses_invalid_token": false,
|
| 3715 |
+
"single_answer": true
|
| 3716 |
+
}
|
| 3717 |
+
}
|
| 3718 |
+
]
|
releases/2026-10-02/iar_inference/fixtures/reference_smoke_report.json
ADDED
|
@@ -0,0 +1,253 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"schema": "iar_two_real_saved_readout_full_model_smoke_v1",
|
| 3 |
+
"status": "PASS_FULL_WA3_STRICT_LOAD_AND_TWO_REAL_SAVED_READOUT_FORWARDS",
|
| 4 |
+
"started_unix": 1790740892.3816009,
|
| 5 |
+
"script_sha256": "d757fda5194ba6a6ce9fc03096b5596e47f7889844034aa70efbac33fb8235cb",
|
| 6 |
+
"scope": "Strict full WA3 plus two recorded single-linkage cases and fixed saved readout; no refit or metrics.",
|
| 7 |
+
"limits": [
|
| 8 |
+
"CPU smoke, not historical CUDA numerical replay or model-quality evidence.",
|
| 9 |
+
"No residue or multi-token fallback; no full corpus parity or seeded case reconstruction.",
|
| 10 |
+
"Original Nova native authority bootstrap can read complete sequence/topology packages."
|
| 11 |
+
],
|
| 12 |
+
"manifest_sha256": "440a748a14e9c09d017677ef3477d19ed02169a8e5ee048ff8b3f05bdaa1a12d",
|
| 13 |
+
"runtime": {
|
| 14 |
+
"python": "3.10.16",
|
| 15 |
+
"torch": "2.9.1+cu128",
|
| 16 |
+
"numpy": "2.2.6",
|
| 17 |
+
"device": "cpu",
|
| 18 |
+
"precision": "float32",
|
| 19 |
+
"threads": 4,
|
| 20 |
+
"host": "nova18-wide-4",
|
| 21 |
+
"slurm_job_id": "16662851"
|
| 22 |
+
},
|
| 23 |
+
"phase": "two_case_saved_readout_forward",
|
| 24 |
+
"inputs_sha256": "60ac0c0fd1b6e0ada2d847d1fccff4f6fe7c085aab3146247dc5d7bfebbabc27",
|
| 25 |
+
"full_model": {
|
| 26 |
+
"state_entries": 505,
|
| 27 |
+
"parameters": 138487995,
|
| 28 |
+
"strict_load": true,
|
| 29 |
+
"checkpoint_sha256": "8e7d95ee492df6d843f495dd4708c97ee16a947e75b5cd8f83b23e4f4a0d6d82",
|
| 30 |
+
"neutral_vector": {
|
| 31 |
+
"shape": [
|
| 32 |
+
768
|
| 33 |
+
],
|
| 34 |
+
"dtype": "float32",
|
| 35 |
+
"sha256_c_order_bytes": "297bc451bcb34097045af18278e9cbeabbf38fdb22777d77aee87001784d4b29"
|
| 36 |
+
},
|
| 37 |
+
"hidden_capture_input_of": "sequence_head"
|
| 38 |
+
},
|
| 39 |
+
"readout": {
|
| 40 |
+
"sha256": "a03990a02a1737de05a7fa1739164e84fa6a0a4170ebaa65317a9f3c2f16c0b0",
|
| 41 |
+
"classes": 211,
|
| 42 |
+
"fit": {
|
| 43 |
+
"dev_accuracy_for_selection": 0.7359,
|
| 44 |
+
"best_epoch": 46,
|
| 45 |
+
"tokens": 211,
|
| 46 |
+
"train_samples": 111989,
|
| 47 |
+
"development_samples": 27690,
|
| 48 |
+
"feature_dim": 768
|
| 49 |
+
},
|
| 50 |
+
"refit": false
|
| 51 |
+
},
|
| 52 |
+
"forward_calls": 2,
|
| 53 |
+
"cases": [
|
| 54 |
+
{
|
| 55 |
+
"dataset": "bench1392",
|
| 56 |
+
"case_id": "g0000_s00_linkage_38_38",
|
| 57 |
+
"used_saved_readout": true,
|
| 58 |
+
"wa3_position": 43,
|
| 59 |
+
"truth_token_id": 1720,
|
| 60 |
+
"truth_token": "g8-h2",
|
| 61 |
+
"final_token_id": 1720,
|
| 62 |
+
"final_token": "g8-h2",
|
| 63 |
+
"abstained": false,
|
| 64 |
+
"rounds": [
|
| 65 |
+
{
|
| 66 |
+
"iteration": 1,
|
| 67 |
+
"hidden_sha256_c_order_bytes": "ff29f35c4eb22549a5185b89c2bf9dabe5ff7f4a3fdc44291cbfa724eb5349ee",
|
| 68 |
+
"top10": [
|
| 69 |
+
{
|
| 70 |
+
"token_id": 1720,
|
| 71 |
+
"token": "g8-h2",
|
| 72 |
+
"probability": 0.9999593496322632
|
| 73 |
+
},
|
| 74 |
+
{
|
| 75 |
+
"token_id": 1261,
|
| 76 |
+
"token": "g3-h2",
|
| 77 |
+
"probability": 4.006435483461246e-05
|
| 78 |
+
},
|
| 79 |
+
{
|
| 80 |
+
"token_id": 1380,
|
| 81 |
+
"token": "h8-i2",
|
| 82 |
+
"probability": 2.607788189834537e-07
|
| 83 |
+
},
|
| 84 |
+
{
|
| 85 |
+
"token_id": 1122,
|
| 86 |
+
"token": "d3-e2",
|
| 87 |
+
"probability": 1.445049662152087e-07
|
| 88 |
+
},
|
| 89 |
+
{
|
| 90 |
+
"token_id": 531,
|
| 91 |
+
"token": "g2-h1",
|
| 92 |
+
"probability": 1.0591251964342518e-07
|
| 93 |
+
},
|
| 94 |
+
{
|
| 95 |
+
"token_id": 544,
|
| 96 |
+
"token": "g3-h1",
|
| 97 |
+
"probability": 6.952672038096352e-08
|
| 98 |
+
},
|
| 99 |
+
{
|
| 100 |
+
"token_id": 1548,
|
| 101 |
+
"token": "m6-n2",
|
| 102 |
+
"probability": 1.4976388129639417e-08
|
| 103 |
+
},
|
| 104 |
+
{
|
| 105 |
+
"token_id": 1572,
|
| 106 |
+
"token": "h3-i2",
|
| 107 |
+
"probability": 8.80937189862152e-09
|
| 108 |
+
},
|
| 109 |
+
{
|
| 110 |
+
"token_id": 710,
|
| 111 |
+
"token": "f3-g2",
|
| 112 |
+
"probability": 6.006392716528808e-09
|
| 113 |
+
},
|
| 114 |
+
{
|
| 115 |
+
"token_id": 486,
|
| 116 |
+
"token": "g4-h1",
|
| 117 |
+
"probability": 4.912561468728427e-09
|
| 118 |
+
}
|
| 119 |
+
],
|
| 120 |
+
"accepted": true
|
| 121 |
+
}
|
| 122 |
+
]
|
| 123 |
+
},
|
| 124 |
+
{
|
| 125 |
+
"dataset": "seal162",
|
| 126 |
+
"case_id": "g0000_s00_linkage_9_9",
|
| 127 |
+
"used_saved_readout": true,
|
| 128 |
+
"wa3_position": 9,
|
| 129 |
+
"truth_token_id": 228,
|
| 130 |
+
"truth_token": "a4-b1",
|
| 131 |
+
"final_token_id": 4,
|
| 132 |
+
"final_token": "[MASK]",
|
| 133 |
+
"abstained": true,
|
| 134 |
+
"rounds": [
|
| 135 |
+
{
|
| 136 |
+
"iteration": 1,
|
| 137 |
+
"hidden_sha256_c_order_bytes": "1cd693d3ea8df175d65f0eca3673ce2a73dff666d1cf06aa84bf4943127c3be8",
|
| 138 |
+
"top10": [
|
| 139 |
+
{
|
| 140 |
+
"token_id": 228,
|
| 141 |
+
"token": "a4-b1",
|
| 142 |
+
"probability": 0.7713369131088257
|
| 143 |
+
},
|
| 144 |
+
{
|
| 145 |
+
"token_id": 262,
|
| 146 |
+
"token": "a3-b1",
|
| 147 |
+
"probability": 0.2158111184835434
|
| 148 |
+
},
|
| 149 |
+
{
|
| 150 |
+
"token_id": 404,
|
| 151 |
+
"token": "a6-b1",
|
| 152 |
+
"probability": 0.01060701534152031
|
| 153 |
+
},
|
| 154 |
+
{
|
| 155 |
+
"token_id": 399,
|
| 156 |
+
"token": "a2-b1",
|
| 157 |
+
"probability": 0.002030769130215049
|
| 158 |
+
},
|
| 159 |
+
{
|
| 160 |
+
"token_id": 518,
|
| 161 |
+
"token": "a5-b1",
|
| 162 |
+
"probability": 9.787840826902539e-05
|
| 163 |
+
},
|
| 164 |
+
{
|
| 165 |
+
"token_id": 1282,
|
| 166 |
+
"token": "a7-b1",
|
| 167 |
+
"probability": 7.618743984494358e-05
|
| 168 |
+
},
|
| 169 |
+
{
|
| 170 |
+
"token_id": 710,
|
| 171 |
+
"token": "f3-g2",
|
| 172 |
+
"probability": 1.4471691429207567e-05
|
| 173 |
+
},
|
| 174 |
+
{
|
| 175 |
+
"token_id": 1252,
|
| 176 |
+
"token": "d6-g1",
|
| 177 |
+
"probability": 8.236345820478164e-06
|
| 178 |
+
},
|
| 179 |
+
{
|
| 180 |
+
"token_id": 1331,
|
| 181 |
+
"token": "c3-d2",
|
| 182 |
+
"probability": 2.9395614546956494e-06
|
| 183 |
+
},
|
| 184 |
+
{
|
| 185 |
+
"token_id": 466,
|
| 186 |
+
"token": "h4-i1",
|
| 187 |
+
"probability": 1.904394366647466e-06
|
| 188 |
+
}
|
| 189 |
+
],
|
| 190 |
+
"accepted": false
|
| 191 |
+
},
|
| 192 |
+
{
|
| 193 |
+
"iteration": 2,
|
| 194 |
+
"hidden_sha256_c_order_bytes": "1cd693d3ea8df175d65f0eca3673ce2a73dff666d1cf06aa84bf4943127c3be8",
|
| 195 |
+
"top10": [
|
| 196 |
+
{
|
| 197 |
+
"token_id": 228,
|
| 198 |
+
"token": "a4-b1",
|
| 199 |
+
"probability": 0.7713369131088257
|
| 200 |
+
},
|
| 201 |
+
{
|
| 202 |
+
"token_id": 262,
|
| 203 |
+
"token": "a3-b1",
|
| 204 |
+
"probability": 0.2158111184835434
|
| 205 |
+
},
|
| 206 |
+
{
|
| 207 |
+
"token_id": 404,
|
| 208 |
+
"token": "a6-b1",
|
| 209 |
+
"probability": 0.01060701534152031
|
| 210 |
+
},
|
| 211 |
+
{
|
| 212 |
+
"token_id": 399,
|
| 213 |
+
"token": "a2-b1",
|
| 214 |
+
"probability": 0.002030769130215049
|
| 215 |
+
},
|
| 216 |
+
{
|
| 217 |
+
"token_id": 518,
|
| 218 |
+
"token": "a5-b1",
|
| 219 |
+
"probability": 9.787840826902539e-05
|
| 220 |
+
},
|
| 221 |
+
{
|
| 222 |
+
"token_id": 1282,
|
| 223 |
+
"token": "a7-b1",
|
| 224 |
+
"probability": 7.618743984494358e-05
|
| 225 |
+
},
|
| 226 |
+
{
|
| 227 |
+
"token_id": 710,
|
| 228 |
+
"token": "f3-g2",
|
| 229 |
+
"probability": 1.4471691429207567e-05
|
| 230 |
+
},
|
| 231 |
+
{
|
| 232 |
+
"token_id": 1252,
|
| 233 |
+
"token": "d6-g1",
|
| 234 |
+
"probability": 8.236345820478164e-06
|
| 235 |
+
},
|
| 236 |
+
{
|
| 237 |
+
"token_id": 1331,
|
| 238 |
+
"token": "c3-d2",
|
| 239 |
+
"probability": 2.9395614546956494e-06
|
| 240 |
+
},
|
| 241 |
+
{
|
| 242 |
+
"token_id": 466,
|
| 243 |
+
"token": "h4-i1",
|
| 244 |
+
"probability": 1.904394366647466e-06
|
| 245 |
+
}
|
| 246 |
+
],
|
| 247 |
+
"accepted": false
|
| 248 |
+
}
|
| 249 |
+
]
|
| 250 |
+
}
|
| 251 |
+
],
|
| 252 |
+
"finished_unix": 1790740986.703624
|
| 253 |
+
}
|
releases/2026-10-02/iar_inference/infer.py
ADDED
|
@@ -0,0 +1,290 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""Strict full-WA3 CPU inference on two recorded single-linkage IAR cases.
|
| 3 |
+
|
| 4 |
+
The full model uses unchanged, pinned released classes and authority checks.
|
| 5 |
+
This entry point neither fits a readout nor imports the historical main script.
|
| 6 |
+
"""
|
| 7 |
+
from pathlib import Path
|
| 8 |
+
import argparse
|
| 9 |
+
import ast
|
| 10 |
+
import hashlib
|
| 11 |
+
import importlib.util
|
| 12 |
+
import json
|
| 13 |
+
import os
|
| 14 |
+
import platform
|
| 15 |
+
import sys
|
| 16 |
+
import time
|
| 17 |
+
from types import SimpleNamespace
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
ROOT = Path(__file__).resolve().parent
|
| 21 |
+
sys.dont_write_bytecode = True
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
def require(condition, message):
|
| 25 |
+
if not condition:
|
| 26 |
+
raise ValueError(message)
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
def sha256(path):
|
| 30 |
+
digest = hashlib.sha256()
|
| 31 |
+
with Path(path).open("rb") as handle:
|
| 32 |
+
for block in iter(lambda: handle.read(4 << 20), b""):
|
| 33 |
+
digest.update(block)
|
| 34 |
+
return digest.hexdigest()
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
def load_module(name, path):
|
| 38 |
+
spec = importlib.util.spec_from_file_location(name, path)
|
| 39 |
+
require(spec is not None and spec.loader is not None, "Cannot import " + str(path))
|
| 40 |
+
module = importlib.util.module_from_spec(spec)
|
| 41 |
+
sys.modules[name] = module
|
| 42 |
+
spec.loader.exec_module(module)
|
| 43 |
+
return module
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
def read_config(path=ROOT / "config.json", source_root=None, readout_root=None):
|
| 47 |
+
path = Path(path).resolve()
|
| 48 |
+
config = json.loads(path.read_text())
|
| 49 |
+
require(config["schema"] == "bertose_portable_two_case_iar_v1", "Unknown config schema")
|
| 50 |
+
source = Path(source_root).resolve() if source_root else (path.parent / config["source_root"]).resolve()
|
| 51 |
+
readout = Path(readout_root).resolve() if readout_root else (path.parent / config["readout_root"]).resolve()
|
| 52 |
+
return config, source, readout
|
| 53 |
+
|
| 54 |
+
|
| 55 |
+
def preflight(config, source_root, readout_root):
|
| 56 |
+
"""Check small source/authority/fixture bytes without torch or a checkpoint."""
|
| 57 |
+
verified = []
|
| 58 |
+
for root, key in ((source_root, "source_files"), (readout_root, "readout_files"), (ROOT, "local_files")):
|
| 59 |
+
for item in config[key]:
|
| 60 |
+
path = root / item["path"]
|
| 61 |
+
require(path.is_file() and path.stat().st_size == item["bytes"], "Missing/changed file: " + str(path))
|
| 62 |
+
require(sha256(path) == item["sha256"], "SHA-256 differs: " + str(path))
|
| 63 |
+
verified.append({"path": str(path), "sha256": item["sha256"]})
|
| 64 |
+
# Verify that the copied helpers retain the original function ASTs. Do not
|
| 65 |
+
# import the monolithic historical source (it changes builtins.open).
|
| 66 |
+
def functions(path):
|
| 67 |
+
return {n.name: ast.dump(n, include_attributes=False) for n in ast.parse(path.read_text()).body
|
| 68 |
+
if isinstance(n, ast.FunctionDef)}
|
| 69 |
+
original = functions(readout_root / "originals/wa3_final_iar_readout_all.py")
|
| 70 |
+
portable = functions(ROOT / "original_inference_helpers.py")
|
| 71 |
+
names = config["original_helper_functions"]
|
| 72 |
+
require(set(portable) == set(names), "Unexpected portable inference helper")
|
| 73 |
+
require(all(portable[n] == original[n] for n in names), "Original helper semantics changed")
|
| 74 |
+
records = json.loads((ROOT / "fixtures/rebuilt_two_case_inputs.json").read_text())
|
| 75 |
+
require(len(records) == 2, "Expected exactly two recorded cases")
|
| 76 |
+
for record in records:
|
| 77 |
+
case = record["rebuilt_case"]
|
| 78 |
+
require(len(case["positions"]) == len(case["units"]) == len(case["truth_ids"]) == 1,
|
| 79 |
+
"Only one masked token and one semantic unit are supported")
|
| 80 |
+
require(case["single_answer"] and case["units"][0]["unit_type"] == "linkage", "Not an ordinary single linkage")
|
| 81 |
+
for key in ("masked_ids", "attention_mask", "residue_ids", "branch_depths_blank", "linkage_types_blank"):
|
| 82 |
+
require(len(case[key]) == 256 and all(type(v) is int for v in case[key]), "Invalid input channel: " + key)
|
| 83 |
+
position = case["positions"][0]
|
| 84 |
+
require(0 <= position < 256 and case["attention_mask"][position] == 1
|
| 85 |
+
and case["masked_ids"][position] == 4 and case["residue_ids"][position] == -2
|
| 86 |
+
and case["branch_depths_blank"][position] == 0 and case["linkage_types_blank"][position] == 9,
|
| 87 |
+
"Masked linkage channel contract changed")
|
| 88 |
+
return records, verified
|
| 89 |
+
|
| 90 |
+
|
| 91 |
+
def load_model(checkpoint, config, source_root):
|
| 92 |
+
"""Load the pinned full checkpoint through the original production classes.
|
| 93 |
+
|
| 94 |
+
Caller must run preflight first. The R5 constructor independently reopens
|
| 95 |
+
all twelve component authorities with its original no-follow traversal.
|
| 96 |
+
"""
|
| 97 |
+
import torch
|
| 98 |
+
checkpoint = Path(checkpoint).resolve()
|
| 99 |
+
expected = config["checkpoint"]
|
| 100 |
+
# Keep the same descriptor for hashing and deserialization. weights_only=False
|
| 101 |
+
# is permitted only for these exact, predeclared historical checkpoint bytes.
|
| 102 |
+
with checkpoint.open("rb") as handle:
|
| 103 |
+
before = os.fstat(handle.fileno())
|
| 104 |
+
digest = hashlib.sha256()
|
| 105 |
+
for block in iter(lambda: handle.read(4 << 20), b""):
|
| 106 |
+
digest.update(block)
|
| 107 |
+
require(digest.hexdigest() == expected["sha256"], "Full checkpoint SHA-256 differs; refusing deserialization")
|
| 108 |
+
handle.seek(0)
|
| 109 |
+
saved = torch.load(handle, map_location="cpu", weights_only=False)
|
| 110 |
+
after = os.fstat(handle.fileno())
|
| 111 |
+
require((before.st_dev, before.st_ino, before.st_size, before.st_mtime_ns)
|
| 112 |
+
== (after.st_dev, after.st_ino, after.st_size, after.st_mtime_ns), "Checkpoint changed during load")
|
| 113 |
+
require(saved.get("md_cell_id") == expected["md_cell_id"]
|
| 114 |
+
and int(saved["selection"]["best_epoch"]) == expected["best_epoch"], "Checkpoint cell/epoch identity differs")
|
| 115 |
+
r5 = load_module("_portable_iar_r5", source_root / config["model_sources"]["r5"])
|
| 116 |
+
md = load_module("_portable_iar_md", source_root / config["model_sources"]["md_core"])
|
| 117 |
+
# The original factory accesses exactly these two attributes of the executor.
|
| 118 |
+
# No training planner, scheduler or static-release launcher is needed here.
|
| 119 |
+
executor_binding = SimpleNamespace(_composite=r5, NativeEightCompositeR5=r5.NativeEightCompositeR5)
|
| 120 |
+
model_type = md.make_md_enabled_composite_class(executor_binding)
|
| 121 |
+
model = model_type(r5.NativeEightConfig(cell_id=expected["base_cell_id"], seq_vocab_size=expected["vocabulary_size"]),
|
| 122 |
+
md_cell_id=expected["md_cell_id"], md_temporal_size=expected["md_temporal_size"])
|
| 123 |
+
require(len(saved["model_state"]) == expected["state_entries"], "Checkpoint state count differs")
|
| 124 |
+
model.load_state_dict(saved["model_state"], strict=True)
|
| 125 |
+
del saved
|
| 126 |
+
require(len(model.state_dict()) == expected["state_entries"]
|
| 127 |
+
and sum(p.numel() for p in model.parameters()) == expected["parameter_count"], "Full model inventory differs")
|
| 128 |
+
require(all(p.dtype == torch.float32 for p in model.parameters()), "Expected float32 model parameters")
|
| 129 |
+
model.eval().requires_grad_(False)
|
| 130 |
+
model.verify_live_contract()
|
| 131 |
+
bindings = dict(model.reverify_component_authorities())
|
| 132 |
+
require(bindings == dict(r5.EXPECTED_COMPONENT_BINDINGS), "Component authority bindings differ")
|
| 133 |
+
return model, bindings
|
| 134 |
+
|
| 135 |
+
|
| 136 |
+
def run_cases(model, records, config, readout_root, output_dir):
|
| 137 |
+
import numpy as np
|
| 138 |
+
import torch
|
| 139 |
+
helper = load_module("_portable_iar_helpers", ROOT / "original_inference_helpers.py")
|
| 140 |
+
readout = load_module("_portable_iar_readout", readout_root / "readout.py")
|
| 141 |
+
payload, linear, metadata = readout.load_readout(readout_root)
|
| 142 |
+
contract = config["inference"]
|
| 143 |
+
require(metadata["linkage_input"]["training_counts"] == contract["neutral_training_counts"]
|
| 144 |
+
and metadata["evaluation"]["threshold"] == contract["threshold"]
|
| 145 |
+
and metadata["evaluation"]["rounds"] == contract["maximum_rounds"], "Readout inference contract differs")
|
| 146 |
+
require(metadata["encoder"]["checkpoint_sha256"] == config["checkpoint"]["sha256"], "Readout encoder binding differs")
|
| 147 |
+
vocab = json.loads((readout_root / metadata["vocabulary"]["path"]).read_text())["token_to_id"]
|
| 148 |
+
id_to_token = {v: k for k, v in vocab.items()}
|
| 149 |
+
cases = [r["rebuilt_case"] for r in records]
|
| 150 |
+
require(all(c["truth_ids"][0] in payload["token_ids"] for c in cases), "Fixture truth is outside saved readout")
|
| 151 |
+
lk_name, linkage = helper.find_linkage_embedding(model)
|
| 152 |
+
head_name, head = helper.find_lm_projection(model)
|
| 153 |
+
require(lk_name == contract["neutral_module"] and head_name == contract["hidden_module"], "Hook module differs")
|
| 154 |
+
counts = np.asarray(contract["neutral_training_counts"], dtype=np.float64)
|
| 155 |
+
weights = torch.as_tensor(counts / counts.sum(), dtype=torch.float32)
|
| 156 |
+
helper.HOOK["vec"] = (linkage.weight[1:9].detach().float() * weights[:, None]).sum(0)
|
| 157 |
+
neutral_sha = hashlib.sha256(helper.HOOK["vec"].numpy().tobytes()).hexdigest()
|
| 158 |
+
hooks = [linkage.register_forward_hook(helper._linkage_hook), head.register_forward_hook(helper._cap_hook)]
|
| 159 |
+
current = [list(c["masked_ids"]) for c in cases]
|
| 160 |
+
unresolved = [True] * len(cases)
|
| 161 |
+
histories = [[] for _ in cases]
|
| 162 |
+
comparisons = []
|
| 163 |
+
positions = [(i, c["positions"][0]) for i, c in enumerate(cases)]
|
| 164 |
+
tensor = lambda key: torch.tensor([c[key] for c in cases], dtype=torch.long)
|
| 165 |
+
reference = json.loads((ROOT / "fixtures/reference_smoke_report.json").read_text())
|
| 166 |
+
try:
|
| 167 |
+
for iteration in range(contract["maximum_rounds"]):
|
| 168 |
+
helper.CAP["h"] = None
|
| 169 |
+
logits = helper._forward(model, "cpu", torch.tensor(current, dtype=torch.long),
|
| 170 |
+
tensor("attention_mask"), tensor("residue_ids"), tensor("branch_depths_blank"),
|
| 171 |
+
tensor("linkage_types_blank"), positions)
|
| 172 |
+
require(tuple(logits.shape) == (2, 256, 2114) and torch.isfinite(logits).all().item(), "Invalid full MLM output")
|
| 173 |
+
progress = 0
|
| 174 |
+
for i, case in enumerate(cases):
|
| 175 |
+
if not unresolved[i]:
|
| 176 |
+
continue
|
| 177 |
+
position = case["positions"][0]
|
| 178 |
+
hidden = helper._gather_h(2, 256, i, position).float().cpu().numpy()[None, :]
|
| 179 |
+
require(hidden.shape == (1, 768) and np.isfinite(hidden).all(), "Invalid hidden feature")
|
| 180 |
+
if iteration == 0:
|
| 181 |
+
expected_hidden = np.load(ROOT / ("fixtures/case%d_pre_sequence_head.npy" % i), allow_pickle=False)
|
| 182 |
+
matches = bool(np.allclose(hidden, expected_hidden, atol=contract["hidden_allclose_atol"],
|
| 183 |
+
rtol=contract["hidden_allclose_rtol"]))
|
| 184 |
+
comparisons.append({"case_id": case["case_id"], "hidden_allclose": matches,
|
| 185 |
+
"hidden_max_abs_difference": float(np.max(np.abs(hidden - expected_hidden))),
|
| 186 |
+
"hidden_bitwise_equal": bool(np.array_equal(hidden, expected_hidden))})
|
| 187 |
+
require(matches, "Hidden feature differs from executed reference for " + case["case_id"])
|
| 188 |
+
with (output_dir / ("case%d_pre_sequence_head.npy" % i)).open("xb") as handle:
|
| 189 |
+
np.save(handle, hidden, allow_pickle=False)
|
| 190 |
+
probabilities = readout.probabilities(hidden, payload, linear)[0]
|
| 191 |
+
pp, indices = torch.topk(torch.from_numpy(probabilities), k=10)
|
| 192 |
+
ids = [int(payload["token_ids"][int(j)]) for j in indices]
|
| 193 |
+
# Every saved class is verified by load_readout as an ordinary
|
| 194 |
+
# linkage token; it therefore cannot be a special/ambiguous ID.
|
| 195 |
+
accepted = float(pp[0]) >= contract["threshold"]
|
| 196 |
+
histories[i].append({"iteration": iteration + 1,
|
| 197 |
+
"hidden_sha256_c_order_bytes": hashlib.sha256(hidden.tobytes()).hexdigest(),
|
| 198 |
+
"top10": [{"token_id": token, "token": id_to_token[token], "probability": float(p)}
|
| 199 |
+
for token, p in zip(ids, pp)], "accepted": accepted})
|
| 200 |
+
if accepted:
|
| 201 |
+
current[i][position] = ids[0]
|
| 202 |
+
unresolved[i] = False
|
| 203 |
+
progress += 1
|
| 204 |
+
if progress == 0:
|
| 205 |
+
break
|
| 206 |
+
finally:
|
| 207 |
+
for hook in hooks:
|
| 208 |
+
hook.remove()
|
| 209 |
+
helper.HOOK["mask"] = None
|
| 210 |
+
helper.CAP["h"] = None
|
| 211 |
+
results = [{"dataset": record["dataset"], "case_id": case["case_id"], "used_saved_readout": True,
|
| 212 |
+
"wa3_position": case["positions"][0], "truth_token_id": case["truth_ids"][0],
|
| 213 |
+
"truth_token": id_to_token[case["truth_ids"][0]], "final_token_id": current[i][case["positions"][0]],
|
| 214 |
+
"final_token": id_to_token[current[i][case["positions"][0]]], "abstained": unresolved[i], "rounds": histories[i]}
|
| 215 |
+
for i, (record, case) in enumerate(zip(records, cases))]
|
| 216 |
+
for result, expected in zip(results, reference["cases"]):
|
| 217 |
+
for key in ("dataset", "case_id", "wa3_position", "truth_token_id", "final_token_id", "abstained"):
|
| 218 |
+
require(result[key] == expected[key], "Reference result differs: " + key)
|
| 219 |
+
require(len(result["rounds"]) == len(expected["rounds"]), "Reference round count differs")
|
| 220 |
+
for actual_round, expected_round in zip(result["rounds"], expected["rounds"]):
|
| 221 |
+
require(actual_round["accepted"] == expected_round["accepted"], "Reference acceptance differs")
|
| 222 |
+
require([x["token_id"] for x in actual_round["top10"]] == [x["token_id"] for x in expected_round["top10"]],
|
| 223 |
+
"Reference top-10 token order differs")
|
| 224 |
+
require(np.allclose([x["probability"] for x in actual_round["top10"]],
|
| 225 |
+
[x["probability"] for x in expected_round["top10"]],
|
| 226 |
+
atol=contract["probability_allclose_atol"], rtol=contract["probability_allclose_rtol"]),
|
| 227 |
+
"Reference probabilities differ")
|
| 228 |
+
return {"cases": results, "forward_calls": iteration + 1, "reference_comparisons": comparisons,
|
| 229 |
+
"neutral_vector_sha256_c_order_bytes": neutral_sha,
|
| 230 |
+
"neutral_vector_bitwise_reference_match": neutral_sha == reference["full_model"]["neutral_vector"]["sha256_c_order_bytes"],
|
| 231 |
+
"readout": {"sha256": metadata["readout"]["sha256"], "classes": len(payload["token_ids"]), "fit": metadata["fit"], "refit": False}}
|
| 232 |
+
|
| 233 |
+
|
| 234 |
+
def main():
|
| 235 |
+
parser = argparse.ArgumentParser(description=__doc__)
|
| 236 |
+
parser.add_argument("--config", type=Path, default=ROOT / "config.json")
|
| 237 |
+
parser.add_argument("--source-root", type=Path, help="Released bertose_source root; preserves its relative layout")
|
| 238 |
+
parser.add_argument("--readout-root", type=Path, help="Released iar_completion root")
|
| 239 |
+
parser.add_argument("--checkpoint", type=Path, help="Full pinned WA3 review_md20x6_checkpoint_best.pt")
|
| 240 |
+
parser.add_argument("--output-dir", type=Path, help="New directory for report and two hidden feature arrays")
|
| 241 |
+
parser.add_argument("--threads", type=int, default=4, choices=range(1, 9))
|
| 242 |
+
parser.add_argument("--preflight-only", action="store_true", help="Small-file integrity and input checks only; no torch/checkpoint load")
|
| 243 |
+
args = parser.parse_args()
|
| 244 |
+
config, source, readout = read_config(args.config, args.source_root, args.readout_root)
|
| 245 |
+
records, verified = preflight(config, source, readout)
|
| 246 |
+
if args.preflight_only:
|
| 247 |
+
print(json.dumps({"status": "PASS_PREFLIGHT_ONLY", "verified_files": len(verified), "cases": len(records),
|
| 248 |
+
"checkpoint_loaded": False, "model_forward_executed": False}, indent=2))
|
| 249 |
+
return
|
| 250 |
+
if args.checkpoint is None or args.output_dir is None:
|
| 251 |
+
parser.error("--checkpoint and --output-dir are required for inference")
|
| 252 |
+
output = args.output_dir.absolute()
|
| 253 |
+
require(output.parent.is_dir() and not output.exists(), "Output directory must be new with an existing parent")
|
| 254 |
+
output.mkdir()
|
| 255 |
+
report = {"schema": "bertose_portable_two_case_iar_result_v1", "status": "RUNNING", "started_unix": time.time(),
|
| 256 |
+
"scope": config["scope"], "config_sha256": sha256(args.config), "inference_script_sha256": sha256(Path(__file__)),
|
| 257 |
+
"checkpoint_path": str(args.checkpoint.resolve()), "verified_files": verified,
|
| 258 |
+
"limits": ["Two recorded single-linkage inputs only; no general raw-WURCS conversion or corpus parity.",
|
| 259 |
+
"Physical modalities are explicitly absent; their active paths and residue/multitoken fallback are untested.",
|
| 260 |
+
"This is CPU inference, not a historical CUDA numerical replay or a model-quality estimate.",
|
| 261 |
+
"Original component/model guards are retained. Training/static-release launch bootstrap is outside this inference scope."]}
|
| 262 |
+
try:
|
| 263 |
+
import numpy as np
|
| 264 |
+
import torch
|
| 265 |
+
torch.set_num_threads(args.threads)
|
| 266 |
+
torch.set_num_interop_threads(1)
|
| 267 |
+
report["runtime"] = {"python": platform.python_version(), "torch": torch.__version__, "numpy": np.__version__,
|
| 268 |
+
"device": "cpu", "precision": "float32", "threads": args.threads, "host": platform.node()}
|
| 269 |
+
report["phase"] = "strict_full_checkpoint_load"
|
| 270 |
+
model, bindings = load_model(args.checkpoint, config, source)
|
| 271 |
+
report["full_model"] = {"state_entries": len(model.state_dict()), "parameters": sum(p.numel() for p in model.parameters()),
|
| 272 |
+
"strict_load": True, "checkpoint_sha256": config["checkpoint"]["sha256"],
|
| 273 |
+
"component_authorities": bindings}
|
| 274 |
+
report["phase"] = "two_recorded_case_inference_and_reference_comparison"
|
| 275 |
+
report.update(run_cases(model, records, config, readout, output))
|
| 276 |
+
report["status"] = "PASS_PORTABLE_FULL_WA3_TWO_CASE_REFERENCE_CHECK"
|
| 277 |
+
except (Exception, SystemExit) as error:
|
| 278 |
+
report["status"] = "FAIL"
|
| 279 |
+
report["error"] = type(error).__name__ + ": " + str(error)
|
| 280 |
+
raise
|
| 281 |
+
finally:
|
| 282 |
+
report["finished_unix"] = time.time()
|
| 283 |
+
with (output / "inference_report.json").open("x") as handle:
|
| 284 |
+
json.dump(report, handle, indent=2, allow_nan=False)
|
| 285 |
+
handle.write("\n")
|
| 286 |
+
print(json.dumps({"status": report["status"], "report": str(output / "inference_report.json")}, indent=2))
|
| 287 |
+
|
| 288 |
+
|
| 289 |
+
if __name__ == "__main__":
|
| 290 |
+
main()
|
releases/2026-10-02/iar_inference/original_inference_helpers.py
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Verbatim selected functions from the hash-bound final IAR source.
|
| 2 |
+
|
| 3 |
+
Only these inference helpers are copied. The original module's import-time open
|
| 4 |
+
replacement, Nova paths, fitting functions and main() are not imported or run.
|
| 5 |
+
See config.json for the original source pin and helper names.
|
| 6 |
+
"""
|
| 7 |
+
import torch
|
| 8 |
+
|
| 9 |
+
HOOK = {"mask": None, "vec": None}
|
| 10 |
+
CAP = {"h": None}
|
| 11 |
+
|
| 12 |
+
def fail(msg: str):
|
| 13 |
+
raise SystemExit("FAIL-CLOSED: " + msg)
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
def all_absent(B, dev): # contract from iar_bytype3_20260825_r1/bytype.py (job 12094273)
|
| 17 |
+
return {"ms_token_ids": torch.empty((0, 64), dtype=torch.long, device=dev),
|
| 18 |
+
"ms_attention_mask": torch.zeros((0, 64), dtype=torch.bool, device=dev),
|
| 19 |
+
"ms_input_mask": torch.zeros((0, 64), dtype=torch.bool, device=dev), "ms_labels": None,
|
| 20 |
+
"ms_acquisition_parent_indices": torch.empty((0,), dtype=torch.long, device=dev),
|
| 21 |
+
"ms_parent_available": torch.zeros((B,), dtype=torch.bool, device=dev), "ms_mode": "development",
|
| 22 |
+
"static_token_ids": torch.zeros((B, 1, 4), dtype=torch.long, device=dev),
|
| 23 |
+
"static_attention_mask": torch.zeros((B, 1, 4), dtype=torch.bool, device=dev),
|
| 24 |
+
"static_residue_ids": torch.full((B, 1, 4), -1, dtype=torch.long, device=dev),
|
| 25 |
+
"static_slot_ids": torch.full((B, 1, 4), -1, dtype=torch.long, device=dev),
|
| 26 |
+
"static_state_mask": torch.zeros((B, 1), dtype=torch.bool, device=dev),
|
| 27 |
+
"static_state_ids": torch.full((B, 1), -1, dtype=torch.long, device=dev),
|
| 28 |
+
"static_input_mask": torch.zeros((B, 1, 4), dtype=torch.bool, device=dev), "static_labels": None,
|
| 29 |
+
"static_parent_available": torch.zeros((B,), dtype=torch.bool, device=dev),
|
| 30 |
+
"md_values": torch.zeros((B, 2, 20, 6), dtype=torch.float32, device=dev),
|
| 31 |
+
"md_feature_mask": torch.zeros((B, 2, 20, 6), dtype=torch.bool, device=dev),
|
| 32 |
+
"md_child_present_mask": torch.zeros((B, 2), dtype=torch.bool, device=dev),
|
| 33 |
+
"md_state_row_ids": torch.full((B, 2), -1, dtype=torch.long, device=dev),
|
| 34 |
+
"md_window_input_mask": torch.zeros((B, 2, 20), dtype=torch.bool, device=dev), "md_labels": None,
|
| 35 |
+
"md_parent_available": torch.zeros((B,), dtype=torch.bool, device=dev)}
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
def _linkage_hook(module, inputs, output):
|
| 39 |
+
m = HOOK["mask"]
|
| 40 |
+
if m is None:
|
| 41 |
+
return None
|
| 42 |
+
if output.dim() == 3 and tuple(output.shape[:2]) == tuple(m.shape):
|
| 43 |
+
idx = m
|
| 44 |
+
elif output.dim() == 2 and output.shape[0] == m.numel():
|
| 45 |
+
idx = m.reshape(-1)
|
| 46 |
+
else:
|
| 47 |
+
fail("linkage embedding output %s does not match mask %s" % (tuple(output.shape), tuple(m.shape)))
|
| 48 |
+
out = output.clone()
|
| 49 |
+
out[idx] = HOOK["vec"].to(out.dtype)
|
| 50 |
+
return out
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
def find_linkage_embedding(model):
|
| 54 |
+
cands = [(n, m) for n, m in model.named_modules() if isinstance(m, torch.nn.Embedding) and m.num_embeddings == 10]
|
| 55 |
+
named = [(n, m) for n, m in cands if "linkage" in n.lower()]
|
| 56 |
+
if len(named) != 1:
|
| 57 |
+
fail("linkage embedding not unique: %s" % [n for n, _ in cands])
|
| 58 |
+
return named[0]
|
| 59 |
+
|
| 60 |
+
|
| 61 |
+
def _cap_hook(module, inputs, output):
|
| 62 |
+
CAP["h"] = inputs[0].detach()
|
| 63 |
+
|
| 64 |
+
|
| 65 |
+
def find_lm_projection(model):
|
| 66 |
+
cands = [(n, m) for n, m in model.named_modules() if isinstance(m, torch.nn.Linear) and m.out_features == 2114]
|
| 67 |
+
if len(cands) > 1:
|
| 68 |
+
pref = [(n, m) for n, m in cands if any(k in n.lower() for k in ("seq", "mlm", "lm_", "sequence"))]
|
| 69 |
+
cands = pref if len(pref) == 1 else cands
|
| 70 |
+
if len(cands) != 1:
|
| 71 |
+
fail("LM projection not unique: %s" % [n for n, _ in cands])
|
| 72 |
+
return cands[0]
|
| 73 |
+
|
| 74 |
+
|
| 75 |
+
def _gather_h(B, L, bi, pos):
|
| 76 |
+
H = CAP["h"]
|
| 77 |
+
if H.dim() == 3 and H.shape[0] == B and H.shape[1] == L:
|
| 78 |
+
return H[bi, pos]
|
| 79 |
+
if H.dim() == 2 and H.shape[0] == B * L:
|
| 80 |
+
return H.reshape(B, L, -1)[bi, pos]
|
| 81 |
+
fail("unexpected LM-projection input shape %s for batch %d x %d" % (tuple(H.shape), B, L))
|
| 82 |
+
|
| 83 |
+
|
| 84 |
+
def _forward(model, dev, tok, am, rid, bd, lt, neutral_pos):
|
| 85 |
+
HOOK["mask"] = None
|
| 86 |
+
if neutral_pos is not None:
|
| 87 |
+
m = torch.zeros(tok.shape, dtype=torch.bool)
|
| 88 |
+
for bi, p in neutral_pos:
|
| 89 |
+
m[bi, p] = True
|
| 90 |
+
HOOK["mask"] = m.to(dev)
|
| 91 |
+
with torch.inference_mode():
|
| 92 |
+
o = model(seq_token_ids=tok.to(dev), seq_attention_mask=am.bool().to(dev), seq_residue_ids=rid.to(dev),
|
| 93 |
+
seq_branch_depths=bd.to(dev), seq_linkage_types=lt.to(dev),
|
| 94 |
+
seq_labels=None, topology_labels=None, topology_available=None,
|
| 95 |
+
**all_absent(tok.shape[0], torch.device(dev)))
|
| 96 |
+
HOOK["mask"] = None
|
| 97 |
+
return o.sequence_logits.float()
|
releases/2026-10-02/iar_inference/preparation_validation.json
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"schema": "iar_portable_preparation_validation_v1",
|
| 3 |
+
"status": "PASS_PREPARATION_ONLY_FULL_FORWARD_PENDING",
|
| 4 |
+
"checked_at_utc": "2026-09-30T21:33:17.598488+00:00",
|
| 5 |
+
"python": "3.12.4",
|
| 6 |
+
"syntax": "PASS_2_PYTHON_FILES",
|
| 7 |
+
"small_file_preflight": "PASS",
|
| 8 |
+
"verified_files": 24,
|
| 9 |
+
"recorded_cases": 2,
|
| 10 |
+
"helper_ast_equivalence": "PASS_8_FUNCTIONS",
|
| 11 |
+
"negative_integrity_check": "PASS_CHANGED_FIXTURE_PIN_REJECTED",
|
| 12 |
+
"checkpoint_loaded": false,
|
| 13 |
+
"model_constructed": false,
|
| 14 |
+
"model_forward_executed": false,
|
| 15 |
+
"remote_contact": false,
|
| 16 |
+
"limit": "This receipt validates source/fixture preparation only. Require the independent full-model portable smoke receipt before calling portable inference verified."
|
| 17 |
+
}
|
releases/2026-10-02/iar_inference/requirements.txt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Executed CPU reference versions (Python 3.10.16).
|
| 2 |
+
numpy==2.2.6
|
| 3 |
+
torch==2.9.1
|
releases/2026-10-02/notebooks/BERTose_workbench.ipynb
ADDED
|
@@ -0,0 +1,583 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"cells": [
|
| 3 |
+
{
|
| 4 |
+
"cell_type": "markdown",
|
| 5 |
+
"id": "f77c7ed4",
|
| 6 |
+
"metadata": {},
|
| 7 |
+
"source": [
|
| 8 |
+
"# BERTose workbench\n",
|
| 9 |
+
"\n",
|
| 10 |
+
"Turn WURCS 2.0 glycans into 768-dimensional sequence embeddings, inspect similarity, make a small PCA plot, and export data for your own analysis or application.\n",
|
| 11 |
+
"\n",
|
| 12 |
+
"This notebook uses the released **variant 3** encoder. You can choose variants 1–5. The weights were learned with multimodal supervision; this interface takes WURCS sequence inputs. It does not generate MS, static 3D, or MD inputs.\n",
|
| 13 |
+
"\n",
|
| 14 |
+
"A normal **Run All** embeds six shipped examples and checks the small IAR files. Binding and full IAR are separate opt-in sections. Similarity and PCA are exploratory views, with no fitted downstream head or model-quality claim.\n",
|
| 15 |
+
"\n",
|
| 16 |
+
"The notebook works in Colab, a local Jupyter kernel, or a backend Python environment. Start with a CPU kernel and allow memory for the encoder and activations. Downloads use public Hugging Face repositories; no token is needed for public access."
|
| 17 |
+
]
|
| 18 |
+
},
|
| 19 |
+
{
|
| 20 |
+
"cell_type": "markdown",
|
| 21 |
+
"id": "86a15c72",
|
| 22 |
+
"metadata": {},
|
| 23 |
+
"source": [
|
| 24 |
+
"## 1. Get the versioned code\n",
|
| 25 |
+
"\n",
|
| 26 |
+
"The bootstrap downloads only `releases/2026-10-02/**` from the Hugging Face code repository. It does not fetch its older code tree or model weights.\n",
|
| 27 |
+
"\n",
|
| 28 |
+
"For an existing checkout, set `BERTose_CODE_DIR` to the directory containing `bertose_workbench.py`. For offline use, also set `BERTose_OFFLINE=1`, `BERTose_INSTALL=0`, and `BERTose_CHECKPOINT` to your downloaded variant checkpoint before starting the kernel. The offline path never installs packages or downloads files. Dependencies must already be available.\n",
|
| 29 |
+
"\n",
|
| 30 |
+
"You can pin code and encoder commits with `BERTose_CODE_REVISION` and `BERTose_ENCODER_REVISION`. A code snapshot and the selected encoder's hash checks provide separate provenance."
|
| 31 |
+
]
|
| 32 |
+
},
|
| 33 |
+
{
|
| 34 |
+
"cell_type": "code",
|
| 35 |
+
"execution_count": null,
|
| 36 |
+
"id": "07f338df",
|
| 37 |
+
"metadata": {},
|
| 38 |
+
"outputs": [],
|
| 39 |
+
"source": [
|
| 40 |
+
"import os\n",
|
| 41 |
+
"import sys\n",
|
| 42 |
+
"import subprocess\n",
|
| 43 |
+
"import importlib.util\n",
|
| 44 |
+
"from pathlib import Path\n",
|
| 45 |
+
"\n",
|
| 46 |
+
"OFFLINE = os.environ.get(\"BERTose_OFFLINE\", \"0\") == \"1\"\n",
|
| 47 |
+
"INSTALL_DEPENDENCIES = os.environ.get(\"BERTose_INSTALL\", \"1\") == \"1\" and not OFFLINE\n",
|
| 48 |
+
"CODE_REVISION = os.environ.get(\"BERTose_CODE_REVISION\", \"main\")\n",
|
| 49 |
+
"ENCODER_REVISION = os.environ.get(\"BERTose_ENCODER_REVISION\", \"main\")\n",
|
| 50 |
+
"CODE_REPO = \"supanthadey1/bertose-affinose-training-code\"\n",
|
| 51 |
+
"RELEASE_PATH = \"releases/2026-10-02\"\n",
|
| 52 |
+
"\n",
|
| 53 |
+
"local_code = os.environ.get(\"BERTose_CODE_DIR\")\n",
|
| 54 |
+
"if local_code:\n",
|
| 55 |
+
" CODE_DIR = Path(local_code).expanduser().resolve()\n",
|
| 56 |
+
"else:\n",
|
| 57 |
+
" # A notebook opened from its downloaded code/notebooks folder can reuse it.\n",
|
| 58 |
+
" candidates = (Path.cwd(), Path.cwd().parent)\n",
|
| 59 |
+
" CODE_DIR = next((p.resolve() for p in candidates if (p / \"bertose_workbench.py\").is_file()), None)\n",
|
| 60 |
+
" if CODE_DIR is None:\n",
|
| 61 |
+
" if OFFLINE:\n",
|
| 62 |
+
" raise RuntimeError(\"Offline: set BERTose_CODE_DIR to the downloaded code directory.\")\n",
|
| 63 |
+
" if importlib.util.find_spec(\"huggingface_hub\") is None:\n",
|
| 64 |
+
" if not INSTALL_DEPENDENCIES:\n",
|
| 65 |
+
" raise ImportError(\"Install huggingface_hub or set BERTose_CODE_DIR to local code.\")\n",
|
| 66 |
+
" subprocess.run([sys.executable, \"-m\", \"pip\", \"install\", \"huggingface_hub>=1.1,<2\"], check=True)\n",
|
| 67 |
+
" from huggingface_hub import snapshot_download\n",
|
| 68 |
+
" snapshot = Path(snapshot_download(\n",
|
| 69 |
+
" repo_id=CODE_REPO, repo_type=\"model\", revision=CODE_REVISION,\n",
|
| 70 |
+
" allow_patterns=[f\"{RELEASE_PATH}/**\"],\n",
|
| 71 |
+
" ))\n",
|
| 72 |
+
" CODE_DIR = snapshot / RELEASE_PATH\n",
|
| 73 |
+
"\n",
|
| 74 |
+
"if not (CODE_DIR / \"bertose_workbench.py\").is_file():\n",
|
| 75 |
+
" raise FileNotFoundError(f\"The workbench module is absent from {CODE_DIR}. Check the release revision.\")\n",
|
| 76 |
+
"sys.path.insert(0, str(CODE_DIR))\n",
|
| 77 |
+
"sys.dont_write_bytecode = True\n",
|
| 78 |
+
"print(\"Code directory:\", CODE_DIR)\n",
|
| 79 |
+
"print(\"Offline:\", OFFLINE, \"| package installation:\", INSTALL_DEPENDENCIES)"
|
| 80 |
+
]
|
| 81 |
+
},
|
| 82 |
+
{
|
| 83 |
+
"cell_type": "markdown",
|
| 84 |
+
"id": "4b53e279",
|
| 85 |
+
"metadata": {},
|
| 86 |
+
"source": [
|
| 87 |
+
"## 2. Prepare the environment\n",
|
| 88 |
+
"\n",
|
| 89 |
+
"The following cell installs `requirements-workbench.txt` in the current kernel's Python when installation is enabled. That file adds Hugging Face access, plotting and notebook support to the encoder dependencies. Restart the kernel if Jupyter requests it after an installation. Installation errors stop the run."
|
| 90 |
+
]
|
| 91 |
+
},
|
| 92 |
+
{
|
| 93 |
+
"cell_type": "code",
|
| 94 |
+
"execution_count": null,
|
| 95 |
+
"id": "ffe5b4ab",
|
| 96 |
+
"metadata": {},
|
| 97 |
+
"outputs": [],
|
| 98 |
+
"source": [
|
| 99 |
+
"if INSTALL_DEPENDENCIES:\n",
|
| 100 |
+
" subprocess.run([\n",
|
| 101 |
+
" sys.executable, \"-m\", \"pip\", \"install\", \"-r\",\n",
|
| 102 |
+
" str(CODE_DIR / \"requirements-workbench.txt\"),\n",
|
| 103 |
+
" ], check=True)\n",
|
| 104 |
+
"else:\n",
|
| 105 |
+
" print(\"Using the current environment; no packages installed.\")\n",
|
| 106 |
+
"\n",
|
| 107 |
+
"import csv\n",
|
| 108 |
+
"import json\n",
|
| 109 |
+
"import time\n",
|
| 110 |
+
"import shlex\n",
|
| 111 |
+
"import numpy as np\n",
|
| 112 |
+
"import torch\n",
|
| 113 |
+
"import matplotlib.pyplot as plt\n",
|
| 114 |
+
"from bertose_workbench import Encoder, cosine_similarity, nearest_neighbors, pca\n",
|
| 115 |
+
"\n",
|
| 116 |
+
"torch.set_num_threads(4)\n",
|
| 117 |
+
"VARIANT = \"3\"\n",
|
| 118 |
+
"DEVICE = \"cpu\" # Change to \"cuda\" only in a suitable local runtime.\n",
|
| 119 |
+
"BATCH_SIZE = 8\n",
|
| 120 |
+
"checkpoint_env = os.environ.get(\"BERTose_CHECKPOINT\")\n",
|
| 121 |
+
"LOCAL_CHECKPOINT = Path(checkpoint_env).expanduser().resolve() if checkpoint_env else None\n",
|
| 122 |
+
"if OFFLINE and LOCAL_CHECKPOINT is None:\n",
|
| 123 |
+
" raise RuntimeError(\"Offline: set BERTose_CHECKPOINT to the downloaded variant-3 sequence_encoder.pt.\")\n",
|
| 124 |
+
"\n",
|
| 125 |
+
"run_name = time.strftime(\"run_%Y%m%d_%H%M%S\") + f\"_{time.time_ns() % 1_000_000:06d}\"\n",
|
| 126 |
+
"OUTPUT_DIR = Path(os.environ.get(\"BERTose_OUTPUT_DIR\", str(Path.cwd() / \"bertose_outputs\" / run_name))).expanduser().resolve()\n",
|
| 127 |
+
"OUTPUT_DIR.mkdir(parents=True, exist_ok=True)\n",
|
| 128 |
+
"ASSETS_DIR = Path(os.environ.get(\"BERTose_ASSETS_DIR\", str(Path.cwd() / \"bertose_assets\"))).expanduser().resolve()\n",
|
| 129 |
+
"print({\"python\": sys.version.split()[0], \"torch\": torch.__version__, \"numpy\": np.__version__,\n",
|
| 130 |
+
" \"variant\": VARIANT, \"device\": DEVICE, \"batch_size\": BATCH_SIZE, \"threads\": torch.get_num_threads()})\n",
|
| 131 |
+
"print(\"Results:\", OUTPUT_DIR)"
|
| 132 |
+
]
|
| 133 |
+
},
|
| 134 |
+
{
|
| 135 |
+
"cell_type": "markdown",
|
| 136 |
+
"id": "c8d734d5",
|
| 137 |
+
"metadata": {},
|
| 138 |
+
"source": [
|
| 139 |
+
"## 3. Load once, then embed batches\n",
|
| 140 |
+
"\n",
|
| 141 |
+
"`Encoder.from_pretrained` retrieves the selected sequence export from Hugging Face and verifies it against the release manifest. Supply `local_checkpoint=...` to use an existing file. The same API is usable in a Python script or backend service; load the encoder once per worker.\n",
|
| 142 |
+
"\n",
|
| 143 |
+
"`pooling=\"first\"` returns the START-envelope token state. `pooling=\"mean\"` averages all attended states, including START and END. These are representation choices, not trained binding scores."
|
| 144 |
+
]
|
| 145 |
+
},
|
| 146 |
+
{
|
| 147 |
+
"cell_type": "code",
|
| 148 |
+
"execution_count": null,
|
| 149 |
+
"id": "d2339c0d",
|
| 150 |
+
"metadata": {},
|
| 151 |
+
"outputs": [],
|
| 152 |
+
"source": [
|
| 153 |
+
"encoder = Encoder.from_pretrained(\n",
|
| 154 |
+
" variant=VARIANT,\n",
|
| 155 |
+
" revision=ENCODER_REVISION,\n",
|
| 156 |
+
" device=DEVICE,\n",
|
| 157 |
+
" local_checkpoint=LOCAL_CHECKPOINT,\n",
|
| 158 |
+
")\n",
|
| 159 |
+
"print(\"Encoder loaded.\")"
|
| 160 |
+
]
|
| 161 |
+
},
|
| 162 |
+
{
|
| 163 |
+
"cell_type": "markdown",
|
| 164 |
+
"id": "7f45afc6",
|
| 165 |
+
"metadata": {},
|
| 166 |
+
"source": [
|
| 167 |
+
"## 4. Six real release inputs\n",
|
| 168 |
+
"\n",
|
| 169 |
+
"The first two WURCS strings come from `examples/glycans.csv`. Four distinct glycans come from the released held-out binding example CSVs. We keep their file and row provenance; these six examples are a demonstration, not a representative evaluation set.\n",
|
| 170 |
+
"\n",
|
| 171 |
+
"To try your own glycans, set `CUSTOM_SAMPLES` below to a list of dictionaries containing unique `sample_id` and `wurcs` strings. A single glycan is also supported; the notebook skips nearest-neighbor and PCA views until there are two or more inputs. Use WURCS 2.0, not IUPAC names or protein sequences. Inspect unknown-token and tree-channel diagnostics. The loader rejects overlength inputs rather than truncating them."
|
| 172 |
+
]
|
| 173 |
+
},
|
| 174 |
+
{
|
| 175 |
+
"cell_type": "code",
|
| 176 |
+
"execution_count": null,
|
| 177 |
+
"id": "1f36c033",
|
| 178 |
+
"metadata": {},
|
| 179 |
+
"outputs": [],
|
| 180 |
+
"source": [
|
| 181 |
+
"CUSTOM_SAMPLES = None # Replace None with your list of sample_id/wurcs dictionaries.\n",
|
| 182 |
+
"samples = []\n",
|
| 183 |
+
"if CUSTOM_SAMPLES is None:\n",
|
| 184 |
+
" seen_wurcs = set()\n",
|
| 185 |
+
" example_sources = [\n",
|
| 186 |
+
" (\"examples/glycans.csv\", \"wurcs\"),\n",
|
| 187 |
+
" (\"bertosebind_inference/examples/glycan_cold.csv\", \"glycan_wurcs\"),\n",
|
| 188 |
+
" (\"bertosebind_inference/examples/protein_cold.csv\", \"glycan_wurcs\"),\n",
|
| 189 |
+
" ]\n",
|
| 190 |
+
" for relative_path, wurcs_column in example_sources:\n",
|
| 191 |
+
" with (CODE_DIR / relative_path).open(newline=\"\") as handle:\n",
|
| 192 |
+
" for source_row, row in enumerate(csv.DictReader(handle), start=2):\n",
|
| 193 |
+
" if row[wurcs_column] not in seen_wurcs:\n",
|
| 194 |
+
" seen_wurcs.add(row[wurcs_column])\n",
|
| 195 |
+
" samples.append({\n",
|
| 196 |
+
" \"sample_id\": row[\"sample_id\"], \"wurcs\": row[wurcs_column],\n",
|
| 197 |
+
" \"source_file\": relative_path, \"source_csv_row\": source_row,\n",
|
| 198 |
+
" })\n",
|
| 199 |
+
" assert len(samples) == 6\n",
|
| 200 |
+
"else:\n",
|
| 201 |
+
" samples = list(CUSTOM_SAMPLES)\n",
|
| 202 |
+
"if not samples:\n",
|
| 203 |
+
" raise ValueError(\"Provide at least one glycan input.\")\n",
|
| 204 |
+
"if any(not row.get(\"sample_id\") for row in samples) or len({row[\"sample_id\"] for row in samples}) != len(samples):\n",
|
| 205 |
+
" raise ValueError(\"Samples require unique, nonempty sample_id values.\")\n",
|
| 206 |
+
"for row in samples:\n",
|
| 207 |
+
" print(row[\"sample_id\"], \"\\n \", row[\"wurcs\"], \"\\n source:\", row.get(\"source_file\", \"custom input\"),\n",
|
| 208 |
+
" \"row\", row.get(\"source_csv_row\", \"\"))"
|
| 209 |
+
]
|
| 210 |
+
},
|
| 211 |
+
{
|
| 212 |
+
"cell_type": "code",
|
| 213 |
+
"execution_count": null,
|
| 214 |
+
"id": "1114f6ab",
|
| 215 |
+
"metadata": {},
|
| 216 |
+
"outputs": [],
|
| 217 |
+
"source": [
|
| 218 |
+
"wurcs = [row[\"wurcs\"] for row in samples]\n",
|
| 219 |
+
"vectors, diagnostics = encoder.encode_with_diagnostics(\n",
|
| 220 |
+
" wurcs, batch_size=BATCH_SIZE, pooling=\"first\",\n",
|
| 221 |
+
")\n",
|
| 222 |
+
"assert vectors.shape == (len(samples), 768) and np.isfinite(vectors).all()\n",
|
| 223 |
+
"print(\"Embedding shape:\", vectors.shape, \"| dtype:\", vectors.dtype)\n",
|
| 224 |
+
"for row, diagnostic in zip(samples, diagnostics):\n",
|
| 225 |
+
" print(row[\"sample_id\"], diagnostic)"
|
| 226 |
+
]
|
| 227 |
+
},
|
| 228 |
+
{
|
| 229 |
+
"cell_type": "markdown",
|
| 230 |
+
"id": "1006eff2",
|
| 231 |
+
"metadata": {},
|
| 232 |
+
"source": [
|
| 233 |
+
"## 5. Compare representations\n",
|
| 234 |
+
"\n",
|
| 235 |
+
"A cosine value describes direction in this representation space. It is not a binding probability, chemical-equivalence test, or validated biological distance. Here the query is the second shipped example and its reference pool excludes the query itself."
|
| 236 |
+
]
|
| 237 |
+
},
|
| 238 |
+
{
|
| 239 |
+
"cell_type": "code",
|
| 240 |
+
"execution_count": null,
|
| 241 |
+
"id": "712c2527",
|
| 242 |
+
"metadata": {},
|
| 243 |
+
"outputs": [],
|
| 244 |
+
"source": [
|
| 245 |
+
"similarity = cosine_similarity(vectors, vectors)\n",
|
| 246 |
+
"assert similarity.shape == (len(samples), len(samples))\n",
|
| 247 |
+
"print(\"Cosine matrix (rows/columns follow samples):\")\n",
|
| 248 |
+
"print(np.array2string(similarity, precision=4))\n",
|
| 249 |
+
"\n",
|
| 250 |
+
"neighbor_rows = []\n",
|
| 251 |
+
"query_index = min(1, len(samples) - 1)\n",
|
| 252 |
+
"reference_indices = np.asarray([i for i in range(len(samples)) if i != query_index])\n",
|
| 253 |
+
"if len(reference_indices):\n",
|
| 254 |
+
" neighbor_indices, neighbor_scores = nearest_neighbors(\n",
|
| 255 |
+
" vectors[query_index:query_index + 1], vectors[reference_indices], k=min(3, len(reference_indices)),\n",
|
| 256 |
+
" )\n",
|
| 257 |
+
" neighbor_rows = [{\n",
|
| 258 |
+
" \"query_id\": samples[query_index][\"sample_id\"], \"rank\": rank + 1,\n",
|
| 259 |
+
" \"neighbor_id\": samples[int(reference_indices[neighbor])][\"sample_id\"],\n",
|
| 260 |
+
" \"cosine\": float(score),\n",
|
| 261 |
+
" } for rank, (neighbor, score) in enumerate(zip(neighbor_indices[0], neighbor_scores[0]))]\n",
|
| 262 |
+
" for row in neighbor_rows:\n",
|
| 263 |
+
" print(row)\n",
|
| 264 |
+
"else:\n",
|
| 265 |
+
" print(\"Nearest neighbors need at least two inputs; the single embedding is ready.\")"
|
| 266 |
+
]
|
| 267 |
+
},
|
| 268 |
+
{
|
| 269 |
+
"cell_type": "markdown",
|
| 270 |
+
"id": "3bf46f04",
|
| 271 |
+
"metadata": {},
|
| 272 |
+
"source": [
|
| 273 |
+
"## 6. A small exploratory PCA view\n",
|
| 274 |
+
"\n",
|
| 275 |
+
"PCA is fit only on these six embeddings. The plotted axes and neighborhoods change when the input set or pooling changes. This plot does not measure downstream performance or establish glycan classes."
|
| 276 |
+
]
|
| 277 |
+
},
|
| 278 |
+
{
|
| 279 |
+
"cell_type": "code",
|
| 280 |
+
"execution_count": null,
|
| 281 |
+
"id": "b97028b5",
|
| 282 |
+
"metadata": {},
|
| 283 |
+
"outputs": [],
|
| 284 |
+
"source": [
|
| 285 |
+
"coordinates = None\n",
|
| 286 |
+
"if len(samples) >= 2:\n",
|
| 287 |
+
" coordinates = pca(vectors, n_components=2)\n",
|
| 288 |
+
" assert coordinates.shape == (len(samples), 2) and np.isfinite(coordinates).all()\n",
|
| 289 |
+
" fig, (ax, key_ax) = plt.subplots(1, 2, figsize=(10, 5), gridspec_kw={\"width_ratios\": [3, 2]})\n",
|
| 290 |
+
" ax.scatter(coordinates[:, 0], coordinates[:, 1], s=60, color=\"#4C78A8\")\n",
|
| 291 |
+
" for i, row in enumerate(samples):\n",
|
| 292 |
+
" ax.annotate(str(i + 1), coordinates[i], xytext=(5, 5), textcoords=\"offset points\", fontsize=10)\n",
|
| 293 |
+
" ax.set(xlabel=\"PC 1\", ylabel=\"PC 2\")\n",
|
| 294 |
+
" ax.grid(alpha=0.2)\n",
|
| 295 |
+
" key_ax.axis(\"off\")\n",
|
| 296 |
+
" key_ax.text(0.0, 0.95, \"Sample key\", va=\"top\", fontsize=11, fontweight=\"bold\")\n",
|
| 297 |
+
" key_ax.text(0.0, 0.85, \"\\n\".join(f\"{i + 1}. {row['sample_id']}\" for i, row in enumerate(samples)),\n",
|
| 298 |
+
" va=\"top\", fontsize=9, linespacing=1.8)\n",
|
| 299 |
+
" key_ax.text(0.0, 0.25, \"Exploratory representation view\", fontsize=9, color=\"0.35\")\n",
|
| 300 |
+
" fig.suptitle(f\"{len(samples)} glycan inputs · variant {VARIANT} · first-token pooling\", fontsize=13)\n",
|
| 301 |
+
" fig.tight_layout(rect=[0, 0, 1, 0.95])\n",
|
| 302 |
+
" fig.savefig(OUTPUT_DIR / \"pca.png\", dpi=180, bbox_inches=\"tight\")\n",
|
| 303 |
+
" plt.show()\n",
|
| 304 |
+
"else:\n",
|
| 305 |
+
" print(\"A two-axis PCA view needs at least two inputs; the single embedding is ready.\")"
|
| 306 |
+
]
|
| 307 |
+
},
|
| 308 |
+
{
|
| 309 |
+
"cell_type": "markdown",
|
| 310 |
+
"id": "f1ee2c41",
|
| 311 |
+
"metadata": {},
|
| 312 |
+
"source": [
|
| 313 |
+
"## 7. Save inputs, vectors and provenance\n",
|
| 314 |
+
"\n",
|
| 315 |
+
"The NPZ stores all 768 columns plus sample IDs and WURCS. CSV files store the same vectors, PCA coordinates and nearest neighbors. A JSON sidecar records the selected settings, input provenance and diagnostics. These files can be read by another notebook or a backend collaborator."
|
| 316 |
+
]
|
| 317 |
+
},
|
| 318 |
+
{
|
| 319 |
+
"cell_type": "code",
|
| 320 |
+
"execution_count": null,
|
| 321 |
+
"id": "d24de9e3",
|
| 322 |
+
"metadata": {},
|
| 323 |
+
"outputs": [],
|
| 324 |
+
"source": [
|
| 325 |
+
"input_csv = OUTPUT_DIR / \"glycans.csv\"\n",
|
| 326 |
+
"with input_csv.open(\"w\", newline=\"\") as handle:\n",
|
| 327 |
+
" writer = csv.DictWriter(handle, fieldnames=[\"sample_id\", \"wurcs\"])\n",
|
| 328 |
+
" writer.writeheader()\n",
|
| 329 |
+
" writer.writerows({k: row[k] for k in writer.fieldnames} for row in samples)\n",
|
| 330 |
+
"\n",
|
| 331 |
+
"np.savez_compressed(\n",
|
| 332 |
+
" OUTPUT_DIR / \"embeddings.npz\",\n",
|
| 333 |
+
" sample_id=np.asarray([row[\"sample_id\"] for row in samples]),\n",
|
| 334 |
+
" wurcs=np.asarray(wurcs), embeddings=vectors,\n",
|
| 335 |
+
")\n",
|
| 336 |
+
"with (OUTPUT_DIR / \"embeddings.csv\").open(\"w\", newline=\"\") as handle:\n",
|
| 337 |
+
" writer = csv.writer(handle)\n",
|
| 338 |
+
" writer.writerow([\"sample_id\"] + [f\"embedding_{i}\" for i in range(vectors.shape[1])])\n",
|
| 339 |
+
" writer.writerows([row[\"sample_id\"], *vector.tolist()] for row, vector in zip(samples, vectors))\n",
|
| 340 |
+
"if coordinates is not None:\n",
|
| 341 |
+
" with (OUTPUT_DIR / \"pca.csv\").open(\"w\", newline=\"\") as handle:\n",
|
| 342 |
+
" writer = csv.writer(handle)\n",
|
| 343 |
+
" writer.writerow([\"sample_id\", \"pc1\", \"pc2\"])\n",
|
| 344 |
+
" writer.writerows([row[\"sample_id\"], *point.tolist()] for row, point in zip(samples, coordinates))\n",
|
| 345 |
+
"with (OUTPUT_DIR / \"neighbors.csv\").open(\"w\", newline=\"\") as handle:\n",
|
| 346 |
+
" writer = csv.DictWriter(handle, fieldnames=[\"query_id\", \"rank\", \"neighbor_id\", \"cosine\"])\n",
|
| 347 |
+
" writer.writeheader()\n",
|
| 348 |
+
" writer.writerows(neighbor_rows)\n",
|
| 349 |
+
"\n",
|
| 350 |
+
"run_metadata = {\n",
|
| 351 |
+
" \"code_repo\": CODE_REPO, \"code_revision_requested\": CODE_REVISION, \"code_dir\": str(CODE_DIR),\n",
|
| 352 |
+
" \"encoder_revision_requested\": ENCODER_REVISION, \"variant\": VARIANT, \"device\": DEVICE,\n",
|
| 353 |
+
" \"checkpoint\": str(encoder.checkpoint), \"encoder_metadata\": encoder.metadata,\n",
|
| 354 |
+
" \"pooling\": \"first\", \"batch_size\": BATCH_SIZE, \"shape\": list(vectors.shape),\n",
|
| 355 |
+
" \"samples\": samples, \"diagnostics\": diagnostics,\n",
|
| 356 |
+
" \"scope\": \"Sequence embeddings and exploratory views; no fitted task head or benchmark evaluation.\",\n",
|
| 357 |
+
"}\n",
|
| 358 |
+
"(OUTPUT_DIR / \"run.json\").write_text(json.dumps(run_metadata, indent=2, allow_nan=False) + \"\\n\")\n",
|
| 359 |
+
"reloaded = np.load(OUTPUT_DIR / \"embeddings.npz\", allow_pickle=False)\n",
|
| 360 |
+
"assert np.array_equal(reloaded[\"embeddings\"], vectors)\n",
|
| 361 |
+
"print(\"Wrote:\", \", \".join(sorted(p.name for p in OUTPUT_DIR.iterdir())))"
|
| 362 |
+
]
|
| 363 |
+
},
|
| 364 |
+
{
|
| 365 |
+
"cell_type": "markdown",
|
| 366 |
+
"id": "d1fee9ab",
|
| 367 |
+
"metadata": {},
|
| 368 |
+
"source": [
|
| 369 |
+
"## 8. Reuse the API in an application\n",
|
| 370 |
+
"\n",
|
| 371 |
+
"This is an ordinary Python function: adapt its dictionary response to your web framework. The shared `encoder` is already loaded. Preserve diagnostics and model settings in application outputs. Do not call `from_pretrained` for every request."
|
| 372 |
+
]
|
| 373 |
+
},
|
| 374 |
+
{
|
| 375 |
+
"cell_type": "code",
|
| 376 |
+
"execution_count": null,
|
| 377 |
+
"id": "25b08f63",
|
| 378 |
+
"metadata": {},
|
| 379 |
+
"outputs": [],
|
| 380 |
+
"source": [
|
| 381 |
+
"def embed_records(records, pooling=\"first\"):\n",
|
| 382 |
+
" matrix, info = encoder.encode_with_diagnostics(\n",
|
| 383 |
+
" [row[\"wurcs\"] for row in records], batch_size=BATCH_SIZE, pooling=pooling,\n",
|
| 384 |
+
" )\n",
|
| 385 |
+
" return {\n",
|
| 386 |
+
" \"variant\": VARIANT, \"pooling\": pooling, \"dimensions\": int(matrix.shape[1]),\n",
|
| 387 |
+
" \"results\": [{\"sample_id\": row[\"sample_id\"], \"embedding\": vector.tolist(), \"diagnostics\": diagnostic}\n",
|
| 388 |
+
" for row, vector, diagnostic in zip(records, matrix, info)],\n",
|
| 389 |
+
" }\n",
|
| 390 |
+
"\n",
|
| 391 |
+
"# One real request, using mean pooling to demonstrate the alternative.\n",
|
| 392 |
+
"api_response = embed_records(samples[:1], pooling=\"mean\")\n",
|
| 393 |
+
"assert len(api_response[\"results\"][0][\"embedding\"]) == 768\n",
|
| 394 |
+
"print({\"variant\": api_response[\"variant\"], \"pooling\": api_response[\"pooling\"],\n",
|
| 395 |
+
" \"dimensions\": api_response[\"dimensions\"], \"sample_id\": api_response[\"results\"][0][\"sample_id\"],\n",
|
| 396 |
+
" \"diagnostics\": api_response[\"results\"][0][\"diagnostics\"]})"
|
| 397 |
+
]
|
| 398 |
+
},
|
| 399 |
+
{
|
| 400 |
+
"cell_type": "markdown",
|
| 401 |
+
"id": "5cf5688a",
|
| 402 |
+
"metadata": {},
|
| 403 |
+
"source": [
|
| 404 |
+
"## 9. Embed an input CSV from the terminal\n",
|
| 405 |
+
"\n",
|
| 406 |
+
"`embed.py` is the released CSV interface. Input columns are `sample_id,wurcs`; sample IDs must be unique. The optional cell below runs it on our saved input and compares its vectors with the API output. The CLI requires a new output path and writes a JSON sidecar. It reuses the already verified checkpoint loaded by the API."
|
| 407 |
+
]
|
| 408 |
+
},
|
| 409 |
+
{
|
| 410 |
+
"cell_type": "code",
|
| 411 |
+
"execution_count": null,
|
| 412 |
+
"id": "ea4276f0",
|
| 413 |
+
"metadata": {},
|
| 414 |
+
"outputs": [],
|
| 415 |
+
"source": [
|
| 416 |
+
"RUN_EMBED_CLI = False # Set True to execute the CLI demonstration.\n",
|
| 417 |
+
"if RUN_EMBED_CLI:\n",
|
| 418 |
+
" cli_checkpoint = encoder.checkpoint\n",
|
| 419 |
+
" cli_output = OUTPUT_DIR / f\"cli_embeddings_{time.time_ns()}.npz\"\n",
|
| 420 |
+
" cli_command = [\n",
|
| 421 |
+
" sys.executable, str(CODE_DIR / \"embed.py\"), \"--checkpoint\", str(cli_checkpoint),\n",
|
| 422 |
+
" \"--variant\", VARIANT, \"--input\", str(input_csv), \"--output\", str(cli_output),\n",
|
| 423 |
+
" \"--pooling\", \"first\", \"--batch-size\", str(BATCH_SIZE), \"--device\", DEVICE, \"--threads\", \"4\",\n",
|
| 424 |
+
" ]\n",
|
| 425 |
+
" print(shlex.join(cli_command))\n",
|
| 426 |
+
" subprocess.run(cli_command, check=True, cwd=CODE_DIR)\n",
|
| 427 |
+
" cli_vectors = np.load(cli_output, allow_pickle=False)[\"embeddings\"]\n",
|
| 428 |
+
" assert np.allclose(cli_vectors, vectors, atol=1e-6, rtol=1e-6)\n",
|
| 429 |
+
" print(\"CLI/API embeddings agree.\")\n",
|
| 430 |
+
"else:\n",
|
| 431 |
+
" print(\"CLI example is ready; set RUN_EMBED_CLI=True to run it.\")"
|
| 432 |
+
]
|
| 433 |
+
},
|
| 434 |
+
{
|
| 435 |
+
"cell_type": "markdown",
|
| 436 |
+
"id": "d932e5ba",
|
| 437 |
+
"metadata": {},
|
| 438 |
+
"source": [
|
| 439 |
+
"## 10. Optional: fitted BERToseBind predictions\n",
|
| 440 |
+
"\n",
|
| 441 |
+
"Set `RUN_BINDING=True` only when you want to download the fitted checkpoint, eight pinned glycan feature/index files and the **2.33 GB protein HDF5 cache**. The downloader fetches the selected fit, not all nine. The default `mo_A_glycan_s42` uses the glycan-cold example CSV. All supported cell IDs and their regimes are in `bertosebind_inference/config.json`; the cell chooses the matching CSV from that configuration.\n",
|
| 442 |
+
"\n",
|
| 443 |
+
"The runnable interface supports pairs already represented in the pinned released glycan features and protein cache. It does not build inputs for arbitrary new proteins/glycans. Its regression score is not a calibrated binding probability or affinity constant. Two example predictions check loading; they do not evaluate model quality.\n",
|
| 444 |
+
"\n",
|
| 445 |
+
"To reuse downloaded assets offline, set `BERTose_BINDING_PATHS` to the downloader's `paths_binding.json`. Paths can point outside the notebook folder. This optional section may require `requirements-analysis.txt` (`h5py` and `pandas`); installation stays off in offline mode."
|
| 446 |
+
]
|
| 447 |
+
},
|
| 448 |
+
{
|
| 449 |
+
"cell_type": "code",
|
| 450 |
+
"execution_count": null,
|
| 451 |
+
"id": "5b5397f3",
|
| 452 |
+
"metadata": {},
|
| 453 |
+
"outputs": [],
|
| 454 |
+
"source": [
|
| 455 |
+
"RUN_BINDING = False # Explicit opt-in to the large binding assets and computation.\n",
|
| 456 |
+
"BINDING_CELL_ID = \"mo_A_glycan_s42\"\n",
|
| 457 |
+
"binding_config = json.loads((CODE_DIR / \"bertosebind_inference/config.json\").read_text())\n",
|
| 458 |
+
"if BINDING_CELL_ID not in binding_config[\"checkpoints\"]:\n",
|
| 459 |
+
" raise ValueError(\"Choose a cell ID from bertosebind_inference/config.json.\")\n",
|
| 460 |
+
"regime = binding_config[\"checkpoints\"][BINDING_CELL_ID][\"regime\"]\n",
|
| 461 |
+
"example_name = {\"test_glycan_cold\": \"glycan_cold.csv\", \"test_protein_cold\": \"protein_cold.csv\",\n",
|
| 462 |
+
" \"test_doubly_cold\": \"doubly_cold.csv\"}[regime]\n",
|
| 463 |
+
"binding_pairs = CODE_DIR / \"bertosebind_inference/examples\" / example_name\n",
|
| 464 |
+
"\n",
|
| 465 |
+
"if RUN_BINDING:\n",
|
| 466 |
+
" if INSTALL_DEPENDENCIES:\n",
|
| 467 |
+
" subprocess.run([sys.executable, \"-m\", \"pip\", \"install\", \"-r\", str(CODE_DIR / \"requirements-analysis.txt\")], check=True)\n",
|
| 468 |
+
" binding_paths_file = Path(os.environ.get(\"BERTose_BINDING_PATHS\", str(ASSETS_DIR / \"paths_binding.json\"))).expanduser()\n",
|
| 469 |
+
" if not binding_paths_file.is_file():\n",
|
| 470 |
+
" if OFFLINE:\n",
|
| 471 |
+
" raise FileNotFoundError(\"Offline binding: provide BERTose_BINDING_PATHS with existing assets.\")\n",
|
| 472 |
+
" subprocess.run([\n",
|
| 473 |
+
" sys.executable, str(CODE_DIR / \"download_assets.py\"), \"--task\", \"binding\",\n",
|
| 474 |
+
" \"--cell-id\", BINDING_CELL_ID, \"--output-dir\", str(ASSETS_DIR),\n",
|
| 475 |
+
" ], check=True)\n",
|
| 476 |
+
" binding_paths = json.loads(binding_paths_file.read_text())\n",
|
| 477 |
+
" if binding_paths[\"cell_id\"] != BINDING_CELL_ID:\n",
|
| 478 |
+
" raise ValueError(\"The downloaded checkpoint cell ID does not match BINDING_CELL_ID.\")\n",
|
| 479 |
+
" binding_output = OUTPUT_DIR / f\"binding_{BINDING_CELL_ID}_{time.time_ns()}.json\"\n",
|
| 480 |
+
" binding_command = [\n",
|
| 481 |
+
" sys.executable, \"-m\", \"bertosebind_inference.predict\",\n",
|
| 482 |
+
" \"--checkpoint\", binding_paths[\"checkpoint\"], \"--cell-id\", BINDING_CELL_ID,\n",
|
| 483 |
+
" \"--pairs\", str(binding_pairs), \"--features-dir\", binding_paths[\"features_dir\"],\n",
|
| 484 |
+
" \"--protein-h5\", binding_paths[\"protein_h5\"], \"--batch-size\", \"8\", \"--threads\", \"4\",\n",
|
| 485 |
+
" \"--output\", str(binding_output),\n",
|
| 486 |
+
" ]\n",
|
| 487 |
+
" print(shlex.join(binding_command))\n",
|
| 488 |
+
" subprocess.run(binding_command, check=True, cwd=CODE_DIR)\n",
|
| 489 |
+
" binding_result = json.loads(binding_output.read_text())\n",
|
| 490 |
+
" print(\"Status:\", binding_result[\"status\"])\n",
|
| 491 |
+
" for prediction in binding_result[\"predictions\"]:\n",
|
| 492 |
+
" print({key: prediction[key] for key in (\"sample_id\", \"protein_id\", \"prediction\")})\n",
|
| 493 |
+
"else:\n",
|
| 494 |
+
" print(\"Binding remains off. Selected fit:\", BINDING_CELL_ID, \"| regime:\", regime)\n",
|
| 495 |
+
" print(\"Pairs:\", binding_pairs)"
|
| 496 |
+
]
|
| 497 |
+
},
|
| 498 |
+
{
|
| 499 |
+
"cell_type": "markdown",
|
| 500 |
+
"id": "df1613ea",
|
| 501 |
+
"metadata": {},
|
| 502 |
+
"source": [
|
| 503 |
+
"## 11. Optional: IAR on the two released cases\n",
|
| 504 |
+
"\n",
|
| 505 |
+
"The released IAR runner accepts exactly two byte-pinned single-linkage fixtures: one benchmark case and one grey-seal case. Raw WURCS is retained as provenance; the runner does not convert arbitrary user WURCS into new masking cases. It uses the full frozen WA3 checkpoint and saved linkage readout with physical modality carriers absent.\n",
|
| 506 |
+
"\n",
|
| 507 |
+
"The small-file preflight below is safe to run with the notebook. It verifies source, metadata and fixture bytes; it does not load the full checkpoint or execute a model forward. Setting `RUN_IAR=True` separately downloads the full checkpoint and runs both recorded cases. Allow several GB of memory. It writes a new result directory and compares hidden features and predictions against the released CPU reference. The report states acceptance or abstention for each case; passing these checks is not completion-accuracy evaluation.\n",
|
| 508 |
+
"\n",
|
| 509 |
+
"For offline inference, set `BERTose_IAR_PATHS` to an existing `paths_iar.json` produced by the downloader."
|
| 510 |
+
]
|
| 511 |
+
},
|
| 512 |
+
{
|
| 513 |
+
"cell_type": "code",
|
| 514 |
+
"execution_count": null,
|
| 515 |
+
"id": "f20a25f6",
|
| 516 |
+
"metadata": {},
|
| 517 |
+
"outputs": [],
|
| 518 |
+
"source": [
|
| 519 |
+
"RUN_IAR = False # Explicit opt-in to the full checkpoint and two model cases.\n",
|
| 520 |
+
"preflight_command = [sys.executable, str(CODE_DIR / \"iar_inference/infer.py\"), \"--preflight-only\"]\n",
|
| 521 |
+
"preflight = subprocess.run(preflight_command, check=True, text=True, capture_output=True, cwd=CODE_DIR)\n",
|
| 522 |
+
"print(preflight.stdout)\n",
|
| 523 |
+
"\n",
|
| 524 |
+
"if RUN_IAR:\n",
|
| 525 |
+
" iar_paths_file = Path(os.environ.get(\"BERTose_IAR_PATHS\", str(ASSETS_DIR / \"paths_iar.json\"))).expanduser()\n",
|
| 526 |
+
" if not iar_paths_file.is_file():\n",
|
| 527 |
+
" if OFFLINE:\n",
|
| 528 |
+
" raise FileNotFoundError(\"Offline IAR: provide BERTose_IAR_PATHS with the existing full checkpoint.\")\n",
|
| 529 |
+
" subprocess.run([\n",
|
| 530 |
+
" sys.executable, str(CODE_DIR / \"download_assets.py\"), \"--task\", \"iar\",\n",
|
| 531 |
+
" \"--output-dir\", str(ASSETS_DIR),\n",
|
| 532 |
+
" ], check=True)\n",
|
| 533 |
+
" iar_paths = json.loads(iar_paths_file.read_text())\n",
|
| 534 |
+
" iar_output = OUTPUT_DIR / f\"iar_two_cases_{time.time_ns()}\"\n",
|
| 535 |
+
" iar_command = [\n",
|
| 536 |
+
" sys.executable, str(CODE_DIR / \"iar_inference/infer.py\"),\n",
|
| 537 |
+
" \"--checkpoint\", iar_paths[\"checkpoint\"], \"--output-dir\", str(iar_output), \"--threads\", \"4\",\n",
|
| 538 |
+
" ]\n",
|
| 539 |
+
" print(shlex.join(iar_command))\n",
|
| 540 |
+
" subprocess.run(iar_command, check=True, cwd=CODE_DIR)\n",
|
| 541 |
+
" iar_result = json.loads((iar_output / \"inference_report.json\").read_text())\n",
|
| 542 |
+
" print(\"Status:\", iar_result[\"status\"])\n",
|
| 543 |
+
" for case in iar_result[\"cases\"]:\n",
|
| 544 |
+
" print({key: case[key] for key in (\"dataset\", \"case_id\", \"final_token\", \"abstained\")})\n",
|
| 545 |
+
"else:\n",
|
| 546 |
+
" print(\"Full IAR remains off; only the small-file preflight ran.\")"
|
| 547 |
+
]
|
| 548 |
+
},
|
| 549 |
+
{
|
| 550 |
+
"cell_type": "markdown",
|
| 551 |
+
"id": "aa091d22",
|
| 552 |
+
"metadata": {},
|
| 553 |
+
"source": [
|
| 554 |
+
"## Continue with your inputs\n",
|
| 555 |
+
"\n",
|
| 556 |
+
"- Start with a small WURCS list, inspect diagnostics, then increase the batch size according to memory.\n",
|
| 557 |
+
"- Keep pooling and encoder variant fixed when comparing vectors. Build a reference matrix once and reuse `nearest_neighbors(query_vectors, reference_vectors, k=...)`.\n",
|
| 558 |
+
"- Use `embeddings.npz` for analysis and `embed_records` for an application response. For a CSV pipeline, use the executed `embed.py` interface above.\n",
|
| 559 |
+
"- Use the separate binding and IAR package READMEs for their fixed-input contracts. The embedding API supports new WURCS inputs; the shipped binding/IAR examples have narrower input support."
|
| 560 |
+
]
|
| 561 |
+
}
|
| 562 |
+
],
|
| 563 |
+
"metadata": {
|
| 564 |
+
"bertose_workbench": {
|
| 565 |
+
"default_batch_size": 8,
|
| 566 |
+
"default_device": "cpu",
|
| 567 |
+
"default_threads": 4,
|
| 568 |
+
"distributed_outputs": "stripped",
|
| 569 |
+
"release": "2026-10-02"
|
| 570 |
+
},
|
| 571 |
+
"kernelspec": {
|
| 572 |
+
"display_name": "Python 3",
|
| 573 |
+
"language": "python",
|
| 574 |
+
"name": "python3"
|
| 575 |
+
},
|
| 576 |
+
"language_info": {
|
| 577 |
+
"name": "python",
|
| 578 |
+
"version": "3.12"
|
| 579 |
+
}
|
| 580 |
+
},
|
| 581 |
+
"nbformat": 4,
|
| 582 |
+
"nbformat_minor": 5
|
| 583 |
+
}
|
releases/2026-10-02/provenance/WA3_checkpoint_index.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"cell_id":"A1111","generation":73,"index_sha256":"249bcca15c06644843070cd47c1d62520d2b5cf00e9533ed65311227040ead33","roles":{"best":{"development_loss":0.38572948901364407,"epoch":58,"filename":"review_md20x6_checkpoint_best.pt","sha256":"8e7d95ee492df6d843f495dd4708c97ee16a947e75b5cd8f83b23e4f4a0d6d82"},"latest":{"development_loss":0.385906232017773,"epoch":73,"filename":"review_md20x6_checkpoint_latest.pt","sha256":"1a2d27f26d585ffedf67518f3fc769e9be1c71d5943a8d0c9ae3f75d7dd62f30"},"milestones":{"25":{"development_loss":0.39812925026342416,"epoch":25,"filename":"review_md20x6_checkpoint_milestone_025.pt","sha256":"08f5e9e744edbc555191949ddc56fc6d793d61572e0bee434eb50135f539e790"},"50":{"development_loss":0.38745878758199537,"epoch":50,"filename":"review_md20x6_checkpoint_milestone_050.pt","sha256":"1026b01bb50beaaaaa30354eb7b2bcd5307d82689f1f38a4b6d382b1e3b77ffa"}}},"run_identity_sha256":"55dd7ff33d2196cb1da5e215adb79b0880249f8f1e8c541a7fe36f5759c369d5","schema":"bertose_review_md_temporal_20x6_checkpoint_index_20260802_r3"}
|
releases/2026-10-02/provenance/WA3_final_receipt.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"development_history":[{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.22662700572537933,"ms":0.8557433197062682,"sequence":0.3059137519524717,"static":0.7551767198470175,"topology":0.030460597622770504},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.25215765373639587,"ms":2.5724487456782112,"sequence":1.5196248877762957,"static":2.5891844269759083,"topology":0.06376307786672697},"total_normalized_loss":0.5028213712413956,"weighted_normalized_losses":{"md":0.45325401145075866,"ms":1.7114866394125363,"sequence":0.15295687597623586,"static":0.18879417996175438,"topology":0.007615149405692626}},"epoch":1,"improved":true,"step_identity_chain_sha256":"8349369e088705ef87b62fa7c6ce3541d2dc06f3988bad23622cfab4bf777499"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.2136726617028679,"ms":0.8150696210605691,"sequence":0.23423114401117145,"static":0.6901099233497171,"topology":0.019501219778012342},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.2377439390780074,"ms":2.450179599482438,"sequence":1.1635419253299568,"static":2.366097655659455,"topology":0.04082184501436121},"total_normalized_loss":0.47040058466287843,"weighted_normalized_losses":{"md":0.4273453234057358,"ms":1.6301392421211383,"sequence":0.11711557200558573,"static":0.17252748083742928,"topology":0.0048753049445030856}},"epoch":2,"improved":true,"step_identity_chain_sha256":"962391a900077917fa24893d4e57fa974e048d4e7b2f1840019ebb021dea6002"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.20491723994564162,"ms":0.7871846769190306,"sequence":0.19421473235822365,"static":0.6489628202681939,"topology":0.04007295908558098},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.22800217595181557,"ms":2.3663547095553628,"sequence":0.9647606195560059,"static":2.225021486712623,"topology":0.08388460535698647},"total_normalized_loss":0.45071402894938,"weighted_normalized_losses":{"md":0.40983447989128324,"ms":1.5743693538380612,"sequence":0.09710736617911182,"static":0.16224070506704846,"topology":0.010018239771395245}},"epoch":3,"improved":true,"step_identity_chain_sha256":"3aa01b318689b035ac47537fb3364c6b32599626130c2aae40ec5ca10d2f10b1"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.20059318098000678,"ms":0.7833350264236384,"sequence":0.1740526846396435,"static":0.6144367794664927,"topology":0.010871273858649505},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.22319099045385438,"ms":2.3547822808140313,"sequence":0.8646057579123623,"static":2.1066461649905643,"topology":0.022756805041848484},"total_normalized_loss":0.44224195409167955,"weighted_normalized_losses":{"md":0.40118636196001356,"ms":1.5666700528472768,"sequence":0.08702634231982175,"static":0.15360919486662317,"topology":0.002717818464662376}},"epoch":4,"improved":true,"step_identity_chain_sha256":"be59cdbbc21e7f36a63f3d33c56c24586746adb6784ae7c3896a5d797cd60d85"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.19842932505038918,"ms":0.7702185946671242,"sequence":0.16123126231503135,"static":0.5864062674323184,"topology":0.02171640669463639},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.22078336549984892,"ms":2.3153529944347926,"sequence":0.800915412719256,"static":2.010541288699162,"topology":0.04545888915917031},"total_normalized_loss":0.43398842782485625,"weighted_normalized_losses":{"md":0.39685865010077837,"ms":1.5404371893342483,"sequence":0.08061563115751567,"static":0.1466015668580796,"topology":0.005429101673659098}},"epoch":5,"improved":true,"step_identity_chain_sha256":"e90df1029db9d0ff865d415bd64e8e26a458506a2824dd0ed00c2583be939787"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.1962911658604727,"ms":0.767122882303372,"sequence":0.15398089224489517,"static":0.5765596184077477,"topology":0.010398237550739037},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.21840433214979185,"ms":2.3060469780117274,"sequence":0.7648992390956554,"static":1.9767812565871012,"topology":0.021766599553807216},"total_normalized_loss":0.43011160128795173,"weighted_normalized_losses":{"md":0.3925823317209454,"ms":1.534245764606744,"sequence":0.07699044612244758,"static":0.14413990460193693,"topology":0.0025995593876847593}},"epoch":6,"improved":true,"step_identity_chain_sha256":"842cfd5af25d82c036c7e15af1643caedbf3bb83562d3a55144a041c438a9506"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.194018423453635,"ms":0.7636756649092812,"sequence":0.14634798267436108,"static":0.5698844597821273,"topology":0.0223091175846953},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.21587555412079626,"ms":2.295684302829463,"sequence":0.7269828025984444,"static":1.9538949356680038,"topology":0.046699609091960845},"total_normalized_loss":0.4273221124809437,"weighted_normalized_losses":{"md":0.38803684690727,"ms":1.5273513298185624,"sequence":0.07317399133718054,"static":0.14247111494553183,"topology":0.005577279396173825}},"epoch":7,"improved":true,"step_identity_chain_sha256":"7c71e534e6ef7cb575a5ad296663a160fb3f0bcf8d5bbbce2a9596e3ed7174bc"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.1930169839550213,"ms":0.7558749452810657,"sequence":0.1399491315920143,"static":0.5620648833879897,"topology":0.00981988587483681},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.21476129753199683,"ms":2.272234570928689,"sequence":0.6951965448841485,"static":1.9270848859231555,"topology":0.02055593772104861},"total_normalized_loss":0.4221459233167775,"weighted_normalized_losses":{"md":0.3860339679100426,"ms":1.5117498905621314,"sequence":0.06997456579600715,"static":0.14051622084699741,"topology":0.0024549714687092023}},"epoch":8,"improved":true,"step_identity_chain_sha256":"81ebd06b29d8386df109dbee8ba895db64884466fb61a76a710ee5a3a8ae6fd0"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.19406822581608854,"ms":0.7518932710631684,"sequence":0.1362528402339793,"static":0.5518898818467565,"topology":0.009015226965808379},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.21593096696458605,"ms":2.260265265867628,"sequence":0.6768352378023567,"static":1.8921990706660943,"topology":0.018871547634290067},"total_normalized_loss":0.420055138215729,"weighted_normalized_losses":{"md":0.3881364516321771,"ms":1.5037865421263368,"sequence":0.06812642011698965,"static":0.13797247046168912,"topology":0.0022538067414520947}},"epoch":9,"improved":true,"step_identity_chain_sha256":"6812ea9698a1e8fa8242d95e3c4df63df9f536847337f3fdba02ed782dd4e07f"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.19102172991507627,"ms":0.7505529410653496,"sequence":0.13160407793951492,"static":0.548196846882865,"topology":0.007217244018334658},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.21254126830066034,"ms":2.256236101815413,"sequence":0.6537425365591589,"static":1.8795372017743697,"topology":0.015107835309843994},"total_normalized_loss":0.4175609807311818,"weighted_normalized_losses":{"md":0.38204345983015253,"ms":1.5011058821306993,"sequence":0.06580203896975746,"static":0.13704921172071624,"topology":0.0018043110045836645}},"epoch":10,"improved":true,"step_identity_chain_sha256":"244f9ebf8f844fdc582f8b77d68d58f852ae14f87ac5110b30ede39a22e546c5"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.19106956913570272,"ms":0.7422393981299115,"sequence":0.12959927503388055,"static":0.5440629670213283,"topology":0.006221932800593297},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.21259449684503057,"ms":2.231244772518503,"sequence":0.643783689102829,"static":1.8653638605163814,"topology":0.013024353315681565},"total_normalized_loss":0.41379775940072977,"weighted_normalized_losses":{"md":0.38213913827140544,"ms":1.484478796259823,"sequence":0.06479963751694028,"static":0.13601574175533207,"topology":0.0015554832001483242}},"epoch":11,"improved":true,"step_identity_chain_sha256":"19faa5da708b534a9be44e7b7c20d35f2f66ac5d15d9d680284a7f8b692c7e9f"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.19037402365003858,"ms":0.7366234966393759,"sequence":0.12822089536794967,"static":0.5452088458164462,"topology":0.008232884439421842},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.21182059473583295,"ms":2.2143628192359004,"sequence":0.6369365956597113,"static":1.869292598589931,"topology":0.017233872364545984},"total_normalized_loss":0.4112931841653541,"weighted_normalized_losses":{"md":0.38074804730007716,"ms":1.4732469932787517,"sequence":0.06411044768397484,"static":0.13630221145411156,"topology":0.0020582211098554605}},"epoch":12,"improved":true,"step_identity_chain_sha256":"9db8b63da1b78fa49d70078c2a3b87a934a5cf570a6742755f3d6ce00885e1f7"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.19041639201178032,"ms":0.736960530254102,"sequence":0.12604434886221993,"static":0.5334526507395191,"topology":0.005343901317552914},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.2118677361021289,"ms":2.215375975493727,"sequence":0.6261246128102991,"static":1.8289855334835847,"topology":0.011186372639271922},"total_normalized_loss":0.41049503139542853,"weighted_normalized_losses":{"md":0.38083278402356063,"ms":1.473921060508204,"sequence":0.06302217443110997,"static":0.13336316268487977,"topology":0.0013359753293882286}},"epoch":13,"improved":true,"step_identity_chain_sha256":"41ffade6ef912d2969b95a2eedcc3a039106187cdbc564b05bb150a4b1926dea"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.18864850129010685,"ms":0.7347006251585065,"sequence":0.125190681186743,"static":0.535602107175571,"topology":0.022280826714292268},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.2099006837863086,"ms":2.208582478080844,"sequence":0.6218840233066719,"static":1.8363551186209766,"topology":0.04664038789759145},"total_normalized_loss":0.4097528653926128,"weighted_normalized_losses":{"md":0.3772970025802137,"ms":1.469401250317013,"sequence":0.0625953405933715,"static":0.13390052679389275,"topology":0.005570206678573067}},"epoch":14,"improved":true,"step_identity_chain_sha256":"e1fc779a32a5752f26e197664962d6285d2e86d09a0b301734ec06433cfced47"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.18932230534558994,"ms":0.7300639699996679,"sequence":0.12059135975771769,"static":0.5375086685680924,"topology":0.005507952683596159},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.2106503951861696,"ms":2.194644235768195,"sequence":0.5990369192918266,"static":1.8428919184677595,"topology":0.011529780872974427},"total_normalized_loss":0.4069644771764594,"weighted_normalized_losses":{"md":0.3786446106911799,"ms":1.4601279399993359,"sequence":0.060295679878858845,"static":0.1343771671420231,"topology":0.0013769881708990397}},"epoch":15,"improved":true,"step_identity_chain_sha256":"528261498391f3cb63bf1f013018798661c55d67e76113418f6d2a8c1e4ce07d"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.18979667588370328,"ms":0.729257050377908,"sequence":0.1224965826079112,"static":0.5377193858019084,"topology":0.004572563830447886},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.21117820590100242,"ms":2.192218555869727,"sequence":0.6085011033680101,"static":1.8436143795367423,"topology":0.009571734185329138},"total_normalized_loss":0.40698574624705347,"weighted_normalized_losses":{"md":0.37959335176740655,"ms":1.458514100755816,"sequence":0.0612482913039556,"static":0.1344298464504771,"topology":0.0011431409576119714}},"epoch":16,"improved":false,"step_identity_chain_sha256":"94ee181ed0af332478fbc91d6850ea1c5b9fb37055d602f6eb92ecb6f393c058"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.19044398384067177,"ms":0.7253422453133344,"sequence":0.12148093259013977,"static":0.5359335464438555,"topology":0.0063599683910022155},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.21189843628639551,"ms":2.180450266072976,"sequence":0.6034558674659781,"static":1.837491484943424,"topology":0.013313302804087004},"total_normalized_loss":0.40557726066235933,"weighted_normalized_losses":{"md":0.38088796768134353,"ms":1.4506844906266687,"sequence":0.060740466295069885,"static":0.13398338661096387,"topology":0.0015899920977505539}},"epoch":17,"improved":true,"step_identity_chain_sha256":"accedf095414e081aba3585d10801cc7152637684e6b1e66d3ba0ae439dd611e"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.1888921825736983,"ms":0.7306011329012926,"sequence":0.11935736189567756,"static":0.5428638884042807,"topology":0.00425405742116268},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.21017181696628076,"ms":2.1962590003835745,"sequence":0.5929070416689655,"static":1.86125272255306,"topology":0.0089050056717322},"total_normalized_loss":0.4070889596708363,"weighted_normalized_losses":{"md":0.3777843651473966,"ms":1.4612022658025852,"sequence":0.05967868094783878,"static":0.13571597210107017,"topology":0.00106351435529067}},"epoch":18,"improved":false,"step_identity_chain_sha256":"4748dc16e2e0fb741438ffffe8ea67358decacfada7422972ed9de47e448a950"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.18853731601049878,"ms":0.7212504073037117,"sequence":0.11723436805777301,"static":0.5373463378322132,"topology":0.00529378593435542},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.20977697293752312,"ms":2.1681497977982307,"sequence":0.5823610814037444,"static":1.8423353544181642,"topology":0.011081466257568041},"total_normalized_loss":0.40277053231979,"weighted_normalized_losses":{"md":0.37707463202099756,"ms":1.4425008146074234,"sequence":0.05861718402888651,"static":0.1343365844580533,"topology":0.001323446483588855}},"epoch":19,"improved":true,"step_identity_chain_sha256":"cf9daba2764d8263ffb79ca7f35556d573366151727cab1c57de3eb41a0b6b31"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.18732470522153952,"ms":0.7195666013047894,"sequence":0.11674263354679772,"static":0.5369274246652657,"topology":0.00497569131779692},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.20842775557280213,"ms":2.1630881110398934,"sequence":0.5799183929129941,"static":1.8408990767633984,"topology":0.010415599748453847},"total_normalized_loss":0.40152594176436446,"weighted_normalized_losses":{"md":0.37464941044307903,"ms":1.4391332026095789,"sequence":0.05837131677339886,"static":0.13423185616631642,"topology":0.00124392282944923}},"epoch":20,"improved":true,"step_identity_chain_sha256":"3528d61e9a4953b6aa0220d8c4b3496d374e71547d7f57b7064f92d2af5b2893"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.1876363582716866,"ms":0.7190431341736717,"sequence":0.11718534196001842,"static":0.5390776018521963,"topology":0.004164038808132024},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.2087745178734968,"ms":2.1615145172602657,"sequence":0.5821175445315936,"static":1.8482711330534378,"topology":0.008716569978407598},"total_normalized_loss":0.4015524132071616,"weighted_normalized_losses":{"md":0.3752727165433732,"ms":1.4380862683473434,"sequence":0.05859267098000921,"static":0.13476940046304908,"topology":0.001041009702033006}},"epoch":21,"improved":false,"step_identity_chain_sha256":"0478c6e9854ecd9b251c9e213bc36891fa8d4a8b44144d0effcccacf80043cb8"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.18783271945591928,"ms":0.715846598873989,"sequence":0.11771536798749985,"static":0.5461228993038463,"topology":0.004379447172740652},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.2089930001119332,"ms":2.151905417156502,"sequence":0.5847504459209208,"static":1.872426504856902,"topology":0.009167483663548718},"total_normalized_loss":0.4007683814545427,"weighted_normalized_losses":{"md":0.37566543891183857,"ms":1.431693197747978,"sequence":0.058857683993749924,"static":0.13653072482596157,"topology":0.001094861793185163}},"epoch":22,"improved":true,"step_identity_chain_sha256":"7ee0957a690bf9f5456ca77b9742b292ae6a5c51b43eff3cb19b9bd8cb8f8929"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.1871767668245945,"ms":0.7103727853823291,"sequence":0.11628192666514102,"static":0.5459911714081273,"topology":0.0037820487306240874},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.20826315118705482,"ms":2.135450594400152,"sequence":0.5776298340009903,"static":1.8719748651185064,"topology":0.007916951292060883},"total_normalized_loss":0.3981366745562211,"weighted_normalized_losses":{"md":0.374353533649189,"ms":1.4207455707646581,"sequence":0.05814096333257051,"static":0.1364977928520318,"topology":0.0009455121826560218}},"epoch":23,"improved":true,"step_identity_chain_sha256":"2c8d3171c46864ec94861d9996b8811b38ba0d322556d6934fce6395b6ff16c0"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.18777199994128557,"ms":0.7049079101886564,"sequence":0.11539469749322528,"static":0.5454564029586294,"topology":0.0036034899744572567},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.20892544024501863,"ms":2.1190226410483493,"sequence":0.5732225279475711,"static":1.8701413682626205,"topology":0.0075431747820182676},"total_normalized_loss":0.39606442844795364,"weighted_normalized_losses":{"md":0.37554399988257114,"ms":1.4098158203773128,"sequence":0.05769734874661264,"static":0.13636410073965735,"topology":0.0009008724936143142}},"epoch":24,"improved":true,"step_identity_chain_sha256":"f84a0cf966e10855452bfead8481542f5a9b20cde80b2192359d4f8e68cbf4f6"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.1869681200818719,"ms":0.7099487995044106,"sequence":0.11643272414371737,"static":0.5502300342311925,"topology":0.00415416605959564},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.20803099936147573,"ms":2.134176051070721,"sequence":0.5783789196501185,"static":1.886508148946153,"topology":0.008695903383435295},"total_normalized_loss":0.39812925026342416,"weighted_normalized_losses":{"md":0.3739362401637438,"ms":1.4198975990088212,"sequence":0.058216362071858686,"static":0.13755750855779814,"topology":0.00103854151489891}},"epoch":25,"improved":false,"step_identity_chain_sha256":"51dd88d5d4db95b3b32fbb7ac9b952ca723bf7e2c5eed0fa35fb5b19c05f868c"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.18841552983824386,"ms":0.7033956170602036,"sequence":0.11585168737709899,"static":0.5479196650977544,"topology":0.003713389834364146},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.2096414669533398,"ms":2.114476538879861,"sequence":0.5754926226934405,"static":1.8785868616187633,"topology":0.0077732278299449085},"total_normalized_loss":0.3958912802436948,"weighted_normalized_losses":{"md":0.3768310596764877,"ms":1.4067912341204072,"sequence":0.05792584368854949,"static":0.1369799162744386,"topology":0.0009283474585910365}},"epoch":26,"improved":true,"step_identity_chain_sha256":"ea75ef4544cd28fed4e054f41bad2fce6f86774be1051c0350b1e433d612ec03"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.18669901981477316,"ms":0.7046144276012817,"sequence":0.11363491391429,"static":0.550115956922508,"topology":0.003343397025061905},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.20773158362435176,"ms":2.1181404034703455,"sequence":0.564480812655002,"static":1.8861170256721502,"topology":0.006998722989237778},"total_normalized_loss":0.39556183805522943,"weighted_normalized_losses":{"md":0.3733980396295463,"ms":1.4092288552025634,"sequence":0.056817456957145,"static":0.137528989230627,"topology":0.0008358492562654762}},"epoch":27,"improved":true,"step_identity_chain_sha256":"ee247d44c437c3533ebc85d2582f2877b2d1a5562bc2d3391fed073f0ddedfee"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.18680978057918643,"ms":0.7027360981756547,"sequence":0.11532498453928958,"static":0.5581590564718851,"topology":0.003439281182740489},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.2078548221342156,"ms":2.11249396012261,"sequence":0.5728762292306127,"static":1.9136934426227188,"topology":0.0071994370096243885},"total_normalized_loss":0.3954307668385967,"weighted_normalized_losses":{"md":0.37361956115837286,"ms":1.4054721963513095,"sequence":0.05766249226964479,"static":0.13953976411797128,"topology":0.0008598202956851223}},"epoch":28,"improved":true,"step_identity_chain_sha256":"2e05d67d34765b01db30476b094440885b15faa753286e940942a504e246f993"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.18611718220913312,"ms":0.701507074633941,"sequence":0.11576753504756795,"static":0.5507436567855164,"topology":0.0035271283558496297},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.20708419914771276,"ms":2.108799394245805,"sequence":0.5750745964572758,"static":1.8882691453911553,"topology":0.007383327234258153},"total_normalized_loss":0.39433999549905474,"weighted_normalized_losses":{"md":0.37223436441826624,"ms":1.403014149267882,"sequence":0.05788376752378398,"static":0.1376859141963791,"topology":0.0008817820889624074}},"epoch":29,"improved":true,"step_identity_chain_sha256":"e34003c15ef687cafdece48f6eb4640a91a8cdb00f0fee6879a58624bb3874f0"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.1870041062465378,"ms":0.6952488676497738,"sequence":0.11350901360033186,"static":0.5610069497587966,"topology":0.00359732086848505},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.20807103954477196,"ms":2.0899866073552906,"sequence":0.5638554035347891,"static":1.9234576749598256,"topology":0.007530261010944391},"total_normalized_loss":0.3924823044499219,"weighted_normalized_losses":{"md":0.3740082124930756,"ms":1.3904977352995476,"sequence":0.05675450680016593,"static":0.14025173743969915,"topology":0.0008993302171212625}},"epoch":30,"improved":true,"step_identity_chain_sha256":"c94b9d5bf751a42a5761422aa4c67519abfe51e1c3e2ff7b2186a2c1943fcf9b"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.18552926299512953,"ms":0.6984604122216393,"sequence":0.11633959795669416,"static":0.5623446920579128,"topology":0.0035183603877805185},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.20643004793958472,"ms":2.0996408268102797,"sequence":0.5779163158259982,"static":1.9280442325656804,"topology":0.007364973272932529},"total_normalized_loss":0.39352298250466167,"weighted_normalized_losses":{"md":0.37105852599025907,"ms":1.3969208244432787,"sequence":0.05816979897834708,"static":0.1405861730144782,"topology":0.0008795900969451296}},"epoch":31,"improved":false,"step_identity_chain_sha256":"22a99ec6e93cdfc3b940b0c535e82b51bcbae5e7499d24baf55db94e31432b4d"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.18568012430750563,"ms":0.7001969914321841,"sequence":0.11344239058137431,"static":0.5685290688956781,"topology":0.0029350338868824578},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.20659790452157764,"ms":2.1048611550431313,"sequence":0.5635244540529155,"static":1.949247868453895,"topology":0.006143897653894644},"total_normalized_loss":0.3942682904931413,"weighted_normalized_losses":{"md":0.37136024861501127,"ms":1.4003939828643681,"sequence":0.05672119529068716,"static":0.14213226722391953,"topology":0.0007337584717206144}},"epoch":32,"improved":false,"step_identity_chain_sha256":"895e2cc888a7f56cd52ea5a37a973da1ff3b308ce4dcf07bfc24318f2c824749"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.18579079378983765,"ms":0.6941709269924471,"sequence":0.11519749822068524,"static":0.5661192489833935,"topology":0.004340516875965144},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.20672104146598436,"ms":2.0867462115169597,"sequence":0.572242941641004,"static":1.9409856060923543,"topology":0.009085990989786602},"total_normalized_loss":0.39202742642795035,"weighted_normalized_losses":{"md":0.3715815875796753,"ms":1.3883418539848942,"sequence":0.05759874911034262,"static":0.14152981224584837,"topology":0.001085129218991286}},"epoch":33,"improved":true,"step_identity_chain_sha256":"b231fba6226a93658e7564b44fa90e2c690117d8039abd8dc94a481b032eed83"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.18593081767416006,"ms":0.693387096507827,"sequence":0.11454659821670357,"static":0.5614319089508184,"topology":0.0031280227162407697},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.2068768397302944,"ms":2.084389939839984,"sequence":0.5690095994352639,"static":1.9249146819002751,"topology":0.006547880592974724},"total_normalized_loss":0.39140982207781816,"weighted_normalized_losses":{"md":0.3718616353483201,"ms":1.386774193015654,"sequence":0.057273299108351786,"static":0.1403579772377046,"topology":0.0007820056790601924}},"epoch":34,"improved":true,"step_identity_chain_sha256":"0b9516f1d44359fc25b265efd05b7ea82c1b915b26529bbebba2297c941d81e6"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.18653092448192274,"ms":0.6913025012821786,"sequence":0.11700309612352572,"static":0.5737887574360878,"topology":0.003213575276954297},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.20754455152462503,"ms":2.0781234411715435,"sequence":0.5812122393367132,"static":1.9672811357695654,"topology":0.006726967512346149},"total_normalized_loss":0.3916837965536452,"weighted_normalized_losses":{"md":0.3730618489638455,"ms":1.3826050025643573,"sequence":0.05850154806176286,"static":0.14344718935902195,"topology":0.0008033938192385742}},"epoch":35,"improved":false,"step_identity_chain_sha256":"6b030e9056e01db69523e77e658de8319eccfcb688835a2ef86bd664004b6e27"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.18587856384316986,"ms":0.6880689560718966,"sequence":0.1145185470539755,"static":0.5619452845015106,"topology":0.002963250731657305},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.20681869924796725,"ms":2.068403085629488,"sequence":0.5688702554380078,"static":1.9266748314733604,"topology":0.006202963890638041},"total_normalized_loss":0.3892762894330825,"weighted_normalized_losses":{"md":0.37175712768633973,"ms":1.376137912143793,"sequence":0.05725927352698775,"static":0.14048632112537765,"topology":0.0007408126829143262}},"epoch":36,"improved":true,"step_identity_chain_sha256":"665bd47cce5e02ea2ada4e5fdeec90728c96bf663423dd8b62fc65ad4e3336ad"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.1855978427576254,"ms":0.6912036318598846,"sequence":0.11474447700890597,"static":0.570678268483088,"topology":0.00325730043461577},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.20650635354998365,"ms":2.077826229945339,"sequence":0.569992561252033,"static":1.9566165729649554,"topology":0.006818497254054803},"total_normalized_loss":0.3908918159937798,"weighted_normalized_losses":{"md":0.3711956855152508,"ms":1.3824072637197693,"sequence":0.057372238504452985,"static":0.142669567120772,"topology":0.0008143251086539425}},"epoch":37,"improved":false,"step_identity_chain_sha256":"59e4358eb8cb3989c99ed96be6b743c92a78cef713baf3b8ec4fc200ac5aae21"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.18628226273452947,"ms":0.6894950283626093,"sequence":0.11541384521930931,"static":0.5732782976481989,"topology":0.0028644966366610483},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.20726787680708206,"ms":2.072689999463358,"sequence":0.5733176441720491,"static":1.9655309831249406,"topology":0.005996242239051097},"total_normalized_loss":0.39065944067502945,"weighted_normalized_losses":{"md":0.37256452546905894,"ms":1.3789900567252187,"sequence":0.057706922609654654,"static":0.14331957441204973,"topology":0.0007161241591652621}},"epoch":38,"improved":false,"step_identity_chain_sha256":"61ac63140ee97daeb11ff0af98b55e2cc266f7784b21723cd60e04ccb26d536e"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.18609527192481407,"ms":0.6879375812347679,"sequence":0.11606297331560542,"static":0.5749748418130596,"topology":0.004197018666955648},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.20705982056198813,"ms":2.0680081599231426,"sequence":0.5765421844360633,"static":1.9713477219304267,"topology":0.008785606618208533},"total_normalized_loss":0.3901780316193941,"weighted_normalized_losses":{"md":0.37219054384962813,"ms":1.3758751624695358,"sequence":0.05803148665780271,"static":0.1437437104532649,"topology":0.001049254666738912}},"epoch":39,"improved":false,"step_identity_chain_sha256":"14815a131129fdd53c6afacd0ea26e9c7cd5fc479630dad23a4465d2c7273792"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.1860477765532129,"ms":0.6861794792469316,"sequence":0.11415070244626119,"static":0.5796372890932975,"topology":0.003095314515184333},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.20700697460292886,"ms":2.0627231321008557,"sequence":0.5670429893633404,"static":1.987333299308969,"topology":0.006479412613565053},"total_normalized_loss":0.389442602745108,"weighted_normalized_losses":{"md":0.3720955531064258,"ms":1.3723589584938631,"sequence":0.057075351223130594,"static":0.14490932227332437,"topology":0.0007738286287960833}},"epoch":40,"improved":false,"step_identity_chain_sha256":"f74344ec081ae3f0e76daae3fa24451a0156b680057b368a8667f24b8d407827"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.18539234416764283,"ms":0.691727826314129,"sequence":0.11626568618353424,"static":0.5780178487884755,"topology":0.002925738766876558},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.20627770453205094,"ms":2.0794020101299573,"sequence":0.5775491594975343,"static":1.9817809173201393,"topology":0.006124440206996961},"total_normalized_loss":0.39152181618882975,"weighted_normalized_losses":{"md":0.37078468833528566,"ms":1.383455652628258,"sequence":0.05813284309176712,"static":0.14450446219711888,"topology":0.0007314346917191395}},"epoch":41,"improved":false,"step_identity_chain_sha256":"eb5126073313a51f4be295e16d8024995dbe9b86e0f5e81a784022c988690245"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.18587224769755226,"ms":0.6882215320340647,"sequence":0.11647381389194182,"static":0.58260749159163,"topology":0.003232723529785487},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.20681167155744778,"ms":2.068861744006903,"sequence":0.5785830327494342,"static":1.9975168786640176,"topology":0.006767050492706792},"total_normalized_loss":0.39057690403791173,"weighted_normalized_losses":{"md":0.3717444953951045,"ms":1.3764430640681293,"sequence":0.05823690694597091,"static":0.1456518728979075,"topology":0.0008081808824463718}},"epoch":42,"improved":false,"step_identity_chain_sha256":"676e09381467a3e25fd85135dc74b5227bec02e5d64206f5f2a6bf387f1296fd"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.18614700269163967,"ms":0.685320170987359,"sequence":0.1171421065871618,"static":0.5920840246162111,"topology":0.002909834056541092},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.20711737905439717,"ms":2.060139966794643,"sequence":0.581902773053666,"static":2.030007938152635,"topology":0.006091146924438054},"total_normalized_loss":0.39005077306395325,"weighted_normalized_losses":{"md":0.37229400538327934,"ms":1.370640341974718,"sequence":0.0585710532935809,"static":0.14802100615405278,"topology":0.000727458514135273}},"epoch":43,"improved":false,"step_identity_chain_sha256":"7ff1a9c0e0fa0e04008787607011e553c3d962cca1f1f4cedde45e1761d375b6"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.1852961985002174,"ms":0.6863376928436224,"sequence":0.11782033374489713,"static":0.590915873170764,"topology":0.0026635949468924143},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.20617072758180918,"ms":2.0631987377631895,"sequence":0.585271862746046,"static":2.026002836497073,"topology":0.005575695332949085},"total_normalized_loss":0.3901145633179085,"weighted_normalized_losses":{"md":0.3705923970004348,"ms":1.372675385687245,"sequence":0.058910166872448565,"static":0.147728968292691,"topology":0.0006658987367231036}},"epoch":44,"improved":false,"step_identity_chain_sha256":"90f8e0e5218cea022036b7b15872317dd62b7769a369c702fa95d2cdf261f6f2"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.1852771771014432,"ms":0.6854490128941951,"sequence":0.11695329923316397,"static":0.5881065115506812,"topology":0.0027799599137752775},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.20614956332880974,"ms":2.060527278262929,"sequence":0.5809648735565068,"static":2.0163707130943074,"topology":0.0058192817699651645},"total_normalized_loss":0.38953012949479454,"weighted_normalized_losses":{"md":0.3705543542028864,"ms":1.3708980257883903,"sequence":0.058476649616581985,"static":0.1470266278876703,"topology":0.0006949899784438194}},"epoch":45,"improved":false,"step_identity_chain_sha256":"6fc0204c9d72382b80dbc82c884f4ed3bbdd571aa60e6f3d4132bc84032f5c25"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.18515215322101983,"ms":0.683250564808573,"sequence":0.11521552646327139,"static":0.5882545155033189,"topology":0.0027547604911359077},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.20601045489269165,"ms":2.0539185266781215,"sequence":0.572332496837336,"static":2.0168781566094864,"topology":0.005766531893949943},"total_normalized_loss":0.388433103657887,"weighted_normalized_losses":{"md":0.37030430644203965,"ms":1.366501129617146,"sequence":0.057607763231635696,"static":0.14706362887582972,"topology":0.0006886901227839769}},"epoch":46,"improved":true,"step_identity_chain_sha256":"c05eda781550a7ce7718d4df2fe6c3a7de66cbabd7e25f3d23cb3984b19b4ffa"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.18562786327526232,"ms":0.6840400894463337,"sequence":0.11642953551058739,"static":0.5928588482855713,"topology":0.0033916578212694337},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.20653975602674077,"ms":2.0562919155405512,"sequence":0.5783630801325048,"static":2.032664483734133,"topology":0.007099747169544423},"total_normalized_loss":0.3893226599450392,"weighted_normalized_losses":{"md":0.37125572655052463,"ms":1.3680801788926673,"sequence":0.058214767755293696,"static":0.14821471207139283,"topology":0.0008479144553173584}},"epoch":47,"improved":false,"step_identity_chain_sha256":"dfa4f9e50c25e779fe20c46465945d19eacc644643045d20d3ce69bbde8abd11"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.1847732815355456,"ms":0.6809981609338026,"sequence":0.11489368631824985,"static":0.5954631925978346,"topology":0.0028269217085146654},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.20558890144644393,"ms":2.047147578674224,"sequence":0.570733757679195,"static":2.041593688724935,"topology":0.005917586754385115},"total_normalized_loss":0.38771245133488175,"weighted_normalized_losses":{"md":0.3695465630710912,"ms":1.3619963218676052,"sequence":0.057446843159124926,"static":0.14886579814945866,"topology":0.0007067304271286663}},"epoch":48,"improved":true,"step_identity_chain_sha256":"eb398cc6689a6cfc4580944d4217239ae6ef50ca051c458b18128689efdb8d5f"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.18503533879837353,"ms":0.6819155163233396,"sequence":0.11916113116360362,"static":0.5977301799585286,"topology":0.00319209553651353},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.20588048075018917,"ms":2.0499052393731887,"sequence":0.5919322665818604,"static":2.049366238137805,"topology":0.006682004035948107},"total_normalized_loss":0.38874256893979775,"weighted_normalized_losses":{"md":0.37007067759674706,"ms":1.3638310326466792,"sequence":0.05958056558180181,"static":0.14943254498963215,"topology":0.0007980238841283825}},"epoch":49,"improved":false,"step_identity_chain_sha256":"cf660140247c0497c5db143523d149b00c9d2a00d5a4a95f18df54b57cf0e4cc"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.18459828916343385,"ms":0.6798209047768676,"sequence":0.11901937290670442,"static":0.5930596659260227,"topology":0.00272378837806317},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.20539419532202496,"ms":2.0436086306573245,"sequence":0.5912280832169188,"static":2.0333530032470546,"topology":0.005701698062322236},"total_normalized_loss":0.38745878758199537,"weighted_normalized_losses":{"md":0.3691965783268677,"ms":1.3596418095537353,"sequence":0.05950968645335221,"static":0.14826491648150567,"topology":0.0006809470945157925}},"epoch":50,"improved":true,"step_identity_chain_sha256":"a1e41959edfb7e58c20e7c6671743081f886539cda2acb274458f70e0d75133b"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.18416298638185008,"ms":0.6839928277328658,"sequence":0.11752657470392035,"static":0.5983071006205644,"topology":0.0031425546130316993},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.204909853538848,"ms":2.056149842172604,"sequence":0.5838126163184877,"static":2.051344257261655,"topology":0.006578300169048262},"total_normalized_loss":0.3890874658779582,"weighted_normalized_losses":{"md":0.36832597276370016,"ms":1.3679856554657317,"sequence":0.058763287351960174,"static":0.1495767751551411,"topology":0.0007856386532579248}},"epoch":51,"improved":false,"step_identity_chain_sha256":"b06726e9afd1de13fd3dd5397fbb33c4e12079a6970199b902832d816ac333e4"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.1850617024274701,"ms":0.6803602939273509,"sequence":0.11883763390680872,"static":0.5924614841583618,"topology":0.00247797867838134},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.2059098143719069,"ms":2.045230087596152,"sequence":0.5903252957300588,"static":2.031302088703976,"topology":0.005187145353432089},"total_normalized_loss":0.3877995350744464,"weighted_normalized_losses":{"md":0.3701234048549402,"ms":1.3607205878547017,"sequence":0.05941881695340436,"static":0.14811537103959044,"topology":0.000619494669595335}},"epoch":52,"improved":false,"step_identity_chain_sha256":"11ed01719e06709d88c69773df2523b945afc2b94b4b270694cb70b2c15ac0ea"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.18370845765909932,"ms":0.6804429154197278,"sequence":0.11740630981809595,"static":0.6040176960551386,"topology":0.003298208957414267},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.2044041199175711,"ms":2.0454784559439227,"sequence":0.583215201156672,"static":2.070923495311994,"topology":0.006904130942432061},"total_normalized_loss":0.3877669754639681,"weighted_normalized_losses":{"md":0.36741691531819864,"ms":1.3608858308394556,"sequence":0.058703154909047976,"static":0.15100442401378464,"topology":0.0008245522393535668}},"epoch":53,"improved":false,"step_identity_chain_sha256":"913413f22ca2cd32737d80a3497310d56ee9a3c56c63f4e07cc369a0df62f64b"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.18539548567909112,"ms":0.6766529714521453,"sequence":0.11625312833833575,"static":0.6043026706381643,"topology":0.0029920733819102396},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.20628119995023134,"ms":2.0340855109087865,"sequence":0.577486778470272,"static":2.071900553705166,"topology":0.006263298258176171},"total_normalized_loss":0.3868094328873319,"weighted_normalized_losses":{"md":0.37079097135818223,"ms":1.3533059429042906,"sequence":0.05812656416916787,"static":0.15107566765954109,"topology":0.0007480183454775599}},"epoch":54,"improved":true,"step_identity_chain_sha256":"5a56dd1131a7e16092e6a90761dcddda7d953a9b02013be21bcdbbf0a802bc40"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.18360077804570496,"ms":0.6775535407567341,"sequence":0.1180505303007513,"static":0.6068469521069519,"topology":0.0033234063843095},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.20428430966555874,"ms":2.036792710982263,"sequence":0.5864153628767977,"static":2.080623828382069,"topology":0.006956876640762052},"total_normalized_loss":0.3867752984756138,"weighted_normalized_losses":{"md":0.3672015560914099,"ms":1.3551070815134683,"sequence":0.05902526515037565,"static":0.15171173802673799,"topology":0.000830851596077375}},"epoch":55,"improved":true,"step_identity_chain_sha256":"ddb2a2911f734055a9a27af2aac9ecee0676628234a6cc6d2a40783cdd07dada"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.18322473303664413,"ms":0.6806532835732804,"sequence":0.11936803171721157,"static":0.6086277957821803,"topology":0.003679147716284187},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.20386590133473975,"ms":2.046110843343596,"sequence":0.5929600439490125,"static":2.0867295948730087,"topology":0.007701548906619323},"total_normalized_loss":0.38810335699061416,"weighted_normalized_losses":{"md":0.36644946607328827,"ms":1.3613065671465607,"sequence":0.059684015858605784,"static":0.15215694894554507,"topology":0.0009197869290710468}},"epoch":56,"improved":false,"step_identity_chain_sha256":"35bcd33f3111f1bd29fab1d6ce26847179e59086d510cfd3201a811beb361e21"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.18489347082031377,"ms":0.6799477774086968,"sequence":0.12097173139885309,"static":0.6050795141984117,"topology":0.0026783415226312546},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.20572263064590274,"ms":2.0439900222908833,"sequence":0.6009264133364207,"static":2.0745640246458437,"topology":0.0056065642958219725},"total_normalized_loss":0.3884215652175417,"weighted_normalized_losses":{"md":0.36978694164062753,"ms":1.3598955548173937,"sequence":0.060485865699426544,"static":0.15126987854960292,"topology":0.0006695853806578136}},"epoch":57,"improved":false,"step_identity_chain_sha256":"0ce3e2612758e7a54a43bd3bb38b91b6b28f56240369c17e10387d65a57fb47f"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.18345770502032352,"ms":0.6742300866444119,"sequence":0.11983664951638005,"static":0.6109896249676888,"topology":0.002424522954548807},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.20412511875943667,"ms":2.0268020804208735,"sequence":0.5952879003004393,"static":2.094827317148577,"topology":0.005075246646671062},"total_normalized_loss":0.38572948901364407,"weighted_normalized_losses":{"md":0.36691541004064704,"ms":1.3484601732888237,"sequence":0.05991832475819003,"static":0.1527474062419222,"topology":0.0006061307386372017}},"epoch":58,"improved":true,"step_identity_chain_sha256":"bbc4d6ab68e210958fb43e54319fbc9ff2c3adf5fd559e6c903a7bebb9174ffb"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.18430541764756114,"ms":0.6772358458843342,"sequence":0.11843834313645311,"static":0.6130100008762871,"topology":0.0025234864641710594},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.20506833038791303,"ms":2.035837688889547,"sequence":0.5883418210146559,"static":2.1017543392636653,"topology":0.005282406665268042},"total_normalized_loss":0.38723701409342637,"weighted_normalized_losses":{"md":0.3686108352951223,"ms":1.3544716917686683,"sequence":0.05921917156822656,"static":0.15325250021907177,"topology":0.0006308716160427648}},"epoch":59,"improved":false,"step_identity_chain_sha256":"687971b0d82869252fa7c1b48eef634e327372223f0fb19ca240703d9752ed95"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.1838877833078002,"ms":0.6749785765260923,"sequence":0.1211451243655598,"static":0.6121063319860106,"topology":0.0031933095673136393},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.20460364748352222,"ms":2.0290521147628797,"sequence":0.6017877419491136,"static":2.0986560374273475,"topology":0.006684545362989639},"total_normalized_loss":0.3864260384477792,"weighted_normalized_losses":{"md":0.3677755666156004,"ms":1.3499571530521846,"sequence":0.0605725621827799,"static":0.15302658299650265,"topology":0.0007983273918284098}},"epoch":60,"improved":false,"step_identity_chain_sha256":"59e42a6d27800dbabab6785e733bdbebd6ef23959a5e0b1308c3cd3ded043300"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.18457687056416733,"ms":0.6799754532590466,"sequence":0.12034037085904453,"static":0.6192550061116541,"topology":0.002440056515538208},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.2053703638120949,"ms":2.044073218624268,"sequence":0.5977901333119712,"static":2.123165844513815,"topology":0.005107763003414316},"total_normalized_loss":0.3889397197465497,"weighted_normalized_losses":{"md":0.36915374112833466,"ms":1.3599509065180932,"sequence":0.060170185429522266,"static":0.15481375152791352,"topology":0.000610014128884552}},"epoch":61,"improved":false,"step_identity_chain_sha256":"dc2034f12c0777e9868357640285ed0f944cd341aed61e684219241eca93718e"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.18451724904843766,"ms":0.6783744721375862,"sequence":0.11993402709049762,"static":0.610575358743474,"topology":0.002646263407398155},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.20530402563906702,"ms":2.0392605116093083,"sequence":0.5957716228666721,"static":2.0934069719125956,"topology":0.005539415273181098},"total_normalized_loss":0.3878111722910029,"weighted_normalized_losses":{"md":0.36903449809687533,"ms":1.3567489442751723,"sequence":0.05996701354524881,"static":0.1526438396858685,"topology":0.0006615658518495387}},"epoch":62,"improved":false,"step_identity_chain_sha256":"914a329af955c22b510a20e9a742b47286eed9943d40890667c9b2cd01fd1b44"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.183479316404788,"ms":0.6776447250870751,"sequence":0.11841026921407123,"static":0.6209331289968829,"topology":0.002429041752571319},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.20414916477276648,"ms":2.0370668200647524,"sequence":0.5882023639589442,"static":2.128919424473042,"topology":0.005084705833051504},"total_normalized_loss":0.3874587520556251,"weighted_normalized_losses":{"md":0.366958632809576,"ms":1.3552894501741501,"sequence":0.059205134607035616,"static":0.15523328224922073,"topology":0.0006072604381428297}},"epoch":63,"improved":false,"step_identity_chain_sha256":"c73bf6800b9b71249ca8b0567c1bb5a08f63b9a73e146bc7580374ac7f30834d"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.1839770862407608,"ms":0.6767613667208217,"sequence":0.11981215230251706,"static":0.6118474175612922,"topology":0.0023987463457327595},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.20470301083157091,"ms":2.034411357767912,"sequence":0.5951662105247107,"static":2.097768328393446,"topology":0.005021288548559121},"total_normalized_loss":0.38698890461023594,"weighted_normalized_losses":{"md":0.3679541724815216,"ms":1.3535227334416433,"sequence":0.05990607615125853,"static":0.15296185439032306,"topology":0.0005996865864331899}},"epoch":64,"improved":false,"step_identity_chain_sha256":"44177bb1bdc9d989f02c516b19401fd98bc6e0d74c6ee38ef91634c4447710b3"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.1840057954520985,"ms":0.6791053649388362,"sequence":0.12021965637908434,"static":0.6151097989587911,"topology":0.0026189933671735247},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.20473495427691787,"ms":2.04145764739349,"sequence":0.5971904847937477,"static":2.1089536667218987,"topology":0.005482330979569865},"total_normalized_loss":0.3881528694105806,"weighted_normalized_losses":{"md":0.368011590904197,"ms":1.3582107298776724,"sequence":0.06010982818954217,"static":0.15377744973969779,"topology":0.0006547483417933812}},"epoch":65,"improved":false,"step_identity_chain_sha256":"d1e4eae03c524e388b26674ded529f15d0ba620a9572a09d488b7fd91d1b337a"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.18458304129881448,"ms":0.6778930106022428,"sequence":0.11855682889465703,"static":0.6244757621811947,"topology":0.0024463066961293023},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.20537722971038216,"ms":2.037813190789893,"sequence":0.5889303983697586,"static":2.1410656287060936,"topology":0.005120846487745337},"total_normalized_loss":0.3881922070937548,"weighted_normalized_losses":{"md":0.36916608259762895,"ms":1.3557860212044857,"sequence":0.059278414447328516,"static":0.15611894054529868,"topology":0.0006115766740323256}},"epoch":66,"improved":false,"step_identity_chain_sha256":"35f9a9a13062d8eb7dc8563c986c972e4adc7fa99339ff87265f2a48c0de3dbf"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.18442390757562716,"ms":0.6800514643494341,"sequence":0.1214192548395407,"static":0.6306108756564948,"topology":0.0031009598053264383},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.20520016878977027,"ms":2.044301715452256,"sequence":0.6031494835775972,"static":2.162100361174005,"topology":0.006491229882529015},"total_normalized_loss":0.38961766602706965,"weighted_normalized_losses":{"md":0.3688478151512543,"ms":1.3601029286988682,"sequence":0.06070962741977035,"static":0.1576527189141237,"topology":0.0007752399513316096}},"epoch":67,"improved":false,"step_identity_chain_sha256":"b0f4cd477a45ba36039ed25cd16fc13b90ed5365e1c8ee898084bad7d13ffeca"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.18361496530402258,"ms":0.6741262142646623,"sequence":0.12185378527980724,"static":0.6222918734381624,"topology":0.0024981878603235986},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.20430009518837794,"ms":2.0264898298115566,"sequence":0.6053080111603258,"static":2.1335779896209632,"topology":0.00522944917352667},"total_normalized_loss":0.38652135342037897,"weighted_normalized_losses":{"md":0.36722993060804515,"ms":1.3482524285293247,"sequence":0.06092689263990362,"static":0.1555729683595406,"topology":0.0006245469650808997}},"epoch":68,"improved":false,"step_identity_chain_sha256":"076ecb1a4f813b50f84d86e9de78407809f775bab6232fff8c4bfbc37eaae592"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.18410910225290328,"ms":0.673996083267659,"sequence":0.11852014571671958,"static":0.621748625770358,"topology":0.002154287613960629},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.20484989909747253,"ms":2.0260986432111983,"sequence":0.588748174884215,"static":2.131715421079715,"topology":0.0045095638167523015},"total_normalized_loss":0.3862892344491128,"weighted_normalized_losses":{"md":0.36821820450580656,"ms":1.347992166535318,"sequence":0.05926007285835979,"static":0.1554371564425895,"topology":0.0005385719034901572}},"epoch":69,"improved":false,"step_identity_chain_sha256":"bd1b69f073ada6c240df716653e793aa4cdd588fbac71c752c182c77a9fb5607"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.18340061655024986,"ms":0.6747456800720724,"sequence":0.12225088358616547,"static":0.6182707426786871,"topology":0.0027239572689114313},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.2040615989921296,"ms":2.0283520050720183,"sequence":0.6072805948228267,"static":2.1197912177732077,"topology":0.005702051601029585},"total_normalized_loss":0.3865333420049254,"weighted_normalized_losses":{"md":0.3668012331004997,"ms":1.3494913601441447,"sequence":0.061125441793082734,"static":0.15456768566967177,"topology":0.0006809893172278578}},"epoch":70,"improved":false,"step_identity_chain_sha256":"58b877487b7272d4cb96cca3210d8253569729e85bfecd05b4bf15a815cd074f"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.18375603488669295,"ms":0.675921536063296,"sequence":0.12494299095684128,"static":0.6285623639921295,"topology":0.0021978501680299835},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.2044570569541034,"ms":2.031886744052814,"sequence":0.6206536234458765,"static":2.1550768733459806,"topology":0.004600753180848078},"total_normalized_loss":0.38790333818368766,"weighted_normalized_losses":{"md":0.3675120697733859,"ms":1.351843072126592,"sequence":0.06247149547842064,"static":0.15714059099803238,"topology":0.0005494625420074959}},"epoch":71,"improved":false,"step_identity_chain_sha256":"21fe679e356c863708cd463cb4f97cc5727ed675d96196e10849f99070f5a87d"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.1837435376703293,"ms":0.675566786829554,"sequence":0.12207702804374553,"static":0.6313521664754512,"topology":0.002319502583325566},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.20444315186478537,"ms":2.0308203328984935,"sequence":0.6064169683678112,"static":2.164641936667343,"topology":0.004855407817806645},"total_normalized_loss":0.3876154160572667,"weighted_normalized_losses":{"md":0.3674870753406586,"ms":1.351133573659108,"sequence":0.06103851402187276,"static":0.1578380416188628,"topology":0.0005798756458313915}},"epoch":72,"improved":false,"step_identity_chain_sha256":"fa7add9defcff3fd01d8bbfc74a36de8ad26fc8ce4d61890a7025e31dd55a327"},{"development":{"native_contract_sha256":"1f18091e8b5cd24c2d4937233064ccfb1522d61f71b0e6a2b4cca0cf7224b025","native_surface_sha256":"c102fca3c4dd0df8ac57172da75b90f1dff0954f526330f545474d47a0059f4a","normalized_losses":{"md":0.1842874184263841,"ms":0.6726172266165018,"sequence":0.1200924884666931,"static":0.6200451426897949,"topology":0.0026573603891926574},"parent_counts":{"md":5066,"ms":580,"sequence":55440,"static":5390,"topology":17650},"r4_provenance_chain_sha256":"377a4ff4acb5c062f86cf190f5598d63d99d10ee85b3640c812817976f4b483b","raw_parent_means":{"md":0.20504830346584982,"ms":2.021953664242555,"sequence":0.5965587788852591,"static":2.1258748916408514,"topology":0.0055626445519697575},"total_normalized_loss":0.385906232017773,"weighted_normalized_losses":{"md":0.3685748368527682,"ms":1.3452344532330036,"sequence":0.06004624423334655,"static":0.15501128567244873,"topology":0.0006643400972981643}},"epoch":73,"improved":false,"step_identity_chain_sha256":"e33e5b3a8e3b44c0f5af6f0ff0ac49320eaadbe28d8254685dc22687a8f0e0df"}],"receipt_sha256":"b595e1691e185649a671284778eeb81e0a37414ce5be7f20ac27d7e9c71cdecc","run_identity":{"attribution_claim":"fixed_sequence_heavy_loss_sensitivity_on_final_md_inclusive_a1111","base_control_cell_id":"A111","base_launch_config_sha256":"2a89d6b54668d4db8f1b9fe857f744d31116eb6d28b2695b31461161c1aea2b9","coefficients":{"md":2.0,"ms":2.0,"sequence":0.5,"static":0.25,"topology":0.25},"completed_epoch_resume":true,"core_source_sha256":"3e96d8092239c2c21f217ad5bae4ee7e07dbe0f7630b213bad468d6b08d3b1c1","evaluation_populations":["all_parent_primary","md_present_secondary"],"heldout_access":false,"hpo":false,"initial_model_state_sha256":"128cefb8648ca4519365ec48c3c8c1525735ef2325faf881b64366bae4c5c7bc","loss_denominator":5,"loss_policy":"WA3_FINAL_MS_MD_HEAVY","manifest_sha256":"eeebc9c7e2cfc701f3ad47e62696ae2247c8caec93d8b034d5f573b701eab2a1","maximum_epochs":100,"md_cell_id":"A1111","md_native_intersection_rosters":{"pretraining_development":{"count":5066,"sha256":"b94e6907dc441597ee7ea098894de9ffd7cfe71a61b9ae3a0489f5e1b73e79d8"},"pretraining_train":{"count":22872,"sha256":"6efa5bd7ff81f9b49aab026d44d613765041dc5ea10e116059c9477650f7403a"}},"md_null_receipt_sha256":"ee6147fb6f3448b27823d0edc4ac2922b5322af7967027b778d0b2da03e92aa6","md_package_summary_sha256":"39c6691d762b1ac2d0bed3464b1ed31e4fbe72b18e218ba4a553f3f94702a9e2","md_training_window_policy":{"fixed_development_seed":0,"pretraining_seed":42,"schema":"bertose_review_md_temporal_20x6_a1111_seeded_md_window_20260811_r1","seed43_legacy_exact":true},"native_adapter_contract":{"affinose_supported":false,"authority_set_sha256":"7804332dfc2be432b45f6a82459f21f0b577fc5c358f16b1fea90ba4cb6bb52f","cells":["A000","A100","A010","A001","A110","A101","A011","A111"],"common_seed":42,"development_manifest_sha256":"4eea50c1bd4eee0ea10062c287f31c619cef5835e2e660facd098698859f7e70","development_parent_count":55440,"development_roster_sha256":"dbadd12a88e29cc1a7ca1da85895d89f0162fa8bc9f3dcf8aebf5b8781a1e698","disabled_branch_contract":"static-disabled cell opens no static package/loader/mask stream/payload","downstream_supported":false,"execution_certified":false,"gpu_launch_authorized":false,"loss_policy":{"adaptive_or_weight_ablation":false,"coefficients":[1,"topology_bit","ms_bit","static_bit"],"denominator":4},"matched_weight_policies":["WA1_FINAL_MD_EQUAL_NORMALIZED","WA2_FINAL_MD_SEQUENCE_HEAVY"],"md_supported":false,"nova_submission_authorized":false,"postfit_static":{"binding_sha256":"4ac795da03db66b1f08ad03839dd4b2432fa6f794e6afe77575ae59127f2289b","compatibility_view_persisted":false,"direct_postfit_producer_source_sha256":"8e57c17fd43f3894f94f980cf70a0d6d7f183cf04c26780c3fe30c1932bb7abb","direct_publication_validated_before_compatibility_view":true,"direct_static_bridge_evidence":{"bridge_evidence_sha256":"908452818740e3a406fca7b20605343679c791ed58162b07453635f4ed85e1dd","compatibility_view_persisted":false,"direct_export_receipt_sha256":"b68da847cd4ccd5b6cbfd65e42a4d4b504fcfae00136851fdc980acb1690ad72","direct_join_receipt_sha256":"7b55cf83bd3175e9a9e0be15fc2a9fc998d0803bc67cb2761f69f612e9b6c921","direct_null_file_sha256":"661d04d76fcf36d116feb117154eac01e6569e377d4245c07653b28696e1227b","direct_null_receipt_sha256":"84d8fdb5e960ed0f695c1618d881fe9dd13062e2ad143e099fc7db6415e54c89","direct_publication_file_sha256":"77ba176a9fab70e75b3c2c423c857d1e266f2021875aea01e15bac3f11f327d1","direct_publication_receipt_sha256":"654faac335def8eccb7c50eb8a7d871036bf2a8c223e61f0cb11027830869a84","direct_token_file_sha256":"f9a032f0bd3ad47b99c8a3df2fc46596500e13baf0e77f4b39d26a8351dc7323","direct_token_package_semantic_sha256":"b4c0adb42cc2444e91611c4492c8d385c10fe706a862dbe9b51c144aad80f9e7","native_ablation_data_binding_authorized_by_source_publication":false,"nova_submission_authorized_by_source_publication":false,"official_submitted_artifacts_modified":false,"owner_amendment_file_sha256":"876a3746653254a812d5607d1115abfa112fcefb0772b3828efcb26865dfaf7d","owner_amendment_receipt_sha256":"672d247a416280617634b8f51c7c69716fd7a6fe010db4109fe634b25c531b93","schema":"bertose_review_a5_native_eight_direct_static_bridge_20260724_r1","writer_source_sha256":"ceffd07edb6b8b322baecd95e023053ad8c783cc97cdb2edfc03c0b4fdeeaab6"},"direct_static_bridge_source_sha256":"c71ba654568a24993bc1733b26b6863b11e5c198c53871a6183b485ab96540f0","masker_binding_sha256":"c3373ddbe58ebe15cf6e941f48ea71bcb569fe14b94f394090ffbdaf12faad36","max_static_tokens":192,"nova_submission_authorized":false,"null_receipt_sha256":"661d04d76fcf36d116feb117154eac01e6569e377d4245c07653b28696e1227b","null_scale":3.4285808327094895,"null_scale_hex":"0x1.b6dbbc9a17009p+1","parent_counts":{"pretraining_development":5390,"pretraining_train":22980},"predecessor_compatibility_binding_sha256":"3105b52ff97f720a02be38fb24433087eddd19b4da362fc601a8e7540bb29d25","publication_receipt_semantic_sha256":"a79630e44bba95c7bec3bc59235dc4d8f5012968049e591bd127a26c52063803","publication_receipt_sha256":"77ba176a9fab70e75b3c2c423c857d1e266f2021875aea01e15bac3f11f327d1","release_receipt_sha256":"261099ec7bf32cd72e261ea95d0631702b46cb53cc19085827ed368ba3e3bb63","residue_counts":{"pretraining_development":51237,"pretraining_train":205801},"schema":"bertose_review_a5_native_eight_direct_static_runtime_binding_20260724_r8","state_counts":{"pretraining_development":7964,"pretraining_train":34408},"support_binding_sha256":"38c47a7c323b29bfe9c6a76668de45370789687e50663b0acf52b25bc5f96779","support_sha256_by_slot":["427c4b27091096e0260bb3ad896db841b4b41e9c615bec24cc4330e3e4ddf158","fc55a9e195344141ed497f5a59fa8ab8fcd58f04ccb21c6b7f5a9166cb8d19b6","da96778691370fa5a1c59e471af23113f72c1a93bc277f40d8ea05bdf4aa4720","db2889304eef19132309f70744dc696d2b1bb344473296b5fd7fae48afca8f5c"],"token_count":1028152,"token_export_receipt_sha256":"0e851404deed73e8557ea385a18f9d340c333f259d6c5d171fedc49b09959699","token_null_receipt_sha256":"6333289557fb1fc23324351f30b546a493ef1f2e6ea71efde49a812d3d38bb54","token_package_semantic_sha256":"f434b2cb0ecea84053563faeed700ffd351658e3bb79c8daa4b833404d6691be","token_package_sha256":"f9a032f0bd3ad47b99c8a3df2fc46596500e13baf0e77f4b39d26a8351dc7323","training_authorized":false},"predecessor_adapter_r2_receipt_sha256":"3b2118e128a5550ba4918b4f4f2c6d8045e319b7cff37b76d74dce6b3220c9f0","predecessor_adapter_r2_source_sha256":"9f8f167148aa234df413e4c3d4e1846881781c8e5a19bd91b0b178b260a3a537","predecessor_common_seed":43,"processing_contract":{"ms":"frozen MS-V3 train selection and mask streams parameterized by the declared upstream seed; fixed development seed 0","sequence":"frozen R4 train stream parameterized by the declared upstream seed; fixed development seed 0","static":"frozen final static token stream parameterized by the declared upstream seed; fixed development seed 0","topology":"R4-bound original-residue BFS matrix with receipt-bound inverse-multiplicity equal-parent loss"},"receipt_sha256":"77ba176a9fab70e75b3c2c423c857d1e266f2021875aea01e15bac3f11f327d1","schema":"bertose_review_md_temporal_20x6_a1111_wa2_seed_adapter_20260811_r1","scientific_launch_authorized":false,"seed_parameterization":{"fixed_development_seed":0,"model_rng_seed":42,"ms_train_selection_and_mask_seed":42,"r5_epoch_plan_seed":42,"sequence_train_mask_seed":42,"static_train_mask_seed":42},"sequence_topology_r4":{"bfs_replay_receipt_sha256":"f20a1dd444f2760ccd8605d53ad716ceb55112fd32d3409826bcaf78ff2c6c3d","predecessor_receipt_sha256":"53b058a2032c424718a96757b3aa63df5160c20910001fcb128b0ace03a13a4c","predecessor_relative_path":"review/multimodal/outputs/review_a5_official_ragged_sequence_topology_runtime_20260721_r3","provenance_fields":["sequence_rows","roles","seq_token_categories","topology_rows","topology_residue_counts","topology_target_counts"],"r4_masker_only_checkpoint_restore":true,"r4_store_collation_required":true,"rows_only_through_r4_store_sample":true,"runtime_receipt_sha256":"654f5b9728c3dfd2588c4b570b0e3a1bcab8feb366af28eeead36f9beb37d921","runtime_sha256":"efc56a84cb82f30c0566da83a38bf0f02fdd507e02d116d827c1bbd827151ecf","store_manifest_identity_sha256":"7bd44c2f15715924bce78c7bbdbe57d40fc69aaf90ed834e17d9632bded0fc17","topology_loss_source_sha256":"64eaf9174f523ae909c84987049d071bf3869ca8e83919f14f0572ef77b0530e"},"source_sha256":"4430560565a18da0e68700d60526d3dec15fabd79854111d1e85deb59e2381c8","static_final_token_package_bound":true,"status":"WA2_SEED_PARAMETERIZED_SUCCESSOR","successor_source_sha256":"dd74253863f39150af4ddc7e8d48c0a366e1f327c30aa50e0748078330b97b85","train_manifest_sha256":"13b7ebc78b22baa1a38d2ae40da202dcc1e20e56f44220b4d4d5003ca5f3b8f2","train_parent_count":221827,"train_roster_sha256":"2a7c8121c9ec88418e930cdec47302b7ef2b4d92e01fafa523218461a249de6e","training_authorized":false,"weight_ablation_supported":false,"world_size":1},"native_adapter_contract_sha256":"ad9d49ba49f69d17e8f462930179af4832f741edf6447b880944eef0988423bd","native_launch_sha256":"30082379d47318f5d9e17fafad4aa018e7e9f0f0bf1aac559178d46784fe4b9f","optimizer_contract_sha256":"4c4498fd71ea6a14e654ee7a1e6737bcd578ee328ec73de731cf8da12396c6c0","owner_decision_sha256":"2c7fdb2f522b52fd0692fac9fce8ef5b0a202d1b418b1b9f3570ad7ea9944b83","parameter_summary":{"four_slot_fusion_parameters":2952192,"md_branch_parameters":179206,"total_parameters":138487995,"trainable_parameters":138487995},"patience":15,"precision":"fp32_no_amp","pretraining_seed":42,"runner_source_sha256":"dd74253863f39150af4ddc7e8d48c0a366e1f327c30aa50e0748078330b97b85","schema":"bertose_review_md_temporal_20x6_a1111_wa2_training_20260811_r1","selection_rule":"strict_lower_earliest_tie","semantic_array_id":"md20x6-a1111-wa345-20260817-r1","static_binding_sha256":"4ac795da03db66b1f08ad03839dd4b2432fa6f794e6afe77575ae59127f2289b"},"run_identity_sha256":"55dd7ff33d2196cb1da5e215adb79b0880249f8f1e8c541a7fe36f5759c369d5","schema":"bertose_review_md_temporal_20x6_a1111_wa2_final_20260811_r1","selection":{"best_epoch":58,"best_loss":0.38572948901364407,"completed_epochs":73,"epochs_without_improvement":15,"stop_reason":"patience_exhausted"},"status":"PASS_TRAINING_COMPLETE","terminal_attempt_identity":{"actual_slurm_route":{"account":"ratul-scavenger","partition":"scavenger","qos":"scavenger"},"attempt_sha256":"f299e47d3aaf076a1fc97d2c6ff03e62c0f913bb5ccd97098476e2f02aa302f4","device":{"compute_capability":[9,0],"cuda_visible_devices":"0","name":"NVIDIA H200 NVL","total_memory_bytes":150109880320},"slurm_array_job_id":"12042738","slurm_array_task_id":"0","slurm_job_id":"12042740","slurm_restart_count":1}}
|
releases/2026-10-02/provenance/affinose_arms_on_test_20260909.json
ADDED
|
@@ -0,0 +1,263 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"bob_B_protein_s43": {
|
| 3 |
+
"stratum": "test_protein_cold",
|
| 4 |
+
"seed": 43,
|
| 5 |
+
"test_macro": 0.24463542038572242,
|
| 6 |
+
"test_pooled": 0.26184445034413995,
|
| 7 |
+
"assays": 246,
|
| 8 |
+
"rows": 38539,
|
| 9 |
+
"dir": "affinose_bob_20260909_bob_B_protein_s43"
|
| 10 |
+
},
|
| 11 |
+
"bob_B_protein_s44": {
|
| 12 |
+
"stratum": "test_protein_cold",
|
| 13 |
+
"seed": 44,
|
| 14 |
+
"test_macro": 0.24516174432219207,
|
| 15 |
+
"test_pooled": 0.2730962401378244,
|
| 16 |
+
"assays": 246,
|
| 17 |
+
"rows": 38539,
|
| 18 |
+
"dir": "affinose_bob_20260909_bob_B_protein_s44"
|
| 19 |
+
},
|
| 20 |
+
"mo_A_glycan_s42": {
|
| 21 |
+
"stratum": "test_glycan_cold",
|
| 22 |
+
"seed": 42,
|
| 23 |
+
"test_macro": 0.33405850648525903,
|
| 24 |
+
"test_pooled": 0.3519114017717813,
|
| 25 |
+
"assays": 1767,
|
| 26 |
+
"rows": 37295,
|
| 27 |
+
"dir": "affinose_mo_20260908_mo_A_glycan_s42"
|
| 28 |
+
},
|
| 29 |
+
"mo_C_doubly_s42": {
|
| 30 |
+
"stratum": "test_doubly_cold",
|
| 31 |
+
"seed": 42,
|
| 32 |
+
"test_macro": 0.17732109020146009,
|
| 33 |
+
"test_pooled": 0.19643520103251555,
|
| 34 |
+
"assays": 212,
|
| 35 |
+
"rows": 3691,
|
| 36 |
+
"dir": "affinose_mo_20260908_mo_C_doubly_s42"
|
| 37 |
+
},
|
| 38 |
+
"mof_B_protein_s43": {
|
| 39 |
+
"stratum": "test_protein_cold",
|
| 40 |
+
"seed": 43,
|
| 41 |
+
"test_macro": 0.24512556467979302,
|
| 42 |
+
"test_pooled": 0.2699137753848991,
|
| 43 |
+
"assays": 246,
|
| 44 |
+
"rows": 38539,
|
| 45 |
+
"dir": "affinose_mof_20260909_mof_B_protein_s43"
|
| 46 |
+
},
|
| 47 |
+
"mof_B_protein_s44": {
|
| 48 |
+
"stratum": "test_protein_cold",
|
| 49 |
+
"seed": 44,
|
| 50 |
+
"test_macro": 0.24489399647831056,
|
| 51 |
+
"test_pooled": 0.2547891998912819,
|
| 52 |
+
"assays": 246,
|
| 53 |
+
"rows": 38539,
|
| 54 |
+
"dir": "affinose_mof_20260909_mof_B_protein_s44"
|
| 55 |
+
},
|
| 56 |
+
"mof_C_doubly_s43": {
|
| 57 |
+
"stratum": "test_doubly_cold",
|
| 58 |
+
"seed": 43,
|
| 59 |
+
"test_macro": 0.1839765095395252,
|
| 60 |
+
"test_pooled": 0.2208411762069753,
|
| 61 |
+
"assays": 212,
|
| 62 |
+
"rows": 3691,
|
| 63 |
+
"dir": "affinose_mof_20260909_mof_C_doubly_s43"
|
| 64 |
+
},
|
| 65 |
+
"mof_C_doubly_s44": {
|
| 66 |
+
"stratum": "test_doubly_cold",
|
| 67 |
+
"seed": 44,
|
| 68 |
+
"test_macro": 0.17430173158048537,
|
| 69 |
+
"test_pooled": 0.19176702047106786,
|
| 70 |
+
"assays": 212,
|
| 71 |
+
"rows": 3691,
|
| 72 |
+
"dir": "affinose_mof_20260909_mof_C_doubly_s44"
|
| 73 |
+
},
|
| 74 |
+
"bo_A_glycan_s42": {
|
| 75 |
+
"stratum": "test_glycan_cold",
|
| 76 |
+
"seed": 42,
|
| 77 |
+
"test_macro": 0.2882683038203673,
|
| 78 |
+
"test_pooled": 0.3136364354792883,
|
| 79 |
+
"assays": 1767,
|
| 80 |
+
"rows": 37295,
|
| 81 |
+
"dir": "affinose_sa_20260908_bo_A_glycan_s42"
|
| 82 |
+
},
|
| 83 |
+
"bo_B_protein_s42": {
|
| 84 |
+
"stratum": "test_protein_cold",
|
| 85 |
+
"seed": 42,
|
| 86 |
+
"test_macro": 0.2522396003161021,
|
| 87 |
+
"test_pooled": 0.2653369332383739,
|
| 88 |
+
"assays": 246,
|
| 89 |
+
"rows": 38539,
|
| 90 |
+
"dir": "affinose_sa_20260908_bo_B_protein_s42"
|
| 91 |
+
},
|
| 92 |
+
"bo_C_doubly_s42": {
|
| 93 |
+
"stratum": "test_doubly_cold",
|
| 94 |
+
"seed": 42,
|
| 95 |
+
"test_macro": 0.16472937852334543,
|
| 96 |
+
"test_pooled": 0.1926274802936194,
|
| 97 |
+
"assays": 212,
|
| 98 |
+
"rows": 3691,
|
| 99 |
+
"dir": "affinose_sa_20260908_bo_C_doubly_s42"
|
| 100 |
+
},
|
| 101 |
+
"boa_A_glycan_s43": {
|
| 102 |
+
"stratum": "test_glycan_cold",
|
| 103 |
+
"seed": 43,
|
| 104 |
+
"test_macro": 0.3374435261201508,
|
| 105 |
+
"test_pooled": 0.36037024272127394,
|
| 106 |
+
"assays": 1767,
|
| 107 |
+
"rows": 37295,
|
| 108 |
+
"dir": "affinose_sa_20260908_boa_A_glycan_s43"
|
| 109 |
+
},
|
| 110 |
+
"boa_A_glycan_s44": {
|
| 111 |
+
"stratum": "test_glycan_cold",
|
| 112 |
+
"seed": 44,
|
| 113 |
+
"test_macro": 0.30969468493798785,
|
| 114 |
+
"test_pooled": 0.32123919236737947,
|
| 115 |
+
"assays": 1767,
|
| 116 |
+
"rows": 37295,
|
| 117 |
+
"dir": "affinose_sa_20260908_boa_A_glycan_s44"
|
| 118 |
+
},
|
| 119 |
+
"boc_C_doubly_s43": {
|
| 120 |
+
"stratum": "test_doubly_cold",
|
| 121 |
+
"seed": 43,
|
| 122 |
+
"test_macro": 0.16514492967071465,
|
| 123 |
+
"test_pooled": 0.1791689218089693,
|
| 124 |
+
"assays": 212,
|
| 125 |
+
"rows": 3691,
|
| 126 |
+
"dir": "affinose_sa_20260908_boc_C_doubly_s43"
|
| 127 |
+
},
|
| 128 |
+
"boc_C_doubly_s44": {
|
| 129 |
+
"stratum": "test_doubly_cold",
|
| 130 |
+
"seed": 44,
|
| 131 |
+
"test_macro": 0.20300180090714,
|
| 132 |
+
"test_pooled": 0.23511093681840797,
|
| 133 |
+
"assays": 212,
|
| 134 |
+
"rows": 3691,
|
| 135 |
+
"dir": "affinose_sa_20260908_boc_C_doubly_s44"
|
| 136 |
+
},
|
| 137 |
+
"mc_A_glycan_s42": {
|
| 138 |
+
"stratum": "test_glycan_cold",
|
| 139 |
+
"seed": 42,
|
| 140 |
+
"test_macro": 0.27841973422388244,
|
| 141 |
+
"test_pooled": 0.3022162276393939,
|
| 142 |
+
"assays": 1767,
|
| 143 |
+
"rows": 37295,
|
| 144 |
+
"dir": "affinose_sa_20260908_mc_A_glycan_s42"
|
| 145 |
+
},
|
| 146 |
+
"mc_B_protein_s42": {
|
| 147 |
+
"stratum": "test_protein_cold",
|
| 148 |
+
"seed": 42,
|
| 149 |
+
"test_macro": 0.25218496294299203,
|
| 150 |
+
"test_pooled": 0.26171877856861664,
|
| 151 |
+
"assays": 246,
|
| 152 |
+
"rows": 38539,
|
| 153 |
+
"dir": "affinose_sa_20260908_mc_B_protein_s42"
|
| 154 |
+
},
|
| 155 |
+
"mc_C_doubly_s42": {
|
| 156 |
+
"stratum": "test_doubly_cold",
|
| 157 |
+
"seed": 42,
|
| 158 |
+
"test_macro": 0.15450571314627123,
|
| 159 |
+
"test_pooled": 0.1575716723657401,
|
| 160 |
+
"assays": 212,
|
| 161 |
+
"rows": 3691,
|
| 162 |
+
"dir": "affinose_sa_20260908_mc_C_doubly_s42"
|
| 163 |
+
},
|
| 164 |
+
"mo_B_protein_s42": {
|
| 165 |
+
"stratum": "test_protein_cold",
|
| 166 |
+
"seed": 42,
|
| 167 |
+
"test_macro": 0.23260289913763402,
|
| 168 |
+
"test_pooled": 0.26884245311406896,
|
| 169 |
+
"assays": 246,
|
| 170 |
+
"rows": 38539,
|
| 171 |
+
"dir": "affinose_sa_20260908_mo_B_protein_s42"
|
| 172 |
+
},
|
| 173 |
+
"moc_A_glycan_s43": {
|
| 174 |
+
"stratum": "test_glycan_cold",
|
| 175 |
+
"seed": 43,
|
| 176 |
+
"test_macro": 0.318371586837939,
|
| 177 |
+
"test_pooled": 0.3491029922366602,
|
| 178 |
+
"assays": 1767,
|
| 179 |
+
"rows": 37295,
|
| 180 |
+
"dir": "affinose_sa_20260908_moc_A_glycan_s43"
|
| 181 |
+
},
|
| 182 |
+
"moc_A_glycan_s44": {
|
| 183 |
+
"stratum": "test_glycan_cold",
|
| 184 |
+
"seed": 44,
|
| 185 |
+
"test_macro": 0.3354799039624282,
|
| 186 |
+
"test_pooled": 0.3562564894744605,
|
| 187 |
+
"assays": 1767,
|
| 188 |
+
"rows": 37295,
|
| 189 |
+
"dir": "affinose_sa_20260908_moc_A_glycan_s44"
|
| 190 |
+
},
|
| 191 |
+
"sa_A_glycan_s42": {
|
| 192 |
+
"stratum": "test_glycan_cold",
|
| 193 |
+
"seed": 42,
|
| 194 |
+
"test_macro": 0.28116041536475034,
|
| 195 |
+
"test_pooled": 0.2995676811524887,
|
| 196 |
+
"assays": 1767,
|
| 197 |
+
"rows": 37295,
|
| 198 |
+
"dir": "affinose_sa_20260908_sa_A_glycan_s42"
|
| 199 |
+
},
|
| 200 |
+
"sa_C_doubly_s42": {
|
| 201 |
+
"stratum": "test_doubly_cold",
|
| 202 |
+
"seed": 42,
|
| 203 |
+
"test_macro": 0.14451918425842353,
|
| 204 |
+
"test_pooled": 0.16719428719500484,
|
| 205 |
+
"assays": 212,
|
| 206 |
+
"rows": 3691,
|
| 207 |
+
"dir": "affinose_sa_20260908_sa_C_doubly_s42"
|
| 208 |
+
},
|
| 209 |
+
"swe_A_glycan_s42": {
|
| 210 |
+
"stratum": "test_glycan_cold",
|
| 211 |
+
"seed": 42,
|
| 212 |
+
"test_macro": 0.2919377626107431,
|
| 213 |
+
"test_pooled": 0.3060559058312503,
|
| 214 |
+
"assays": 1767,
|
| 215 |
+
"rows": 37295,
|
| 216 |
+
"dir": "affinose_swe_20260908_swe_A_glycan_s42"
|
| 217 |
+
},
|
| 218 |
+
"swe_C_doubly_s42": {
|
| 219 |
+
"stratum": "test_doubly_cold",
|
| 220 |
+
"seed": 42,
|
| 221 |
+
"test_macro": 0.12325096614703701,
|
| 222 |
+
"test_pooled": 0.13077810558700573,
|
| 223 |
+
"assays": 212,
|
| 224 |
+
"rows": 3691,
|
| 225 |
+
"dir": "affinose_swe_20260908_swe_C_doubly_s42"
|
| 226 |
+
},
|
| 227 |
+
"sz2_A_glycan_s42": {
|
| 228 |
+
"stratum": "test_glycan_cold",
|
| 229 |
+
"seed": 42,
|
| 230 |
+
"test_macro": 0.28711041488202854,
|
| 231 |
+
"test_pooled": 0.3024540500744863,
|
| 232 |
+
"assays": 1767,
|
| 233 |
+
"rows": 37295,
|
| 234 |
+
"dir": "affinose_sz2_20260908_sz2_A_glycan_s42"
|
| 235 |
+
},
|
| 236 |
+
"sz2_C_doubly_s42": {
|
| 237 |
+
"stratum": "test_doubly_cold",
|
| 238 |
+
"seed": 42,
|
| 239 |
+
"test_macro": 0.1490739924202869,
|
| 240 |
+
"test_pooled": 0.166626209128426,
|
| 241 |
+
"assays": 212,
|
| 242 |
+
"rows": 3691,
|
| 243 |
+
"dir": "affinose_sz2_20260908_sz2_C_doubly_s42"
|
| 244 |
+
},
|
| 245 |
+
"szc_C_doubly_s43": {
|
| 246 |
+
"stratum": "test_doubly_cold",
|
| 247 |
+
"seed": 43,
|
| 248 |
+
"test_macro": 0.13519544496948036,
|
| 249 |
+
"test_pooled": 0.1757217730192651,
|
| 250 |
+
"assays": 212,
|
| 251 |
+
"rows": 3691,
|
| 252 |
+
"dir": "affinose_szc_20260908_szc_C_doubly_s43"
|
| 253 |
+
},
|
| 254 |
+
"szc_C_doubly_s44": {
|
| 255 |
+
"stratum": "test_doubly_cold",
|
| 256 |
+
"seed": 44,
|
| 257 |
+
"test_macro": 0.12914485639778248,
|
| 258 |
+
"test_pooled": 0.1359993175882641,
|
| 259 |
+
"assays": 212,
|
| 260 |
+
"rows": 3691,
|
| 261 |
+
"dir": "affinose_szc_20260908_szc_C_doubly_s44"
|
| 262 |
+
}
|
| 263 |
+
}
|
releases/2026-10-02/provenance/affinose_cells/affinose_mo_20260908_mo_A_glycan_s42/receipt.json
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"cell_id": "mo_A_glycan_s42",
|
| 3 |
+
"fingerprint": "cbcc86152b41f424bf9d201d53843e0fdeb2cd9f934e5a1d3f37fe369c35f874",
|
| 4 |
+
"manifest_sha256": "mo_20260908_moA_glycan",
|
| 5 |
+
"args": {
|
| 6 |
+
"csv_path": "/work/ratul1/supantha/Bertint/v2_artifacts/review_affinose_A_glycan_binding.csv",
|
| 7 |
+
"split_path": "/work/ratul1/supantha/Bertint/v2_artifacts/affinose_v2_splits_direct_edit_guarded.json",
|
| 8 |
+
"protein_emb_path": "/work/ratul1/supantha/Bertint/affinose_v2_esmc_by_seqhash_r2.h5",
|
| 9 |
+
"vocab_path": "/work/ratul1/supantha/glycan-SD-VS/bert_training_v3/v3.1_cluster_training/data/review_sequences_a5_non_iar_later_role_official_array_v4_20260721_r1/review_bpe_vocabulary.json",
|
| 10 |
+
"bertose_checkpoint": "/work/ratul1/supantha/bertose_a5_static_precache_20260723_r2c4_closure31_py310_3c8d5299a4af15bc/writing/review/multimodal/outputs/a5_wa345_pretraining_20260817_r1/production/review_md20x6_md20x6-a1111-wa345-20260817-r1_A1111_wa3_seed42/review_checkpoints/review_md20x6_checkpoint_best.pt",
|
| 11 |
+
"output_dir": "/work/ratul1/supantha/Bertint/checkpoints/affinose_mo_20260908_mo_A_glycan_s42",
|
| 12 |
+
"freeze_layers": 4,
|
| 13 |
+
"shared_dim": 512,
|
| 14 |
+
"num_cross_layers": 2,
|
| 15 |
+
"num_heads": 8,
|
| 16 |
+
"swe_slices": 512,
|
| 17 |
+
"dropout": 0.1,
|
| 18 |
+
"protein_dim": 960,
|
| 19 |
+
"separate_swe": false,
|
| 20 |
+
"lr_encoder": 1e-05,
|
| 21 |
+
"lr_head": 5e-05,
|
| 22 |
+
"weight_decay": 0.01,
|
| 23 |
+
"max_grad_norm": 1.0,
|
| 24 |
+
"batch_size": 32,
|
| 25 |
+
"epochs": 30,
|
| 26 |
+
"patience": 10,
|
| 27 |
+
"max_glycan_length": 256,
|
| 28 |
+
"max_protein_length": 1024,
|
| 29 |
+
"protein_mode": "real",
|
| 30 |
+
"ranking_loss": false,
|
| 31 |
+
"assays_per_batch": 4,
|
| 32 |
+
"rows_per_assay": 8,
|
| 33 |
+
"protein_binding_channel": false,
|
| 34 |
+
"glycan_only": false,
|
| 35 |
+
"protein_attentive_pool": false,
|
| 36 |
+
"motif_additive_dim": 165,
|
| 37 |
+
"glycan_size_channel": false,
|
| 38 |
+
"seed": 42,
|
| 39 |
+
"roles_tsv": "/work/ratul1/supantha/Bertint/v2_artifacts/review_affinose_A_glycan_roles.tsv.gz",
|
| 40 |
+
"train_stratum": "fit_train",
|
| 41 |
+
"val_stratum": "val_glycan_cold",
|
| 42 |
+
"test_stratum": "val_glycan_cold",
|
| 43 |
+
"features_dir": "/work/ratul1/supantha/Bertint/data/review_affinose_glycan_features_20260824_r1",
|
| 44 |
+
"expected_train_rows": 484491,
|
| 45 |
+
"expected_val_rows": 36745,
|
| 46 |
+
"expected_test_rows": 36745,
|
| 47 |
+
"manifest_sha256": "mo_20260908_moA_glycan",
|
| 48 |
+
"cell_id": "mo_A_glycan_s42",
|
| 49 |
+
"input_hashes": "/work/ratul1/supantha/Bertint/manifests/affinose_input_hashes_moA_glycan_20260908.json",
|
| 50 |
+
"warmup_pct": 0.05,
|
| 51 |
+
"target_col": "target_rank",
|
| 52 |
+
"checkpoint_interval": 1,
|
| 53 |
+
"resume": false,
|
| 54 |
+
"pooling_mode": "mean",
|
| 55 |
+
"interaction_mode": "concat",
|
| 56 |
+
"no_cross_attention": false
|
| 57 |
+
},
|
| 58 |
+
"input_hashes": {
|
| 59 |
+
"csv": "aa2c0104eb4ac96541081eaa2f0858a6b8575d2c83ce869822ee5107d12ddcb9",
|
| 60 |
+
"roles_tsv": "fd43b4aac814f670519120a012a8ef774a2d4c651bcdc3c34488ac7bed2a9a72",
|
| 61 |
+
"protein_emb_h5": "529ae25ecac7c03d0fc33f8f52f6cacec2db5103f27088d25e9adc06133fdef4",
|
| 62 |
+
"vocabulary": "918c73a55adeb603614112d75bb02033e5823fd9c8a70d43f6c0a4a9c78e360b",
|
| 63 |
+
"upstream_checkpoint": "8e7d95ee492df6d843f495dd4708c97ee16a947e75b5cd8f83b23e4f4a0d6d82",
|
| 64 |
+
"dataset_v8.py": "0cafa57d2b468e1c5ac9d0e9285565de05500fc78ebac467cd09aeceb0e1b6c4",
|
| 65 |
+
"training_v8.py": "6f2ac53d3af2002a8eb42f3b4dc046659a261cdf6fe5eef158724c3527610949",
|
| 66 |
+
"bertint_v8.py": "4df5fcf330bbb4d7d766a141179a5fea76a4e75fc9eef0e403cb567d97dd4564",
|
| 67 |
+
"a1111_encoder_adapter.py": "52c790c24e10061b5890260aad39cefdb6c2c615b8b9c167cc23d86393e41d98",
|
| 68 |
+
"feature_token_ids": "9dbdf73149ce8a3a1d4e1a5322f8a3de68e0f2e1a2e6a73733641e02a9b32ccd",
|
| 69 |
+
"feature_branch_depths": "afa8b69797891b529b212da41726c1d1269e06f26396370e2fcc0b77f25a5086",
|
| 70 |
+
"feature_linkage_types": "3440fc0db96dc3ecdfa315e390fe354c398ded75db8b9017569db7bf6c61610f",
|
| 71 |
+
"feature_attention_mask": "43cdb6ccd9c5e5ecc46aed5ed0c29801144526486e89ba3f611537cea13e8282",
|
| 72 |
+
"feature_tree_channels_valid": "0c867a6e6fdf3a0b72d5fdb76023556d998ad286ef14f0f8f661d760b8f18a2c",
|
| 73 |
+
"feature_motif_features": "d88c2d1342d27f572a27ec030579341a59d72bad89d552695d4db419ff3ceae2",
|
| 74 |
+
"feature_index": "986c4282f79ba621afdd4ad8cfe58d29d79d819946e75d0eb2d9c2316d637a3d",
|
| 75 |
+
"_imported_modules": {
|
| 76 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/training_v8.py": "6f2ac53d3af2002a8eb42f3b4dc046659a261cdf6fe5eef158724c3527610949",
|
| 77 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/bertint_v8.py": "4df5fcf330bbb4d7d766a141179a5fea76a4e75fc9eef0e403cb567d97dd4564",
|
| 78 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/dataset_v8.py": "0cafa57d2b468e1c5ac9d0e9285565de05500fc78ebac467cd09aeceb0e1b6c4",
|
| 79 |
+
"/work/ratul1/supantha/glycan-SD-VS/bert_training_v3/v3.1_cluster_training/bert_training_v4/model/__init__.py": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
| 80 |
+
"/work/ratul1/supantha/glycan-SD-VS/bert_training_v3/v3.1_cluster_training/bert_training_v4/model/glycan_bert.py": "b69f14c9976951325e3a0a4e8107a16126e67d410e966650f513f1f538a732bb",
|
| 81 |
+
"/work/ratul1/supantha/glycan-SD-VS/bert_training_v3/v3.1_cluster_training/bert_training_v4/model/multimodal_glycan_bert_v3.py": "83fde1c18cd6547a6ea026017296b5c94d209ac8f0e125057f03d507b3b65190",
|
| 82 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/a5_tokenizer_shim.py": "771759e04c6c8aabdb928c7a2396fc07af3aefb917b857e07c5c2a0dd77ae96e",
|
| 83 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/a1111_encoder_adapter.py": "52c790c24e10061b5890260aad39cefdb6c2c615b8b9c167cc23d86393e41d98"
|
| 84 |
+
},
|
| 85 |
+
"_roster_digests": {
|
| 86 |
+
"train": "9256821b6057a857ec009868cda30c10d1133790ca283edf7b36bd04e0c784ad",
|
| 87 |
+
"val": "dba86d01797d9f2a30176028da2d07c3f784d8f013faf2ade70391081a20c846",
|
| 88 |
+
"test": "dba86d01797d9f2a30176028da2d07c3f784d8f013faf2ade70391081a20c846"
|
| 89 |
+
}
|
| 90 |
+
},
|
| 91 |
+
"roster_digests": {
|
| 92 |
+
"train": "9256821b6057a857ec009868cda30c10d1133790ca283edf7b36bd04e0c784ad",
|
| 93 |
+
"val": "dba86d01797d9f2a30176028da2d07c3f784d8f013faf2ade70391081a20c846",
|
| 94 |
+
"test": "dba86d01797d9f2a30176028da2d07c3f784d8f013faf2ade70391081a20c846"
|
| 95 |
+
},
|
| 96 |
+
"slurm_job_id": "12247963",
|
| 97 |
+
"slurm_array_task_id": "0",
|
| 98 |
+
"slurm_restart_count": null,
|
| 99 |
+
"node": "nova20-amp-1",
|
| 100 |
+
"gpu": "NVIDIA A100-PCIE-40GB"
|
| 101 |
+
}
|
releases/2026-10-02/provenance/affinose_cells/affinose_mo_20260908_mo_A_glycan_s42/results.json
ADDED
|
@@ -0,0 +1,339 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"task_type": "regression",
|
| 3 |
+
"architecture": "cross-attention=True pooling=mean interaction=concat + live Bertose",
|
| 4 |
+
"best_metric": 0.3518440936915808,
|
| 5 |
+
"best_metric_is": "validation",
|
| 6 |
+
"best_epoch": 8,
|
| 7 |
+
"early_stopped": true,
|
| 8 |
+
"epochs_ran": 19,
|
| 9 |
+
"test_metrics": {
|
| 10 |
+
"spearman": 0.40237059401182945,
|
| 11 |
+
"pearson": 0.4124835133552551,
|
| 12 |
+
"mse": 0.07252673804759979,
|
| 13 |
+
"macro_spearman": 0.3518440936915808,
|
| 14 |
+
"macro_assays_eligible": 1692,
|
| 15 |
+
"macro_assays_total": 1693
|
| 16 |
+
},
|
| 17 |
+
"test_loss": 0.07250597555225989,
|
| 18 |
+
"history": [
|
| 19 |
+
{
|
| 20 |
+
"epoch": 1,
|
| 21 |
+
"train_loss": 0.08178654776577449,
|
| 22 |
+
"val_loss": 0.07449441553264519,
|
| 23 |
+
"val_metrics": {
|
| 24 |
+
"spearman": 0.33265511442497175,
|
| 25 |
+
"pearson": 0.32712677121162415,
|
| 26 |
+
"mse": 0.07448939234018326,
|
| 27 |
+
"macro_spearman": 0.2746683991825071,
|
| 28 |
+
"macro_assays_eligible": 1692,
|
| 29 |
+
"macro_assays_total": 1693
|
| 30 |
+
},
|
| 31 |
+
"lr_encoder": 7.600383347137149e-06,
|
| 32 |
+
"lr_head": 3.8001916735685747e-05
|
| 33 |
+
},
|
| 34 |
+
{
|
| 35 |
+
"epoch": 2,
|
| 36 |
+
"train_loss": 0.07405700735830484,
|
| 37 |
+
"val_loss": 0.07659707693066983,
|
| 38 |
+
"val_metrics": {
|
| 39 |
+
"spearman": 0.3720591600427688,
|
| 40 |
+
"pearson": 0.37388962507247925,
|
| 41 |
+
"mse": 0.07660496979951859,
|
| 42 |
+
"macro_spearman": 0.3207894429302261,
|
| 43 |
+
"macro_assays_eligible": 1692,
|
| 44 |
+
"macro_assays_total": 1693
|
| 45 |
+
},
|
| 46 |
+
"lr_encoder": 9.992405607129421e-06,
|
| 47 |
+
"lr_head": 4.996202803564711e-05
|
| 48 |
+
},
|
| 49 |
+
{
|
| 50 |
+
"epoch": 3,
|
| 51 |
+
"train_loss": 0.06950348176932596,
|
| 52 |
+
"val_loss": 0.0758063778154766,
|
| 53 |
+
"val_metrics": {
|
| 54 |
+
"spearman": 0.3790002388657775,
|
| 55 |
+
"pearson": 0.38117125630378723,
|
| 56 |
+
"mse": 0.07581878453493118,
|
| 57 |
+
"macro_spearman": 0.32246448806993605,
|
| 58 |
+
"macro_assays_eligible": 1692,
|
| 59 |
+
"macro_assays_total": 1693
|
| 60 |
+
},
|
| 61 |
+
"lr_encoder": 9.931800798174588e-06,
|
| 62 |
+
"lr_head": 4.965900399087294e-05
|
| 63 |
+
},
|
| 64 |
+
{
|
| 65 |
+
"epoch": 4,
|
| 66 |
+
"train_loss": 0.06677828642780369,
|
| 67 |
+
"val_loss": 0.07234074125103684,
|
| 68 |
+
"val_metrics": {
|
| 69 |
+
"spearman": 0.3830188559921474,
|
| 70 |
+
"pearson": 0.39124181866645813,
|
| 71 |
+
"mse": 0.07236022502183914,
|
| 72 |
+
"macro_spearman": 0.3261992361563057,
|
| 73 |
+
"macro_assays_eligible": 1692,
|
| 74 |
+
"macro_assays_total": 1693
|
| 75 |
+
},
|
| 76 |
+
"lr_encoder": 9.811330851097227e-06,
|
| 77 |
+
"lr_head": 4.905665425548613e-05
|
| 78 |
+
},
|
| 79 |
+
{
|
| 80 |
+
"epoch": 5,
|
| 81 |
+
"train_loss": 0.06486930890547266,
|
| 82 |
+
"val_loss": 0.07428531616511191,
|
| 83 |
+
"val_metrics": {
|
| 84 |
+
"spearman": 0.4039017349602038,
|
| 85 |
+
"pearson": 0.40416157245635986,
|
| 86 |
+
"mse": 0.0743052139878273,
|
| 87 |
+
"macro_spearman": 0.34451370150779037,
|
| 88 |
+
"macro_assays_eligible": 1692,
|
| 89 |
+
"macro_assays_total": 1693
|
| 90 |
+
},
|
| 91 |
+
"lr_encoder": 9.632458107861948e-06,
|
| 92 |
+
"lr_head": 4.816229053930974e-05
|
| 93 |
+
},
|
| 94 |
+
{
|
| 95 |
+
"epoch": 6,
|
| 96 |
+
"train_loss": 0.06333981823825936,
|
| 97 |
+
"val_loss": 0.07813900106264728,
|
| 98 |
+
"val_metrics": {
|
| 99 |
+
"spearman": 0.36745023533302545,
|
| 100 |
+
"pearson": 0.3778190016746521,
|
| 101 |
+
"mse": 0.07817018032073975,
|
| 102 |
+
"macro_spearman": 0.32126358975578523,
|
| 103 |
+
"macro_assays_eligible": 1692,
|
| 104 |
+
"macro_assays_total": 1693
|
| 105 |
+
},
|
| 106 |
+
"lr_encoder": 9.397353841264184e-06,
|
| 107 |
+
"lr_head": 4.698676920632092e-05
|
| 108 |
+
},
|
| 109 |
+
{
|
| 110 |
+
"epoch": 7,
|
| 111 |
+
"train_loss": 0.06192197361992377,
|
| 112 |
+
"val_loss": 0.07327253127987744,
|
| 113 |
+
"val_metrics": {
|
| 114 |
+
"spearman": 0.40534431983142905,
|
| 115 |
+
"pearson": 0.4101991355419159,
|
| 116 |
+
"mse": 0.07328689843416214,
|
| 117 |
+
"macro_spearman": 0.3481927746525873,
|
| 118 |
+
"macro_assays_eligible": 1692,
|
| 119 |
+
"macro_assays_total": 1693
|
| 120 |
+
},
|
| 121 |
+
"lr_encoder": 9.108871898619753e-06,
|
| 122 |
+
"lr_head": 4.554435949309877e-05
|
| 123 |
+
},
|
| 124 |
+
{
|
| 125 |
+
"epoch": 8,
|
| 126 |
+
"train_loss": 0.0606018938901666,
|
| 127 |
+
"val_loss": 0.07376345989818776,
|
| 128 |
+
"val_metrics": {
|
| 129 |
+
"spearman": 0.3837663608799417,
|
| 130 |
+
"pearson": 0.3917231857776642,
|
| 131 |
+
"mse": 0.07378335297107697,
|
| 132 |
+
"macro_spearman": 0.34328721248155164,
|
| 133 |
+
"macro_assays_eligible": 1692,
|
| 134 |
+
"macro_assays_total": 1693
|
| 135 |
+
},
|
| 136 |
+
"lr_encoder": 8.770514059924366e-06,
|
| 137 |
+
"lr_head": 4.385257029962183e-05
|
| 138 |
+
},
|
| 139 |
+
{
|
| 140 |
+
"epoch": 9,
|
| 141 |
+
"train_loss": 0.05928352163667491,
|
| 142 |
+
"val_loss": 0.07250597555225989,
|
| 143 |
+
"val_metrics": {
|
| 144 |
+
"spearman": 0.40237059401182945,
|
| 145 |
+
"pearson": 0.4124835133552551,
|
| 146 |
+
"mse": 0.07252673804759979,
|
| 147 |
+
"macro_spearman": 0.3518440936915808,
|
| 148 |
+
"macro_assays_eligible": 1692,
|
| 149 |
+
"macro_assays_total": 1693
|
| 150 |
+
},
|
| 151 |
+
"lr_encoder": 8.386387530988106e-06,
|
| 152 |
+
"lr_head": 4.193193765494053e-05
|
| 153 |
+
},
|
| 154 |
+
{
|
| 155 |
+
"epoch": 10,
|
| 156 |
+
"train_loss": 0.057978798184743385,
|
| 157 |
+
"val_loss": 0.07709632041475843,
|
| 158 |
+
"val_metrics": {
|
| 159 |
+
"spearman": 0.3843505992519891,
|
| 160 |
+
"pearson": 0.3893249034881592,
|
| 161 |
+
"mse": 0.07710817456245422,
|
| 162 |
+
"macro_spearman": 0.3388635804374225,
|
| 163 |
+
"macro_assays_eligible": 1692,
|
| 164 |
+
"macro_assays_total": 1693
|
| 165 |
+
},
|
| 166 |
+
"lr_encoder": 7.961155087520675e-06,
|
| 167 |
+
"lr_head": 3.980577543760337e-05
|
| 168 |
+
},
|
| 169 |
+
{
|
| 170 |
+
"epoch": 11,
|
| 171 |
+
"train_loss": 0.05657076605068323,
|
| 172 |
+
"val_loss": 0.07423298842751067,
|
| 173 |
+
"val_metrics": {
|
| 174 |
+
"spearman": 0.3998620770684936,
|
| 175 |
+
"pearson": 0.4072037935256958,
|
| 176 |
+
"mse": 0.07424739003181458,
|
| 177 |
+
"macro_spearman": 0.34683370121850293,
|
| 178 |
+
"macro_assays_eligible": 1692,
|
| 179 |
+
"macro_assays_total": 1693
|
| 180 |
+
},
|
| 181 |
+
"lr_encoder": 7.499978475350636e-06,
|
| 182 |
+
"lr_head": 3.7499892376753175e-05
|
| 183 |
+
},
|
| 184 |
+
{
|
| 185 |
+
"epoch": 12,
|
| 186 |
+
"train_loss": 0.05521496029820552,
|
| 187 |
+
"val_loss": 0.07893912996399703,
|
| 188 |
+
"val_metrics": {
|
| 189 |
+
"spearman": 0.39539492684739164,
|
| 190 |
+
"pearson": 0.40234139561653137,
|
| 191 |
+
"mse": 0.07895530760288239,
|
| 192 |
+
"macro_spearman": 0.34484224357882526,
|
| 193 |
+
"macro_assays_eligible": 1692,
|
| 194 |
+
"macro_assays_total": 1693
|
| 195 |
+
},
|
| 196 |
+
"lr_encoder": 7.0084557538233345e-06,
|
| 197 |
+
"lr_head": 3.504227876911667e-05
|
| 198 |
+
},
|
| 199 |
+
{
|
| 200 |
+
"epoch": 13,
|
| 201 |
+
"train_loss": 0.05384385342549856,
|
| 202 |
+
"val_loss": 0.07758754271336282,
|
| 203 |
+
"val_metrics": {
|
| 204 |
+
"spearman": 0.379476937601036,
|
| 205 |
+
"pearson": 0.38807427883148193,
|
| 206 |
+
"mse": 0.07760068774223328,
|
| 207 |
+
"macro_spearman": 0.33086376694394215,
|
| 208 |
+
"macro_assays_eligible": 1692,
|
| 209 |
+
"macro_assays_total": 1693
|
| 210 |
+
},
|
| 211 |
+
"lr_encoder": 6.492553342943792e-06,
|
| 212 |
+
"lr_head": 3.246276671471896e-05
|
| 213 |
+
},
|
| 214 |
+
{
|
| 215 |
+
"epoch": 14,
|
| 216 |
+
"train_loss": 0.05236243655586875,
|
| 217 |
+
"val_loss": 0.08031580967745955,
|
| 218 |
+
"val_metrics": {
|
| 219 |
+
"spearman": 0.3715908296671469,
|
| 220 |
+
"pearson": 0.383950412273407,
|
| 221 |
+
"mse": 0.08032692223787308,
|
| 222 |
+
"macro_spearman": 0.3383192853501629,
|
| 223 |
+
"macro_assays_eligible": 1692,
|
| 224 |
+
"macro_assays_total": 1693
|
| 225 |
+
},
|
| 226 |
+
"lr_encoder": 5.958533599120159e-06,
|
| 227 |
+
"lr_head": 2.979266799560079e-05
|
| 228 |
+
},
|
| 229 |
+
{
|
| 230 |
+
"epoch": 15,
|
| 231 |
+
"train_loss": 0.050935477340176526,
|
| 232 |
+
"val_loss": 0.08091087176993787,
|
| 233 |
+
"val_metrics": {
|
| 234 |
+
"spearman": 0.3878922278405009,
|
| 235 |
+
"pearson": 0.39411112666130066,
|
| 236 |
+
"mse": 0.08091336488723755,
|
| 237 |
+
"macro_spearman": 0.33990795245997407,
|
| 238 |
+
"macro_assays_eligible": 1692,
|
| 239 |
+
"macro_assays_total": 1693
|
| 240 |
+
},
|
| 241 |
+
"lr_encoder": 5.412878798640137e-06,
|
| 242 |
+
"lr_head": 2.7064393993200682e-05
|
| 243 |
+
},
|
| 244 |
+
{
|
| 245 |
+
"epoch": 16,
|
| 246 |
+
"train_loss": 0.049360674873292626,
|
| 247 |
+
"val_loss": 0.07987832513397107,
|
| 248 |
+
"val_metrics": {
|
| 249 |
+
"spearman": 0.38379380252351775,
|
| 250 |
+
"pearson": 0.38983529806137085,
|
| 251 |
+
"mse": 0.07989616692066193,
|
| 252 |
+
"macro_spearman": 0.3426433799929684,
|
| 253 |
+
"macro_assays_eligible": 1692,
|
| 254 |
+
"macro_assays_total": 1693
|
| 255 |
+
},
|
| 256 |
+
"lr_encoder": 4.862212451617974e-06,
|
| 257 |
+
"lr_head": 2.4311062258089866e-05
|
| 258 |
+
},
|
| 259 |
+
{
|
| 260 |
+
"epoch": 17,
|
| 261 |
+
"train_loss": 0.04789994738429645,
|
| 262 |
+
"val_loss": 0.08231175134041135,
|
| 263 |
+
"val_metrics": {
|
| 264 |
+
"spearman": 0.3703845261663136,
|
| 265 |
+
"pearson": 0.37726807594299316,
|
| 266 |
+
"mse": 0.08232666552066803,
|
| 267 |
+
"macro_spearman": 0.32730402321783136,
|
| 268 |
+
"macro_assays_eligible": 1692,
|
| 269 |
+
"macro_assays_total": 1693
|
| 270 |
+
},
|
| 271 |
+
"lr_encoder": 4.3132189015541166e-06,
|
| 272 |
+
"lr_head": 2.156609450777058e-05
|
| 273 |
+
},
|
| 274 |
+
{
|
| 275 |
+
"epoch": 18,
|
| 276 |
+
"train_loss": 0.046404292282118356,
|
| 277 |
+
"val_loss": 0.08147809532405346,
|
| 278 |
+
"val_metrics": {
|
| 279 |
+
"spearman": 0.3681362465685154,
|
| 280 |
+
"pearson": 0.37861087918281555,
|
| 281 |
+
"mse": 0.08149037510156631,
|
| 282 |
+
"macro_spearman": 0.32856892560631556,
|
| 283 |
+
"macro_assays_eligible": 1692,
|
| 284 |
+
"macro_assays_total": 1693
|
| 285 |
+
},
|
| 286 |
+
"lr_encoder": 3.772562186459968e-06,
|
| 287 |
+
"lr_head": 1.886281093229984e-05
|
| 288 |
+
},
|
| 289 |
+
{
|
| 290 |
+
"epoch": 19,
|
| 291 |
+
"train_loss": 0.0449393058915869,
|
| 292 |
+
"val_loss": 0.08430918386843124,
|
| 293 |
+
"val_metrics": {
|
| 294 |
+
"spearman": 0.3660089664694847,
|
| 295 |
+
"pearson": 0.37466129660606384,
|
| 296 |
+
"mse": 0.08431710302829742,
|
| 297 |
+
"macro_spearman": 0.32766400341899166,
|
| 298 |
+
"macro_assays_eligible": 1692,
|
| 299 |
+
"macro_assays_total": 1693
|
| 300 |
+
},
|
| 301 |
+
"lr_encoder": 3.246805146463778e-06,
|
| 302 |
+
"lr_head": 1.6234025732318888e-05
|
| 303 |
+
}
|
| 304 |
+
],
|
| 305 |
+
"fingerprint": "cbcc86152b41f424bf9d201d53843e0fdeb2cd9f934e5a1d3f37fe369c35f874",
|
| 306 |
+
"input_hashes": {
|
| 307 |
+
"csv": "aa2c0104eb4ac96541081eaa2f0858a6b8575d2c83ce869822ee5107d12ddcb9",
|
| 308 |
+
"roles_tsv": "fd43b4aac814f670519120a012a8ef774a2d4c651bcdc3c34488ac7bed2a9a72",
|
| 309 |
+
"protein_emb_h5": "529ae25ecac7c03d0fc33f8f52f6cacec2db5103f27088d25e9adc06133fdef4",
|
| 310 |
+
"vocabulary": "918c73a55adeb603614112d75bb02033e5823fd9c8a70d43f6c0a4a9c78e360b",
|
| 311 |
+
"upstream_checkpoint": "8e7d95ee492df6d843f495dd4708c97ee16a947e75b5cd8f83b23e4f4a0d6d82",
|
| 312 |
+
"dataset_v8.py": "0cafa57d2b468e1c5ac9d0e9285565de05500fc78ebac467cd09aeceb0e1b6c4",
|
| 313 |
+
"training_v8.py": "6f2ac53d3af2002a8eb42f3b4dc046659a261cdf6fe5eef158724c3527610949",
|
| 314 |
+
"bertint_v8.py": "4df5fcf330bbb4d7d766a141179a5fea76a4e75fc9eef0e403cb567d97dd4564",
|
| 315 |
+
"a1111_encoder_adapter.py": "52c790c24e10061b5890260aad39cefdb6c2c615b8b9c167cc23d86393e41d98",
|
| 316 |
+
"feature_token_ids": "9dbdf73149ce8a3a1d4e1a5322f8a3de68e0f2e1a2e6a73733641e02a9b32ccd",
|
| 317 |
+
"feature_branch_depths": "afa8b69797891b529b212da41726c1d1269e06f26396370e2fcc0b77f25a5086",
|
| 318 |
+
"feature_linkage_types": "3440fc0db96dc3ecdfa315e390fe354c398ded75db8b9017569db7bf6c61610f",
|
| 319 |
+
"feature_attention_mask": "43cdb6ccd9c5e5ecc46aed5ed0c29801144526486e89ba3f611537cea13e8282",
|
| 320 |
+
"feature_tree_channels_valid": "0c867a6e6fdf3a0b72d5fdb76023556d998ad286ef14f0f8f661d760b8f18a2c",
|
| 321 |
+
"feature_motif_features": "d88c2d1342d27f572a27ec030579341a59d72bad89d552695d4db419ff3ceae2",
|
| 322 |
+
"feature_index": "986c4282f79ba621afdd4ad8cfe58d29d79d819946e75d0eb2d9c2316d637a3d",
|
| 323 |
+
"_imported_modules": {
|
| 324 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/training_v8.py": "6f2ac53d3af2002a8eb42f3b4dc046659a261cdf6fe5eef158724c3527610949",
|
| 325 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/bertint_v8.py": "4df5fcf330bbb4d7d766a141179a5fea76a4e75fc9eef0e403cb567d97dd4564",
|
| 326 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/dataset_v8.py": "0cafa57d2b468e1c5ac9d0e9285565de05500fc78ebac467cd09aeceb0e1b6c4",
|
| 327 |
+
"/work/ratul1/supantha/glycan-SD-VS/bert_training_v3/v3.1_cluster_training/bert_training_v4/model/__init__.py": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
| 328 |
+
"/work/ratul1/supantha/glycan-SD-VS/bert_training_v3/v3.1_cluster_training/bert_training_v4/model/glycan_bert.py": "b69f14c9976951325e3a0a4e8107a16126e67d410e966650f513f1f538a732bb",
|
| 329 |
+
"/work/ratul1/supantha/glycan-SD-VS/bert_training_v3/v3.1_cluster_training/bert_training_v4/model/multimodal_glycan_bert_v3.py": "83fde1c18cd6547a6ea026017296b5c94d209ac8f0e125057f03d507b3b65190",
|
| 330 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/a5_tokenizer_shim.py": "771759e04c6c8aabdb928c7a2396fc07af3aefb917b857e07c5c2a0dd77ae96e",
|
| 331 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/a1111_encoder_adapter.py": "52c790c24e10061b5890260aad39cefdb6c2c615b8b9c167cc23d86393e41d98"
|
| 332 |
+
},
|
| 333 |
+
"_roster_digests": {
|
| 334 |
+
"train": "9256821b6057a857ec009868cda30c10d1133790ca283edf7b36bd04e0c784ad",
|
| 335 |
+
"val": "dba86d01797d9f2a30176028da2d07c3f784d8f013faf2ade70391081a20c846",
|
| 336 |
+
"test": "dba86d01797d9f2a30176028da2d07c3f784d8f013faf2ade70391081a20c846"
|
| 337 |
+
}
|
| 338 |
+
}
|
| 339 |
+
}
|
releases/2026-10-02/provenance/affinose_cells/affinose_mo_20260908_mo_C_doubly_s42/receipt.json
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"cell_id": "mo_C_doubly_s42",
|
| 3 |
+
"fingerprint": "20f398ef9542391b9fa12a01e6db7ad58ced7587299a05dfd707be73ddbb9ec6",
|
| 4 |
+
"manifest_sha256": "mo_20260908_moC_doubly",
|
| 5 |
+
"args": {
|
| 6 |
+
"csv_path": "/work/ratul1/supantha/Bertint/v2_artifacts/review_affinose_C_doubly_binding.csv",
|
| 7 |
+
"split_path": "/work/ratul1/supantha/Bertint/v2_artifacts/affinose_v2_splits_direct_edit_guarded.json",
|
| 8 |
+
"protein_emb_path": "/work/ratul1/supantha/Bertint/affinose_v2_esmc_by_seqhash_r2.h5",
|
| 9 |
+
"vocab_path": "/work/ratul1/supantha/glycan-SD-VS/bert_training_v3/v3.1_cluster_training/data/review_sequences_a5_non_iar_later_role_official_array_v4_20260721_r1/review_bpe_vocabulary.json",
|
| 10 |
+
"bertose_checkpoint": "/work/ratul1/supantha/bertose_a5_static_precache_20260723_r2c4_closure31_py310_3c8d5299a4af15bc/writing/review/multimodal/outputs/a5_wa345_pretraining_20260817_r1/production/review_md20x6_md20x6-a1111-wa345-20260817-r1_A1111_wa3_seed42/review_checkpoints/review_md20x6_checkpoint_best.pt",
|
| 11 |
+
"output_dir": "/work/ratul1/supantha/Bertint/checkpoints/affinose_mo_20260908_mo_C_doubly_s42",
|
| 12 |
+
"freeze_layers": 4,
|
| 13 |
+
"shared_dim": 512,
|
| 14 |
+
"num_cross_layers": 2,
|
| 15 |
+
"num_heads": 8,
|
| 16 |
+
"swe_slices": 512,
|
| 17 |
+
"dropout": 0.1,
|
| 18 |
+
"protein_dim": 960,
|
| 19 |
+
"separate_swe": false,
|
| 20 |
+
"lr_encoder": 1e-05,
|
| 21 |
+
"lr_head": 5e-05,
|
| 22 |
+
"weight_decay": 0.01,
|
| 23 |
+
"max_grad_norm": 1.0,
|
| 24 |
+
"batch_size": 32,
|
| 25 |
+
"epochs": 30,
|
| 26 |
+
"patience": 10,
|
| 27 |
+
"max_glycan_length": 256,
|
| 28 |
+
"max_protein_length": 1024,
|
| 29 |
+
"protein_mode": "real",
|
| 30 |
+
"ranking_loss": false,
|
| 31 |
+
"assays_per_batch": 4,
|
| 32 |
+
"rows_per_assay": 8,
|
| 33 |
+
"protein_binding_channel": false,
|
| 34 |
+
"glycan_only": false,
|
| 35 |
+
"protein_attentive_pool": false,
|
| 36 |
+
"motif_additive_dim": 165,
|
| 37 |
+
"glycan_size_channel": false,
|
| 38 |
+
"seed": 42,
|
| 39 |
+
"roles_tsv": "/work/ratul1/supantha/Bertint/v2_artifacts/review_affinose_C_doubly_roles.tsv.gz",
|
| 40 |
+
"train_stratum": "fit_train",
|
| 41 |
+
"val_stratum": "val_doubly_cold",
|
| 42 |
+
"test_stratum": "val_doubly_cold",
|
| 43 |
+
"features_dir": "/work/ratul1/supantha/Bertint/data/review_affinose_glycan_features_20260824_r1",
|
| 44 |
+
"expected_train_rows": 406483,
|
| 45 |
+
"expected_val_rows": 3822,
|
| 46 |
+
"expected_test_rows": 3822,
|
| 47 |
+
"manifest_sha256": "mo_20260908_moC_doubly",
|
| 48 |
+
"cell_id": "mo_C_doubly_s42",
|
| 49 |
+
"input_hashes": "/work/ratul1/supantha/Bertint/manifests/affinose_input_hashes_moC_doubly_20260908.json",
|
| 50 |
+
"warmup_pct": 0.05,
|
| 51 |
+
"target_col": "target_rank",
|
| 52 |
+
"checkpoint_interval": 1,
|
| 53 |
+
"resume": false,
|
| 54 |
+
"pooling_mode": "mean",
|
| 55 |
+
"interaction_mode": "concat",
|
| 56 |
+
"no_cross_attention": false
|
| 57 |
+
},
|
| 58 |
+
"input_hashes": {
|
| 59 |
+
"csv": "e43e150423cb998a77037ad6d82c158a65431b59c46b168febf263ad36267df4",
|
| 60 |
+
"roles_tsv": "e82fb6d73d3ce3ff33e32bd0a8d2e81a0aa4b19b8819bf18339c4aa0382dc5fd",
|
| 61 |
+
"protein_emb_h5": "529ae25ecac7c03d0fc33f8f52f6cacec2db5103f27088d25e9adc06133fdef4",
|
| 62 |
+
"vocabulary": "918c73a55adeb603614112d75bb02033e5823fd9c8a70d43f6c0a4a9c78e360b",
|
| 63 |
+
"upstream_checkpoint": "8e7d95ee492df6d843f495dd4708c97ee16a947e75b5cd8f83b23e4f4a0d6d82",
|
| 64 |
+
"dataset_v8.py": "0cafa57d2b468e1c5ac9d0e9285565de05500fc78ebac467cd09aeceb0e1b6c4",
|
| 65 |
+
"training_v8.py": "6f2ac53d3af2002a8eb42f3b4dc046659a261cdf6fe5eef158724c3527610949",
|
| 66 |
+
"bertint_v8.py": "4df5fcf330bbb4d7d766a141179a5fea76a4e75fc9eef0e403cb567d97dd4564",
|
| 67 |
+
"a1111_encoder_adapter.py": "52c790c24e10061b5890260aad39cefdb6c2c615b8b9c167cc23d86393e41d98",
|
| 68 |
+
"feature_token_ids": "9dbdf73149ce8a3a1d4e1a5322f8a3de68e0f2e1a2e6a73733641e02a9b32ccd",
|
| 69 |
+
"feature_branch_depths": "afa8b69797891b529b212da41726c1d1269e06f26396370e2fcc0b77f25a5086",
|
| 70 |
+
"feature_linkage_types": "3440fc0db96dc3ecdfa315e390fe354c398ded75db8b9017569db7bf6c61610f",
|
| 71 |
+
"feature_attention_mask": "43cdb6ccd9c5e5ecc46aed5ed0c29801144526486e89ba3f611537cea13e8282",
|
| 72 |
+
"feature_tree_channels_valid": "0c867a6e6fdf3a0b72d5fdb76023556d998ad286ef14f0f8f661d760b8f18a2c",
|
| 73 |
+
"feature_motif_features": "d88c2d1342d27f572a27ec030579341a59d72bad89d552695d4db419ff3ceae2",
|
| 74 |
+
"feature_index": "986c4282f79ba621afdd4ad8cfe58d29d79d819946e75d0eb2d9c2316d637a3d",
|
| 75 |
+
"_imported_modules": {
|
| 76 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/training_v8.py": "6f2ac53d3af2002a8eb42f3b4dc046659a261cdf6fe5eef158724c3527610949",
|
| 77 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/bertint_v8.py": "4df5fcf330bbb4d7d766a141179a5fea76a4e75fc9eef0e403cb567d97dd4564",
|
| 78 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/dataset_v8.py": "0cafa57d2b468e1c5ac9d0e9285565de05500fc78ebac467cd09aeceb0e1b6c4",
|
| 79 |
+
"/work/ratul1/supantha/glycan-SD-VS/bert_training_v3/v3.1_cluster_training/bert_training_v4/model/__init__.py": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
| 80 |
+
"/work/ratul1/supantha/glycan-SD-VS/bert_training_v3/v3.1_cluster_training/bert_training_v4/model/glycan_bert.py": "b69f14c9976951325e3a0a4e8107a16126e67d410e966650f513f1f538a732bb",
|
| 81 |
+
"/work/ratul1/supantha/glycan-SD-VS/bert_training_v3/v3.1_cluster_training/bert_training_v4/model/multimodal_glycan_bert_v3.py": "83fde1c18cd6547a6ea026017296b5c94d209ac8f0e125057f03d507b3b65190",
|
| 82 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/a5_tokenizer_shim.py": "771759e04c6c8aabdb928c7a2396fc07af3aefb917b857e07c5c2a0dd77ae96e",
|
| 83 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/a1111_encoder_adapter.py": "52c790c24e10061b5890260aad39cefdb6c2c615b8b9c167cc23d86393e41d98"
|
| 84 |
+
},
|
| 85 |
+
"_roster_digests": {
|
| 86 |
+
"train": "f6ec937bb55813139ed1b26e07953c95d78fd1fe99ccec1f03bb74c09b7960f5",
|
| 87 |
+
"val": "c537ff22ab74b5b6c6ec94e76ef3de2b6ffc1e17086c11657e5f29b0d88da391",
|
| 88 |
+
"test": "c537ff22ab74b5b6c6ec94e76ef3de2b6ffc1e17086c11657e5f29b0d88da391"
|
| 89 |
+
}
|
| 90 |
+
},
|
| 91 |
+
"roster_digests": {
|
| 92 |
+
"train": "f6ec937bb55813139ed1b26e07953c95d78fd1fe99ccec1f03bb74c09b7960f5",
|
| 93 |
+
"val": "c537ff22ab74b5b6c6ec94e76ef3de2b6ffc1e17086c11657e5f29b0d88da391",
|
| 94 |
+
"test": "c537ff22ab74b5b6c6ec94e76ef3de2b6ffc1e17086c11657e5f29b0d88da391"
|
| 95 |
+
},
|
| 96 |
+
"slurm_job_id": "12247962",
|
| 97 |
+
"slurm_array_task_id": "2",
|
| 98 |
+
"slurm_restart_count": null,
|
| 99 |
+
"node": "nova22-gpu-2",
|
| 100 |
+
"gpu": "NVIDIA A100 80GB PCIe"
|
| 101 |
+
}
|
releases/2026-10-02/provenance/affinose_cells/affinose_mo_20260908_mo_C_doubly_s42/results.json
ADDED
|
@@ -0,0 +1,294 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"task_type": "regression",
|
| 3 |
+
"architecture": "cross-attention=True pooling=mean interaction=concat + live Bertose",
|
| 4 |
+
"best_metric": 0.18989928027597247,
|
| 5 |
+
"best_metric_is": "validation",
|
| 6 |
+
"best_epoch": 5,
|
| 7 |
+
"early_stopped": true,
|
| 8 |
+
"epochs_ran": 16,
|
| 9 |
+
"test_metrics": {
|
| 10 |
+
"spearman": 0.23230760714549056,
|
| 11 |
+
"pearson": 0.22095870971679688,
|
| 12 |
+
"mse": 0.0810273140668869,
|
| 13 |
+
"macro_spearman": 0.18989928027597247,
|
| 14 |
+
"macro_assays_eligible": 218,
|
| 15 |
+
"macro_assays_total": 218
|
| 16 |
+
},
|
| 17 |
+
"test_loss": 0.08108399153376619,
|
| 18 |
+
"history": [
|
| 19 |
+
{
|
| 20 |
+
"epoch": 1,
|
| 21 |
+
"train_loss": 0.0820725598469075,
|
| 22 |
+
"val_loss": 0.07980532947306831,
|
| 23 |
+
"val_metrics": {
|
| 24 |
+
"spearman": 0.21861695636332937,
|
| 25 |
+
"pearson": 0.21602514386177063,
|
| 26 |
+
"mse": 0.07971526682376862,
|
| 27 |
+
"macro_spearman": 0.1879467160935374,
|
| 28 |
+
"macro_assays_eligible": 218,
|
| 29 |
+
"macro_assays_total": 218
|
| 30 |
+
},
|
| 31 |
+
"lr_encoder": 7.600456921860401e-06,
|
| 32 |
+
"lr_head": 3.800228460930201e-05
|
| 33 |
+
},
|
| 34 |
+
{
|
| 35 |
+
"epoch": 2,
|
| 36 |
+
"train_loss": 0.07351148931354597,
|
| 37 |
+
"val_loss": 0.08033600815882286,
|
| 38 |
+
"val_metrics": {
|
| 39 |
+
"spearman": 0.2209620955843994,
|
| 40 |
+
"pearson": 0.22815755009651184,
|
| 41 |
+
"mse": 0.08022104948759079,
|
| 42 |
+
"macro_spearman": 0.18053212057010906,
|
| 43 |
+
"macro_assays_eligible": 218,
|
| 44 |
+
"macro_assays_total": 218
|
| 45 |
+
},
|
| 46 |
+
"lr_encoder": 9.992405222215124e-06,
|
| 47 |
+
"lr_head": 4.996202611107562e-05
|
| 48 |
+
},
|
| 49 |
+
{
|
| 50 |
+
"epoch": 3,
|
| 51 |
+
"train_loss": 0.0686865865012365,
|
| 52 |
+
"val_loss": 0.08297244912634293,
|
| 53 |
+
"val_metrics": {
|
| 54 |
+
"spearman": 0.2323234331604067,
|
| 55 |
+
"pearson": 0.229558527469635,
|
| 56 |
+
"mse": 0.08294177800416946,
|
| 57 |
+
"macro_spearman": 0.18236981617035328,
|
| 58 |
+
"macro_assays_eligible": 218,
|
| 59 |
+
"macro_assays_total": 218
|
| 60 |
+
},
|
| 61 |
+
"lr_encoder": 9.93179964821535e-06,
|
| 62 |
+
"lr_head": 4.9658998241076745e-05
|
| 63 |
+
},
|
| 64 |
+
{
|
| 65 |
+
"epoch": 4,
|
| 66 |
+
"train_loss": 0.06548485753726821,
|
| 67 |
+
"val_loss": 0.08214062657207251,
|
| 68 |
+
"val_metrics": {
|
| 69 |
+
"spearman": 0.21538099756417373,
|
| 70 |
+
"pearson": 0.21252787113189697,
|
| 71 |
+
"mse": 0.08202281594276428,
|
| 72 |
+
"macro_spearman": 0.17564361108553003,
|
| 73 |
+
"macro_assays_eligible": 218,
|
| 74 |
+
"macro_assays_total": 218
|
| 75 |
+
},
|
| 76 |
+
"lr_encoder": 9.811328950051998e-06,
|
| 77 |
+
"lr_head": 4.905664475025999e-05
|
| 78 |
+
},
|
| 79 |
+
{
|
| 80 |
+
"epoch": 5,
|
| 81 |
+
"train_loss": 0.06347042579143139,
|
| 82 |
+
"val_loss": 0.07959065570806463,
|
| 83 |
+
"val_metrics": {
|
| 84 |
+
"spearman": 0.22659004415366746,
|
| 85 |
+
"pearson": 0.22342076897621155,
|
| 86 |
+
"mse": 0.07952506840229034,
|
| 87 |
+
"macro_spearman": 0.18600536931930212,
|
| 88 |
+
"macro_assays_eligible": 218,
|
| 89 |
+
"macro_assays_total": 218
|
| 90 |
+
},
|
| 91 |
+
"lr_encoder": 9.632455478806839e-06,
|
| 92 |
+
"lr_head": 4.816227739403419e-05
|
| 93 |
+
},
|
| 94 |
+
{
|
| 95 |
+
"epoch": 6,
|
| 96 |
+
"train_loss": 0.06186302897038609,
|
| 97 |
+
"val_loss": 0.08108399153376619,
|
| 98 |
+
"val_metrics": {
|
| 99 |
+
"spearman": 0.23230760714549056,
|
| 100 |
+
"pearson": 0.22095870971679688,
|
| 101 |
+
"mse": 0.0810273140668869,
|
| 102 |
+
"macro_spearman": 0.18989928027597247,
|
| 103 |
+
"macro_assays_eligible": 218,
|
| 104 |
+
"macro_assays_total": 218
|
| 105 |
+
},
|
| 106 |
+
"lr_encoder": 9.397350516112365e-06,
|
| 107 |
+
"lr_head": 4.698675258056182e-05
|
| 108 |
+
},
|
| 109 |
+
{
|
| 110 |
+
"epoch": 7,
|
| 111 |
+
"train_loss": 0.06046433661505199,
|
| 112 |
+
"val_loss": 0.08360768208901087,
|
| 113 |
+
"val_metrics": {
|
| 114 |
+
"spearman": 0.20523514826535216,
|
| 115 |
+
"pearson": 0.20831626653671265,
|
| 116 |
+
"mse": 0.0835791826248169,
|
| 117 |
+
"macro_spearman": 0.17609303468973836,
|
| 118 |
+
"macro_assays_eligible": 218,
|
| 119 |
+
"macro_assays_total": 218
|
| 120 |
+
},
|
| 121 |
+
"lr_encoder": 9.108867917734062e-06,
|
| 122 |
+
"lr_head": 4.554433958867031e-05
|
| 123 |
+
},
|
| 124 |
+
{
|
| 125 |
+
"epoch": 8,
|
| 126 |
+
"train_loss": 0.05909844870552025,
|
| 127 |
+
"val_loss": 0.0824368055909872,
|
| 128 |
+
"val_metrics": {
|
| 129 |
+
"spearman": 0.20461729443087306,
|
| 130 |
+
"pearson": 0.20222266018390656,
|
| 131 |
+
"mse": 0.08249732106924057,
|
| 132 |
+
"macro_spearman": 0.17707328238386544,
|
| 133 |
+
"macro_assays_eligible": 218,
|
| 134 |
+
"macro_assays_total": 218
|
| 135 |
+
},
|
| 136 |
+
"lr_encoder": 8.770509471627362e-06,
|
| 137 |
+
"lr_head": 4.385254735813681e-05
|
| 138 |
+
},
|
| 139 |
+
{
|
| 140 |
+
"epoch": 9,
|
| 141 |
+
"train_loss": 0.057828584789735946,
|
| 142 |
+
"val_loss": 0.08604417247697711,
|
| 143 |
+
"val_metrics": {
|
| 144 |
+
"spearman": 0.20312934852690515,
|
| 145 |
+
"pearson": 0.2025664895772934,
|
| 146 |
+
"mse": 0.08613406866788864,
|
| 147 |
+
"macro_spearman": 0.16849112239141736,
|
| 148 |
+
"macro_assays_eligible": 218,
|
| 149 |
+
"macro_assays_total": 218
|
| 150 |
+
},
|
| 151 |
+
"lr_encoder": 8.3863823909755e-06,
|
| 152 |
+
"lr_head": 4.1931911954877495e-05
|
| 153 |
+
},
|
| 154 |
+
{
|
| 155 |
+
"epoch": 10,
|
| 156 |
+
"train_loss": 0.056629490814496,
|
| 157 |
+
"val_loss": 0.08503294388453166,
|
| 158 |
+
"val_metrics": {
|
| 159 |
+
"spearman": 0.20220513112798374,
|
| 160 |
+
"pearson": 0.20082733035087585,
|
| 161 |
+
"mse": 0.08514758199453354,
|
| 162 |
+
"macro_spearman": 0.16524417323252355,
|
| 163 |
+
"macro_assays_eligible": 218,
|
| 164 |
+
"macro_assays_total": 218
|
| 165 |
+
},
|
| 166 |
+
"lr_encoder": 7.961149458185257e-06,
|
| 167 |
+
"lr_head": 3.9805747290926286e-05
|
| 168 |
+
},
|
| 169 |
+
{
|
| 170 |
+
"epoch": 11,
|
| 171 |
+
"train_loss": 0.05531735030949904,
|
| 172 |
+
"val_loss": 0.08600124850248297,
|
| 173 |
+
"val_metrics": {
|
| 174 |
+
"spearman": 0.198682925808775,
|
| 175 |
+
"pearson": 0.1959197223186493,
|
| 176 |
+
"mse": 0.08607515692710876,
|
| 177 |
+
"macro_spearman": 0.17737299060322365,
|
| 178 |
+
"macro_assays_eligible": 218,
|
| 179 |
+
"macro_assays_total": 218
|
| 180 |
+
},
|
| 181 |
+
"lr_encoder": 7.499972425024911e-06,
|
| 182 |
+
"lr_head": 3.7499862125124546e-05
|
| 183 |
+
},
|
| 184 |
+
{
|
| 185 |
+
"epoch": 12,
|
| 186 |
+
"train_loss": 0.05402435923889215,
|
| 187 |
+
"val_loss": 0.09162988619258007,
|
| 188 |
+
"val_metrics": {
|
| 189 |
+
"spearman": 0.16928709292866903,
|
| 190 |
+
"pearson": 0.17052659392356873,
|
| 191 |
+
"mse": 0.09164858609437943,
|
| 192 |
+
"macro_spearman": 0.12841904491089645,
|
| 193 |
+
"macro_assays_eligible": 218,
|
| 194 |
+
"macro_assays_total": 218
|
| 195 |
+
},
|
| 196 |
+
"lr_encoder": 7.008449355950063e-06,
|
| 197 |
+
"lr_head": 3.504224677975031e-05
|
| 198 |
+
},
|
| 199 |
+
{
|
| 200 |
+
"epoch": 13,
|
| 201 |
+
"train_loss": 0.052670215866714304,
|
| 202 |
+
"val_loss": 0.09579282198101283,
|
| 203 |
+
"val_metrics": {
|
| 204 |
+
"spearman": 0.15138558513405728,
|
| 205 |
+
"pearson": 0.15384550392627716,
|
| 206 |
+
"mse": 0.09586914628744125,
|
| 207 |
+
"macro_spearman": 0.12292897648647666,
|
| 208 |
+
"macro_assays_eligible": 218,
|
| 209 |
+
"macro_assays_total": 218
|
| 210 |
+
},
|
| 211 |
+
"lr_encoder": 6.492546675184488e-06,
|
| 212 |
+
"lr_head": 3.246273337592243e-05
|
| 213 |
+
},
|
| 214 |
+
{
|
| 215 |
+
"epoch": 14,
|
| 216 |
+
"train_loss": 0.05133482151828506,
|
| 217 |
+
"val_loss": 0.0983895618778964,
|
| 218 |
+
"val_metrics": {
|
| 219 |
+
"spearman": 0.16096614573204776,
|
| 220 |
+
"pearson": 0.16646699607372284,
|
| 221 |
+
"mse": 0.09847484529018402,
|
| 222 |
+
"macro_spearman": 0.1471614747891466,
|
| 223 |
+
"macro_assays_eligible": 218,
|
| 224 |
+
"macro_assays_total": 218
|
| 225 |
+
},
|
| 226 |
+
"lr_encoder": 5.958526742412386e-06,
|
| 227 |
+
"lr_head": 2.9792633712061927e-05
|
| 228 |
+
},
|
| 229 |
+
{
|
| 230 |
+
"epoch": 15,
|
| 231 |
+
"train_loss": 0.04995875641009164,
|
| 232 |
+
"val_loss": 0.10370649403582016,
|
| 233 |
+
"val_metrics": {
|
| 234 |
+
"spearman": 0.1388411585409256,
|
| 235 |
+
"pearson": 0.15041641891002655,
|
| 236 |
+
"mse": 0.10373455286026001,
|
| 237 |
+
"macro_spearman": 0.11630659583110417,
|
| 238 |
+
"macro_assays_eligible": 218,
|
| 239 |
+
"macro_assays_total": 218
|
| 240 |
+
},
|
| 241 |
+
"lr_encoder": 5.412871836215041e-06,
|
| 242 |
+
"lr_head": 2.70643591810752e-05
|
| 243 |
+
},
|
| 244 |
+
{
|
| 245 |
+
"epoch": 16,
|
| 246 |
+
"train_loss": 0.04850863079172903,
|
| 247 |
+
"val_loss": 0.09986912375316023,
|
| 248 |
+
"val_metrics": {
|
| 249 |
+
"spearman": 0.1322993495504737,
|
| 250 |
+
"pearson": 0.13906846940517426,
|
| 251 |
+
"mse": 0.09997473657131195,
|
| 252 |
+
"macro_spearman": 0.10992753432795928,
|
| 253 |
+
"macro_assays_eligible": 218,
|
| 254 |
+
"macro_assays_total": 218
|
| 255 |
+
},
|
| 256 |
+
"lr_encoder": 4.862205467989965e-06,
|
| 257 |
+
"lr_head": 2.431102733994982e-05
|
| 258 |
+
}
|
| 259 |
+
],
|
| 260 |
+
"fingerprint": "20f398ef9542391b9fa12a01e6db7ad58ced7587299a05dfd707be73ddbb9ec6",
|
| 261 |
+
"input_hashes": {
|
| 262 |
+
"csv": "e43e150423cb998a77037ad6d82c158a65431b59c46b168febf263ad36267df4",
|
| 263 |
+
"roles_tsv": "e82fb6d73d3ce3ff33e32bd0a8d2e81a0aa4b19b8819bf18339c4aa0382dc5fd",
|
| 264 |
+
"protein_emb_h5": "529ae25ecac7c03d0fc33f8f52f6cacec2db5103f27088d25e9adc06133fdef4",
|
| 265 |
+
"vocabulary": "918c73a55adeb603614112d75bb02033e5823fd9c8a70d43f6c0a4a9c78e360b",
|
| 266 |
+
"upstream_checkpoint": "8e7d95ee492df6d843f495dd4708c97ee16a947e75b5cd8f83b23e4f4a0d6d82",
|
| 267 |
+
"dataset_v8.py": "0cafa57d2b468e1c5ac9d0e9285565de05500fc78ebac467cd09aeceb0e1b6c4",
|
| 268 |
+
"training_v8.py": "6f2ac53d3af2002a8eb42f3b4dc046659a261cdf6fe5eef158724c3527610949",
|
| 269 |
+
"bertint_v8.py": "4df5fcf330bbb4d7d766a141179a5fea76a4e75fc9eef0e403cb567d97dd4564",
|
| 270 |
+
"a1111_encoder_adapter.py": "52c790c24e10061b5890260aad39cefdb6c2c615b8b9c167cc23d86393e41d98",
|
| 271 |
+
"feature_token_ids": "9dbdf73149ce8a3a1d4e1a5322f8a3de68e0f2e1a2e6a73733641e02a9b32ccd",
|
| 272 |
+
"feature_branch_depths": "afa8b69797891b529b212da41726c1d1269e06f26396370e2fcc0b77f25a5086",
|
| 273 |
+
"feature_linkage_types": "3440fc0db96dc3ecdfa315e390fe354c398ded75db8b9017569db7bf6c61610f",
|
| 274 |
+
"feature_attention_mask": "43cdb6ccd9c5e5ecc46aed5ed0c29801144526486e89ba3f611537cea13e8282",
|
| 275 |
+
"feature_tree_channels_valid": "0c867a6e6fdf3a0b72d5fdb76023556d998ad286ef14f0f8f661d760b8f18a2c",
|
| 276 |
+
"feature_motif_features": "d88c2d1342d27f572a27ec030579341a59d72bad89d552695d4db419ff3ceae2",
|
| 277 |
+
"feature_index": "986c4282f79ba621afdd4ad8cfe58d29d79d819946e75d0eb2d9c2316d637a3d",
|
| 278 |
+
"_imported_modules": {
|
| 279 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/training_v8.py": "6f2ac53d3af2002a8eb42f3b4dc046659a261cdf6fe5eef158724c3527610949",
|
| 280 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/bertint_v8.py": "4df5fcf330bbb4d7d766a141179a5fea76a4e75fc9eef0e403cb567d97dd4564",
|
| 281 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/dataset_v8.py": "0cafa57d2b468e1c5ac9d0e9285565de05500fc78ebac467cd09aeceb0e1b6c4",
|
| 282 |
+
"/work/ratul1/supantha/glycan-SD-VS/bert_training_v3/v3.1_cluster_training/bert_training_v4/model/__init__.py": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
| 283 |
+
"/work/ratul1/supantha/glycan-SD-VS/bert_training_v3/v3.1_cluster_training/bert_training_v4/model/glycan_bert.py": "b69f14c9976951325e3a0a4e8107a16126e67d410e966650f513f1f538a732bb",
|
| 284 |
+
"/work/ratul1/supantha/glycan-SD-VS/bert_training_v3/v3.1_cluster_training/bert_training_v4/model/multimodal_glycan_bert_v3.py": "83fde1c18cd6547a6ea026017296b5c94d209ac8f0e125057f03d507b3b65190",
|
| 285 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/a5_tokenizer_shim.py": "771759e04c6c8aabdb928c7a2396fc07af3aefb917b857e07c5c2a0dd77ae96e",
|
| 286 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/a1111_encoder_adapter.py": "52c790c24e10061b5890260aad39cefdb6c2c615b8b9c167cc23d86393e41d98"
|
| 287 |
+
},
|
| 288 |
+
"_roster_digests": {
|
| 289 |
+
"train": "f6ec937bb55813139ed1b26e07953c95d78fd1fe99ccec1f03bb74c09b7960f5",
|
| 290 |
+
"val": "c537ff22ab74b5b6c6ec94e76ef3de2b6ffc1e17086c11657e5f29b0d88da391",
|
| 291 |
+
"test": "c537ff22ab74b5b6c6ec94e76ef3de2b6ffc1e17086c11657e5f29b0d88da391"
|
| 292 |
+
}
|
| 293 |
+
}
|
| 294 |
+
}
|
releases/2026-10-02/provenance/affinose_cells/affinose_mof_20260909_mof_B_protein_s43/receipt.json
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"cell_id": "mof_B_protein_s43",
|
| 3 |
+
"fingerprint": "10fbf6df61355097aaa03b5b9db42822af419b2c1696866a589fca9efe80bbb9",
|
| 4 |
+
"manifest_sha256": "mof_20260909_moB_protein",
|
| 5 |
+
"args": {
|
| 6 |
+
"csv_path": "/work/ratul1/supantha/Bertint/v2_artifacts/review_affinose_B_protein_binding.csv",
|
| 7 |
+
"split_path": "/work/ratul1/supantha/Bertint/v2_artifacts/affinose_v2_splits_direct_edit_guarded.json",
|
| 8 |
+
"protein_emb_path": "/work/ratul1/supantha/Bertint/affinose_v2_esmc_by_seqhash_r2.h5",
|
| 9 |
+
"vocab_path": "/work/ratul1/supantha/glycan-SD-VS/bert_training_v3/v3.1_cluster_training/data/review_sequences_a5_non_iar_later_role_official_array_v4_20260721_r1/review_bpe_vocabulary.json",
|
| 10 |
+
"bertose_checkpoint": "/work/ratul1/supantha/bertose_a5_static_precache_20260723_r2c4_closure31_py310_3c8d5299a4af15bc/writing/review/multimodal/outputs/a5_wa345_pretraining_20260817_r1/production/review_md20x6_md20x6-a1111-wa345-20260817-r1_A1111_wa3_seed42/review_checkpoints/review_md20x6_checkpoint_best.pt",
|
| 11 |
+
"output_dir": "/work/ratul1/supantha/Bertint/checkpoints/affinose_mof_20260909_mof_B_protein_s43",
|
| 12 |
+
"freeze_layers": 4,
|
| 13 |
+
"shared_dim": 512,
|
| 14 |
+
"num_cross_layers": 2,
|
| 15 |
+
"num_heads": 8,
|
| 16 |
+
"swe_slices": 512,
|
| 17 |
+
"dropout": 0.1,
|
| 18 |
+
"protein_dim": 960,
|
| 19 |
+
"separate_swe": false,
|
| 20 |
+
"lr_encoder": 1e-05,
|
| 21 |
+
"lr_head": 5e-05,
|
| 22 |
+
"weight_decay": 0.01,
|
| 23 |
+
"max_grad_norm": 1.0,
|
| 24 |
+
"batch_size": 32,
|
| 25 |
+
"epochs": 30,
|
| 26 |
+
"patience": 10,
|
| 27 |
+
"max_glycan_length": 256,
|
| 28 |
+
"max_protein_length": 1024,
|
| 29 |
+
"protein_mode": "real",
|
| 30 |
+
"ranking_loss": false,
|
| 31 |
+
"assays_per_batch": 4,
|
| 32 |
+
"rows_per_assay": 8,
|
| 33 |
+
"protein_binding_channel": false,
|
| 34 |
+
"glycan_only": false,
|
| 35 |
+
"protein_attentive_pool": false,
|
| 36 |
+
"motif_additive_dim": 165,
|
| 37 |
+
"glycan_size_channel": false,
|
| 38 |
+
"seed": 43,
|
| 39 |
+
"roles_tsv": "/work/ratul1/supantha/Bertint/v2_artifacts/review_affinose_B_protein_roles.tsv.gz",
|
| 40 |
+
"train_stratum": "fit_train",
|
| 41 |
+
"val_stratum": "val_protein_cold",
|
| 42 |
+
"test_stratum": "val_protein_cold",
|
| 43 |
+
"features_dir": "/work/ratul1/supantha/Bertint/data/review_affinose_glycan_features_20260824_r1",
|
| 44 |
+
"expected_train_rows": 480431,
|
| 45 |
+
"expected_val_rows": 39477,
|
| 46 |
+
"expected_test_rows": 39477,
|
| 47 |
+
"manifest_sha256": "mof_20260909_moB_protein",
|
| 48 |
+
"cell_id": "mof_B_protein_s43",
|
| 49 |
+
"input_hashes": "/work/ratul1/supantha/Bertint/manifests/affinose_input_hashes_moB_protein_20260908.json",
|
| 50 |
+
"warmup_pct": 0.05,
|
| 51 |
+
"target_col": "target_rank",
|
| 52 |
+
"checkpoint_interval": 1,
|
| 53 |
+
"resume": false,
|
| 54 |
+
"pooling_mode": "mean",
|
| 55 |
+
"interaction_mode": "concat",
|
| 56 |
+
"no_cross_attention": false
|
| 57 |
+
},
|
| 58 |
+
"input_hashes": {
|
| 59 |
+
"csv": "db08ac7409ae5f119a706f8acb7c486154f10f70f59571fa7306178032ec6990",
|
| 60 |
+
"roles_tsv": "6ae90f6fed8e1874479b007d1537531b1a9f9f4db5a89855a9d48947ee0a88bc",
|
| 61 |
+
"protein_emb_h5": "529ae25ecac7c03d0fc33f8f52f6cacec2db5103f27088d25e9adc06133fdef4",
|
| 62 |
+
"vocabulary": "918c73a55adeb603614112d75bb02033e5823fd9c8a70d43f6c0a4a9c78e360b",
|
| 63 |
+
"upstream_checkpoint": "8e7d95ee492df6d843f495dd4708c97ee16a947e75b5cd8f83b23e4f4a0d6d82",
|
| 64 |
+
"dataset_v8.py": "0cafa57d2b468e1c5ac9d0e9285565de05500fc78ebac467cd09aeceb0e1b6c4",
|
| 65 |
+
"training_v8.py": "6f2ac53d3af2002a8eb42f3b4dc046659a261cdf6fe5eef158724c3527610949",
|
| 66 |
+
"bertint_v8.py": "4df5fcf330bbb4d7d766a141179a5fea76a4e75fc9eef0e403cb567d97dd4564",
|
| 67 |
+
"a1111_encoder_adapter.py": "52c790c24e10061b5890260aad39cefdb6c2c615b8b9c167cc23d86393e41d98",
|
| 68 |
+
"feature_token_ids": "9dbdf73149ce8a3a1d4e1a5322f8a3de68e0f2e1a2e6a73733641e02a9b32ccd",
|
| 69 |
+
"feature_branch_depths": "afa8b69797891b529b212da41726c1d1269e06f26396370e2fcc0b77f25a5086",
|
| 70 |
+
"feature_linkage_types": "3440fc0db96dc3ecdfa315e390fe354c398ded75db8b9017569db7bf6c61610f",
|
| 71 |
+
"feature_attention_mask": "43cdb6ccd9c5e5ecc46aed5ed0c29801144526486e89ba3f611537cea13e8282",
|
| 72 |
+
"feature_tree_channels_valid": "0c867a6e6fdf3a0b72d5fdb76023556d998ad286ef14f0f8f661d760b8f18a2c",
|
| 73 |
+
"feature_motif_features": "d88c2d1342d27f572a27ec030579341a59d72bad89d552695d4db419ff3ceae2",
|
| 74 |
+
"feature_index": "986c4282f79ba621afdd4ad8cfe58d29d79d819946e75d0eb2d9c2316d637a3d",
|
| 75 |
+
"_imported_modules": {
|
| 76 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/training_v8.py": "6f2ac53d3af2002a8eb42f3b4dc046659a261cdf6fe5eef158724c3527610949",
|
| 77 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/bertint_v8.py": "4df5fcf330bbb4d7d766a141179a5fea76a4e75fc9eef0e403cb567d97dd4564",
|
| 78 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/dataset_v8.py": "0cafa57d2b468e1c5ac9d0e9285565de05500fc78ebac467cd09aeceb0e1b6c4",
|
| 79 |
+
"/work/ratul1/supantha/glycan-SD-VS/bert_training_v3/v3.1_cluster_training/bert_training_v4/model/__init__.py": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
| 80 |
+
"/work/ratul1/supantha/glycan-SD-VS/bert_training_v3/v3.1_cluster_training/bert_training_v4/model/glycan_bert.py": "b69f14c9976951325e3a0a4e8107a16126e67d410e966650f513f1f538a732bb",
|
| 81 |
+
"/work/ratul1/supantha/glycan-SD-VS/bert_training_v3/v3.1_cluster_training/bert_training_v4/model/multimodal_glycan_bert_v3.py": "83fde1c18cd6547a6ea026017296b5c94d209ac8f0e125057f03d507b3b65190",
|
| 82 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/a5_tokenizer_shim.py": "771759e04c6c8aabdb928c7a2396fc07af3aefb917b857e07c5c2a0dd77ae96e",
|
| 83 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/a1111_encoder_adapter.py": "52c790c24e10061b5890260aad39cefdb6c2c615b8b9c167cc23d86393e41d98"
|
| 84 |
+
},
|
| 85 |
+
"_roster_digests": {
|
| 86 |
+
"train": "fb872366d7c824122b62d484a9a90f41ac7b7998b4213bfbdc03702086090c27",
|
| 87 |
+
"val": "9f258e1549c5fc1d1f21a2204f0dbcc46b0f3af489f8845309bcc0d6a3e78713",
|
| 88 |
+
"test": "9f258e1549c5fc1d1f21a2204f0dbcc46b0f3af489f8845309bcc0d6a3e78713"
|
| 89 |
+
}
|
| 90 |
+
},
|
| 91 |
+
"roster_digests": {
|
| 92 |
+
"train": "fb872366d7c824122b62d484a9a90f41ac7b7998b4213bfbdc03702086090c27",
|
| 93 |
+
"val": "9f258e1549c5fc1d1f21a2204f0dbcc46b0f3af489f8845309bcc0d6a3e78713",
|
| 94 |
+
"test": "9f258e1549c5fc1d1f21a2204f0dbcc46b0f3af489f8845309bcc0d6a3e78713"
|
| 95 |
+
},
|
| 96 |
+
"slurm_job_id": "12252895",
|
| 97 |
+
"slurm_array_task_id": "0",
|
| 98 |
+
"slurm_restart_count": null,
|
| 99 |
+
"node": "nova20-amp-1",
|
| 100 |
+
"gpu": "NVIDIA A100-PCIE-40GB"
|
| 101 |
+
}
|
releases/2026-10-02/provenance/affinose_cells/affinose_mof_20260909_mof_B_protein_s43/results.json
ADDED
|
@@ -0,0 +1,294 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"task_type": "regression",
|
| 3 |
+
"architecture": "cross-attention=True pooling=mean interaction=concat + live Bertose",
|
| 4 |
+
"best_metric": 0.2616803241549893,
|
| 5 |
+
"best_metric_is": "validation",
|
| 6 |
+
"best_epoch": 5,
|
| 7 |
+
"early_stopped": true,
|
| 8 |
+
"epochs_ran": 16,
|
| 9 |
+
"test_metrics": {
|
| 10 |
+
"spearman": 0.26465318005549066,
|
| 11 |
+
"pearson": 0.28739896416664124,
|
| 12 |
+
"mse": 0.07721278071403503,
|
| 13 |
+
"macro_spearman": 0.2616803241549893,
|
| 14 |
+
"macro_assays_eligible": 246,
|
| 15 |
+
"macro_assays_total": 246
|
| 16 |
+
},
|
| 17 |
+
"test_loss": 0.07721429514265475,
|
| 18 |
+
"history": [
|
| 19 |
+
{
|
| 20 |
+
"epoch": 1,
|
| 21 |
+
"train_loss": 0.07954162840542994,
|
| 22 |
+
"val_loss": 0.07782782489325205,
|
| 23 |
+
"val_metrics": {
|
| 24 |
+
"spearman": 0.22831785172608393,
|
| 25 |
+
"pearson": 0.2535228133201599,
|
| 26 |
+
"mse": 0.0778268352150917,
|
| 27 |
+
"macro_spearman": 0.19343641142546214,
|
| 28 |
+
"macro_assays_eligible": 246,
|
| 29 |
+
"macro_assays_total": 246
|
| 30 |
+
},
|
| 31 |
+
"lr_encoder": 7.600386589840024e-06,
|
| 32 |
+
"lr_head": 3.8001932949200124e-05
|
| 33 |
+
},
|
| 34 |
+
{
|
| 35 |
+
"epoch": 2,
|
| 36 |
+
"train_loss": 0.0705886414306581,
|
| 37 |
+
"val_loss": 0.07796654568281706,
|
| 38 |
+
"val_metrics": {
|
| 39 |
+
"spearman": 0.24540228051404406,
|
| 40 |
+
"pearson": 0.26456552743911743,
|
| 41 |
+
"mse": 0.0779670774936676,
|
| 42 |
+
"macro_spearman": 0.2274026008849437,
|
| 43 |
+
"macro_assays_eligible": 246,
|
| 44 |
+
"macro_assays_total": 246
|
| 45 |
+
},
|
| 46 |
+
"lr_encoder": 9.992405590165015e-06,
|
| 47 |
+
"lr_head": 4.996202795082508e-05
|
| 48 |
+
},
|
| 49 |
+
{
|
| 50 |
+
"epoch": 3,
|
| 51 |
+
"train_loss": 0.06549934623372175,
|
| 52 |
+
"val_loss": 0.07865211885042091,
|
| 53 |
+
"val_metrics": {
|
| 54 |
+
"spearman": 0.25215879998564106,
|
| 55 |
+
"pearson": 0.2773054242134094,
|
| 56 |
+
"mse": 0.07865151017904282,
|
| 57 |
+
"macro_spearman": 0.2467353133105788,
|
| 58 |
+
"macro_assays_eligible": 246,
|
| 59 |
+
"macro_assays_total": 246
|
| 60 |
+
},
|
| 61 |
+
"lr_encoder": 9.931800747491785e-06,
|
| 62 |
+
"lr_head": 4.965900373745893e-05
|
| 63 |
+
},
|
| 64 |
+
{
|
| 65 |
+
"epoch": 4,
|
| 66 |
+
"train_loss": 0.06254243126504527,
|
| 67 |
+
"val_loss": 0.07637372648575898,
|
| 68 |
+
"val_metrics": {
|
| 69 |
+
"spearman": 0.2581918487150839,
|
| 70 |
+
"pearson": 0.27826398611068726,
|
| 71 |
+
"mse": 0.0763733983039856,
|
| 72 |
+
"macro_spearman": 0.2570732451916451,
|
| 73 |
+
"macro_assays_eligible": 246,
|
| 74 |
+
"macro_assays_total": 246
|
| 75 |
+
},
|
| 76 |
+
"lr_encoder": 9.811330767311252e-06,
|
| 77 |
+
"lr_head": 4.905665383655626e-05
|
| 78 |
+
},
|
| 79 |
+
{
|
| 80 |
+
"epoch": 5,
|
| 81 |
+
"train_loss": 0.06060447233149826,
|
| 82 |
+
"val_loss": 0.07684949162601822,
|
| 83 |
+
"val_metrics": {
|
| 84 |
+
"spearman": 0.2612953255933512,
|
| 85 |
+
"pearson": 0.2877562940120697,
|
| 86 |
+
"mse": 0.07684440910816193,
|
| 87 |
+
"macro_spearman": 0.25594701858636026,
|
| 88 |
+
"macro_assays_eligible": 246,
|
| 89 |
+
"macro_assays_total": 246
|
| 90 |
+
},
|
| 91 |
+
"lr_encoder": 9.632457991989846e-06,
|
| 92 |
+
"lr_head": 4.816228995994923e-05
|
| 93 |
+
},
|
| 94 |
+
{
|
| 95 |
+
"epoch": 6,
|
| 96 |
+
"train_loss": 0.059014895508832266,
|
| 97 |
+
"val_loss": 0.07721429514265475,
|
| 98 |
+
"val_metrics": {
|
| 99 |
+
"spearman": 0.26465318005549066,
|
| 100 |
+
"pearson": 0.28739896416664124,
|
| 101 |
+
"mse": 0.07721278071403503,
|
| 102 |
+
"macro_spearman": 0.2616803241549893,
|
| 103 |
+
"macro_assays_eligible": 246,
|
| 104 |
+
"macro_assays_total": 246
|
| 105 |
+
},
|
| 106 |
+
"lr_encoder": 9.397353694712487e-06,
|
| 107 |
+
"lr_head": 4.6986768473562434e-05
|
| 108 |
+
},
|
| 109 |
+
{
|
| 110 |
+
"epoch": 7,
|
| 111 |
+
"train_loss": 0.05770590116580162,
|
| 112 |
+
"val_loss": 0.07777405114817272,
|
| 113 |
+
"val_metrics": {
|
| 114 |
+
"spearman": 0.25557701527812,
|
| 115 |
+
"pearson": 0.2826829254627228,
|
| 116 |
+
"mse": 0.07777171581983566,
|
| 117 |
+
"macro_spearman": 0.25234290869807796,
|
| 118 |
+
"macro_assays_eligible": 246,
|
| 119 |
+
"macro_assays_total": 246
|
| 120 |
+
},
|
| 121 |
+
"lr_encoder": 9.108871723167402e-06,
|
| 122 |
+
"lr_head": 4.554435861583701e-05
|
| 123 |
+
},
|
| 124 |
+
{
|
| 125 |
+
"epoch": 8,
|
| 126 |
+
"train_loss": 0.05641176031927989,
|
| 127 |
+
"val_loss": 0.07836433754391618,
|
| 128 |
+
"val_metrics": {
|
| 129 |
+
"spearman": 0.252197774483041,
|
| 130 |
+
"pearson": 0.2744917571544647,
|
| 131 |
+
"mse": 0.07836487889289856,
|
| 132 |
+
"macro_spearman": 0.25088632948434425,
|
| 133 |
+
"macro_assays_eligible": 246,
|
| 134 |
+
"macro_assays_total": 246
|
| 135 |
+
},
|
| 136 |
+
"lr_encoder": 8.770513857701111e-06,
|
| 137 |
+
"lr_head": 4.385256928850556e-05
|
| 138 |
+
},
|
| 139 |
+
{
|
| 140 |
+
"epoch": 9,
|
| 141 |
+
"train_loss": 0.05523392668176769,
|
| 142 |
+
"val_loss": 0.07975887371350919,
|
| 143 |
+
"val_metrics": {
|
| 144 |
+
"spearman": 0.2480565658809454,
|
| 145 |
+
"pearson": 0.2695157825946808,
|
| 146 |
+
"mse": 0.07976102828979492,
|
| 147 |
+
"macro_spearman": 0.24774700422451598,
|
| 148 |
+
"macro_assays_eligible": 246,
|
| 149 |
+
"macro_assays_total": 246
|
| 150 |
+
},
|
| 151 |
+
"lr_encoder": 8.386387304448665e-06,
|
| 152 |
+
"lr_head": 4.193193652224333e-05
|
| 153 |
+
},
|
| 154 |
+
{
|
| 155 |
+
"epoch": 10,
|
| 156 |
+
"train_loss": 0.05410393620964645,
|
| 157 |
+
"val_loss": 0.07961486578983899,
|
| 158 |
+
"val_metrics": {
|
| 159 |
+
"spearman": 0.24158881897101642,
|
| 160 |
+
"pearson": 0.265257865190506,
|
| 161 |
+
"mse": 0.07961051166057587,
|
| 162 |
+
"macro_spearman": 0.24260551808764666,
|
| 163 |
+
"macro_assays_eligible": 246,
|
| 164 |
+
"macro_assays_total": 246
|
| 165 |
+
},
|
| 166 |
+
"lr_encoder": 7.961154839414931e-06,
|
| 167 |
+
"lr_head": 3.9805774197074656e-05
|
| 168 |
+
},
|
| 169 |
+
{
|
| 170 |
+
"epoch": 11,
|
| 171 |
+
"train_loss": 0.052832345262743496,
|
| 172 |
+
"val_loss": 0.07933218951217794,
|
| 173 |
+
"val_metrics": {
|
| 174 |
+
"spearman": 0.24484638376952045,
|
| 175 |
+
"pearson": 0.2682126760482788,
|
| 176 |
+
"mse": 0.07932918518781662,
|
| 177 |
+
"macro_spearman": 0.24749593452745058,
|
| 178 |
+
"macro_assays_eligible": 246,
|
| 179 |
+
"macro_assays_total": 246
|
| 180 |
+
},
|
| 181 |
+
"lr_encoder": 7.4999782086902555e-06,
|
| 182 |
+
"lr_head": 3.749989104345127e-05
|
| 183 |
+
},
|
| 184 |
+
{
|
| 185 |
+
"epoch": 12,
|
| 186 |
+
"train_loss": 0.05168314740412603,
|
| 187 |
+
"val_loss": 0.08014735692396542,
|
| 188 |
+
"val_metrics": {
|
| 189 |
+
"spearman": 0.23723716672899273,
|
| 190 |
+
"pearson": 0.25973254442214966,
|
| 191 |
+
"mse": 0.08014728873968124,
|
| 192 |
+
"macro_spearman": 0.2429886585492663,
|
| 193 |
+
"macro_assays_eligible": 246,
|
| 194 |
+
"macro_assays_total": 246
|
| 195 |
+
},
|
| 196 |
+
"lr_encoder": 7.008455471845214e-06,
|
| 197 |
+
"lr_head": 3.504227735922606e-05
|
| 198 |
+
},
|
| 199 |
+
{
|
| 200 |
+
"epoch": 13,
|
| 201 |
+
"train_loss": 0.05040372731105789,
|
| 202 |
+
"val_loss": 0.08099161927260737,
|
| 203 |
+
"val_metrics": {
|
| 204 |
+
"spearman": 0.2331638007735348,
|
| 205 |
+
"pearson": 0.2553894519805908,
|
| 206 |
+
"mse": 0.08098489046096802,
|
| 207 |
+
"macro_spearman": 0.23570626741202766,
|
| 208 |
+
"macro_assays_eligible": 246,
|
| 209 |
+
"macro_assays_total": 246
|
| 210 |
+
},
|
| 211 |
+
"lr_encoder": 6.4925530490707626e-06,
|
| 212 |
+
"lr_head": 3.246276524535381e-05
|
| 213 |
+
},
|
| 214 |
+
{
|
| 215 |
+
"epoch": 14,
|
| 216 |
+
"train_loss": 0.04912812885086062,
|
| 217 |
+
"val_loss": 0.08161971862224117,
|
| 218 |
+
"val_metrics": {
|
| 219 |
+
"spearman": 0.23137538105705088,
|
| 220 |
+
"pearson": 0.24989166855812073,
|
| 221 |
+
"mse": 0.08161360770463943,
|
| 222 |
+
"macro_spearman": 0.23251248469650745,
|
| 223 |
+
"macro_assays_eligible": 246,
|
| 224 |
+
"macro_assays_total": 246
|
| 225 |
+
},
|
| 226 |
+
"lr_encoder": 5.958533296919441e-06,
|
| 227 |
+
"lr_head": 2.97926664845972e-05
|
| 228 |
+
},
|
| 229 |
+
{
|
| 230 |
+
"epoch": 15,
|
| 231 |
+
"train_loss": 0.047906441031257345,
|
| 232 |
+
"val_loss": 0.08224580197095437,
|
| 233 |
+
"val_metrics": {
|
| 234 |
+
"spearman": 0.23034203959773117,
|
| 235 |
+
"pearson": 0.2500419318675995,
|
| 236 |
+
"mse": 0.08224118500947952,
|
| 237 |
+
"macro_spearman": 0.23809430388858327,
|
| 238 |
+
"macro_assays_eligible": 246,
|
| 239 |
+
"macro_assays_total": 246
|
| 240 |
+
},
|
| 241 |
+
"lr_encoder": 5.41287849178004e-06,
|
| 242 |
+
"lr_head": 2.7064392458900194e-05
|
| 243 |
+
},
|
| 244 |
+
{
|
| 245 |
+
"epoch": 16,
|
| 246 |
+
"train_loss": 0.046632020503746034,
|
| 247 |
+
"val_loss": 0.08478603510841172,
|
| 248 |
+
"val_metrics": {
|
| 249 |
+
"spearman": 0.22068337270420055,
|
| 250 |
+
"pearson": 0.23975464701652527,
|
| 251 |
+
"mse": 0.08478289842605591,
|
| 252 |
+
"macro_spearman": 0.22897272805292576,
|
| 253 |
+
"macro_assays_eligible": 246,
|
| 254 |
+
"macro_assays_total": 246
|
| 255 |
+
},
|
| 256 |
+
"lr_encoder": 4.862212143823363e-06,
|
| 257 |
+
"lr_head": 2.4311060719116812e-05
|
| 258 |
+
}
|
| 259 |
+
],
|
| 260 |
+
"fingerprint": "10fbf6df61355097aaa03b5b9db42822af419b2c1696866a589fca9efe80bbb9",
|
| 261 |
+
"input_hashes": {
|
| 262 |
+
"csv": "db08ac7409ae5f119a706f8acb7c486154f10f70f59571fa7306178032ec6990",
|
| 263 |
+
"roles_tsv": "6ae90f6fed8e1874479b007d1537531b1a9f9f4db5a89855a9d48947ee0a88bc",
|
| 264 |
+
"protein_emb_h5": "529ae25ecac7c03d0fc33f8f52f6cacec2db5103f27088d25e9adc06133fdef4",
|
| 265 |
+
"vocabulary": "918c73a55adeb603614112d75bb02033e5823fd9c8a70d43f6c0a4a9c78e360b",
|
| 266 |
+
"upstream_checkpoint": "8e7d95ee492df6d843f495dd4708c97ee16a947e75b5cd8f83b23e4f4a0d6d82",
|
| 267 |
+
"dataset_v8.py": "0cafa57d2b468e1c5ac9d0e9285565de05500fc78ebac467cd09aeceb0e1b6c4",
|
| 268 |
+
"training_v8.py": "6f2ac53d3af2002a8eb42f3b4dc046659a261cdf6fe5eef158724c3527610949",
|
| 269 |
+
"bertint_v8.py": "4df5fcf330bbb4d7d766a141179a5fea76a4e75fc9eef0e403cb567d97dd4564",
|
| 270 |
+
"a1111_encoder_adapter.py": "52c790c24e10061b5890260aad39cefdb6c2c615b8b9c167cc23d86393e41d98",
|
| 271 |
+
"feature_token_ids": "9dbdf73149ce8a3a1d4e1a5322f8a3de68e0f2e1a2e6a73733641e02a9b32ccd",
|
| 272 |
+
"feature_branch_depths": "afa8b69797891b529b212da41726c1d1269e06f26396370e2fcc0b77f25a5086",
|
| 273 |
+
"feature_linkage_types": "3440fc0db96dc3ecdfa315e390fe354c398ded75db8b9017569db7bf6c61610f",
|
| 274 |
+
"feature_attention_mask": "43cdb6ccd9c5e5ecc46aed5ed0c29801144526486e89ba3f611537cea13e8282",
|
| 275 |
+
"feature_tree_channels_valid": "0c867a6e6fdf3a0b72d5fdb76023556d998ad286ef14f0f8f661d760b8f18a2c",
|
| 276 |
+
"feature_motif_features": "d88c2d1342d27f572a27ec030579341a59d72bad89d552695d4db419ff3ceae2",
|
| 277 |
+
"feature_index": "986c4282f79ba621afdd4ad8cfe58d29d79d819946e75d0eb2d9c2316d637a3d",
|
| 278 |
+
"_imported_modules": {
|
| 279 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/training_v8.py": "6f2ac53d3af2002a8eb42f3b4dc046659a261cdf6fe5eef158724c3527610949",
|
| 280 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/bertint_v8.py": "4df5fcf330bbb4d7d766a141179a5fea76a4e75fc9eef0e403cb567d97dd4564",
|
| 281 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/dataset_v8.py": "0cafa57d2b468e1c5ac9d0e9285565de05500fc78ebac467cd09aeceb0e1b6c4",
|
| 282 |
+
"/work/ratul1/supantha/glycan-SD-VS/bert_training_v3/v3.1_cluster_training/bert_training_v4/model/__init__.py": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
| 283 |
+
"/work/ratul1/supantha/glycan-SD-VS/bert_training_v3/v3.1_cluster_training/bert_training_v4/model/glycan_bert.py": "b69f14c9976951325e3a0a4e8107a16126e67d410e966650f513f1f538a732bb",
|
| 284 |
+
"/work/ratul1/supantha/glycan-SD-VS/bert_training_v3/v3.1_cluster_training/bert_training_v4/model/multimodal_glycan_bert_v3.py": "83fde1c18cd6547a6ea026017296b5c94d209ac8f0e125057f03d507b3b65190",
|
| 285 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/a5_tokenizer_shim.py": "771759e04c6c8aabdb928c7a2396fc07af3aefb917b857e07c5c2a0dd77ae96e",
|
| 286 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/a1111_encoder_adapter.py": "52c790c24e10061b5890260aad39cefdb6c2c615b8b9c167cc23d86393e41d98"
|
| 287 |
+
},
|
| 288 |
+
"_roster_digests": {
|
| 289 |
+
"train": "fb872366d7c824122b62d484a9a90f41ac7b7998b4213bfbdc03702086090c27",
|
| 290 |
+
"val": "9f258e1549c5fc1d1f21a2204f0dbcc46b0f3af489f8845309bcc0d6a3e78713",
|
| 291 |
+
"test": "9f258e1549c5fc1d1f21a2204f0dbcc46b0f3af489f8845309bcc0d6a3e78713"
|
| 292 |
+
}
|
| 293 |
+
}
|
| 294 |
+
}
|
releases/2026-10-02/provenance/affinose_cells/affinose_mof_20260909_mof_B_protein_s44/receipt.json
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"cell_id": "mof_B_protein_s44",
|
| 3 |
+
"fingerprint": "b50035032c9c5017afd6328b7c1e4ab3f6ff7eeb8a1d126c918c5567e207115e",
|
| 4 |
+
"manifest_sha256": "mof_20260909_moB_protein",
|
| 5 |
+
"args": {
|
| 6 |
+
"csv_path": "/work/ratul1/supantha/Bertint/v2_artifacts/review_affinose_B_protein_binding.csv",
|
| 7 |
+
"split_path": "/work/ratul1/supantha/Bertint/v2_artifacts/affinose_v2_splits_direct_edit_guarded.json",
|
| 8 |
+
"protein_emb_path": "/work/ratul1/supantha/Bertint/affinose_v2_esmc_by_seqhash_r2.h5",
|
| 9 |
+
"vocab_path": "/work/ratul1/supantha/glycan-SD-VS/bert_training_v3/v3.1_cluster_training/data/review_sequences_a5_non_iar_later_role_official_array_v4_20260721_r1/review_bpe_vocabulary.json",
|
| 10 |
+
"bertose_checkpoint": "/work/ratul1/supantha/bertose_a5_static_precache_20260723_r2c4_closure31_py310_3c8d5299a4af15bc/writing/review/multimodal/outputs/a5_wa345_pretraining_20260817_r1/production/review_md20x6_md20x6-a1111-wa345-20260817-r1_A1111_wa3_seed42/review_checkpoints/review_md20x6_checkpoint_best.pt",
|
| 11 |
+
"output_dir": "/work/ratul1/supantha/Bertint/checkpoints/affinose_mof_20260909_mof_B_protein_s44",
|
| 12 |
+
"freeze_layers": 4,
|
| 13 |
+
"shared_dim": 512,
|
| 14 |
+
"num_cross_layers": 2,
|
| 15 |
+
"num_heads": 8,
|
| 16 |
+
"swe_slices": 512,
|
| 17 |
+
"dropout": 0.1,
|
| 18 |
+
"protein_dim": 960,
|
| 19 |
+
"separate_swe": false,
|
| 20 |
+
"lr_encoder": 1e-05,
|
| 21 |
+
"lr_head": 5e-05,
|
| 22 |
+
"weight_decay": 0.01,
|
| 23 |
+
"max_grad_norm": 1.0,
|
| 24 |
+
"batch_size": 32,
|
| 25 |
+
"epochs": 30,
|
| 26 |
+
"patience": 10,
|
| 27 |
+
"max_glycan_length": 256,
|
| 28 |
+
"max_protein_length": 1024,
|
| 29 |
+
"protein_mode": "real",
|
| 30 |
+
"ranking_loss": false,
|
| 31 |
+
"assays_per_batch": 4,
|
| 32 |
+
"rows_per_assay": 8,
|
| 33 |
+
"protein_binding_channel": false,
|
| 34 |
+
"glycan_only": false,
|
| 35 |
+
"protein_attentive_pool": false,
|
| 36 |
+
"motif_additive_dim": 165,
|
| 37 |
+
"glycan_size_channel": false,
|
| 38 |
+
"seed": 44,
|
| 39 |
+
"roles_tsv": "/work/ratul1/supantha/Bertint/v2_artifacts/review_affinose_B_protein_roles.tsv.gz",
|
| 40 |
+
"train_stratum": "fit_train",
|
| 41 |
+
"val_stratum": "val_protein_cold",
|
| 42 |
+
"test_stratum": "val_protein_cold",
|
| 43 |
+
"features_dir": "/work/ratul1/supantha/Bertint/data/review_affinose_glycan_features_20260824_r1",
|
| 44 |
+
"expected_train_rows": 480431,
|
| 45 |
+
"expected_val_rows": 39477,
|
| 46 |
+
"expected_test_rows": 39477,
|
| 47 |
+
"manifest_sha256": "mof_20260909_moB_protein",
|
| 48 |
+
"cell_id": "mof_B_protein_s44",
|
| 49 |
+
"input_hashes": "/work/ratul1/supantha/Bertint/manifests/affinose_input_hashes_moB_protein_20260908.json",
|
| 50 |
+
"warmup_pct": 0.05,
|
| 51 |
+
"target_col": "target_rank",
|
| 52 |
+
"checkpoint_interval": 1,
|
| 53 |
+
"resume": false,
|
| 54 |
+
"pooling_mode": "mean",
|
| 55 |
+
"interaction_mode": "concat",
|
| 56 |
+
"no_cross_attention": false
|
| 57 |
+
},
|
| 58 |
+
"input_hashes": {
|
| 59 |
+
"csv": "db08ac7409ae5f119a706f8acb7c486154f10f70f59571fa7306178032ec6990",
|
| 60 |
+
"roles_tsv": "6ae90f6fed8e1874479b007d1537531b1a9f9f4db5a89855a9d48947ee0a88bc",
|
| 61 |
+
"protein_emb_h5": "529ae25ecac7c03d0fc33f8f52f6cacec2db5103f27088d25e9adc06133fdef4",
|
| 62 |
+
"vocabulary": "918c73a55adeb603614112d75bb02033e5823fd9c8a70d43f6c0a4a9c78e360b",
|
| 63 |
+
"upstream_checkpoint": "8e7d95ee492df6d843f495dd4708c97ee16a947e75b5cd8f83b23e4f4a0d6d82",
|
| 64 |
+
"dataset_v8.py": "0cafa57d2b468e1c5ac9d0e9285565de05500fc78ebac467cd09aeceb0e1b6c4",
|
| 65 |
+
"training_v8.py": "6f2ac53d3af2002a8eb42f3b4dc046659a261cdf6fe5eef158724c3527610949",
|
| 66 |
+
"bertint_v8.py": "4df5fcf330bbb4d7d766a141179a5fea76a4e75fc9eef0e403cb567d97dd4564",
|
| 67 |
+
"a1111_encoder_adapter.py": "52c790c24e10061b5890260aad39cefdb6c2c615b8b9c167cc23d86393e41d98",
|
| 68 |
+
"feature_token_ids": "9dbdf73149ce8a3a1d4e1a5322f8a3de68e0f2e1a2e6a73733641e02a9b32ccd",
|
| 69 |
+
"feature_branch_depths": "afa8b69797891b529b212da41726c1d1269e06f26396370e2fcc0b77f25a5086",
|
| 70 |
+
"feature_linkage_types": "3440fc0db96dc3ecdfa315e390fe354c398ded75db8b9017569db7bf6c61610f",
|
| 71 |
+
"feature_attention_mask": "43cdb6ccd9c5e5ecc46aed5ed0c29801144526486e89ba3f611537cea13e8282",
|
| 72 |
+
"feature_tree_channels_valid": "0c867a6e6fdf3a0b72d5fdb76023556d998ad286ef14f0f8f661d760b8f18a2c",
|
| 73 |
+
"feature_motif_features": "d88c2d1342d27f572a27ec030579341a59d72bad89d552695d4db419ff3ceae2",
|
| 74 |
+
"feature_index": "986c4282f79ba621afdd4ad8cfe58d29d79d819946e75d0eb2d9c2316d637a3d",
|
| 75 |
+
"_imported_modules": {
|
| 76 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/training_v8.py": "6f2ac53d3af2002a8eb42f3b4dc046659a261cdf6fe5eef158724c3527610949",
|
| 77 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/bertint_v8.py": "4df5fcf330bbb4d7d766a141179a5fea76a4e75fc9eef0e403cb567d97dd4564",
|
| 78 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/dataset_v8.py": "0cafa57d2b468e1c5ac9d0e9285565de05500fc78ebac467cd09aeceb0e1b6c4",
|
| 79 |
+
"/work/ratul1/supantha/glycan-SD-VS/bert_training_v3/v3.1_cluster_training/bert_training_v4/model/__init__.py": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
| 80 |
+
"/work/ratul1/supantha/glycan-SD-VS/bert_training_v3/v3.1_cluster_training/bert_training_v4/model/glycan_bert.py": "b69f14c9976951325e3a0a4e8107a16126e67d410e966650f513f1f538a732bb",
|
| 81 |
+
"/work/ratul1/supantha/glycan-SD-VS/bert_training_v3/v3.1_cluster_training/bert_training_v4/model/multimodal_glycan_bert_v3.py": "83fde1c18cd6547a6ea026017296b5c94d209ac8f0e125057f03d507b3b65190",
|
| 82 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/a5_tokenizer_shim.py": "771759e04c6c8aabdb928c7a2396fc07af3aefb917b857e07c5c2a0dd77ae96e",
|
| 83 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/a1111_encoder_adapter.py": "52c790c24e10061b5890260aad39cefdb6c2c615b8b9c167cc23d86393e41d98"
|
| 84 |
+
},
|
| 85 |
+
"_roster_digests": {
|
| 86 |
+
"train": "fb872366d7c824122b62d484a9a90f41ac7b7998b4213bfbdc03702086090c27",
|
| 87 |
+
"val": "9f258e1549c5fc1d1f21a2204f0dbcc46b0f3af489f8845309bcc0d6a3e78713",
|
| 88 |
+
"test": "9f258e1549c5fc1d1f21a2204f0dbcc46b0f3af489f8845309bcc0d6a3e78713"
|
| 89 |
+
}
|
| 90 |
+
},
|
| 91 |
+
"roster_digests": {
|
| 92 |
+
"train": "fb872366d7c824122b62d484a9a90f41ac7b7998b4213bfbdc03702086090c27",
|
| 93 |
+
"val": "9f258e1549c5fc1d1f21a2204f0dbcc46b0f3af489f8845309bcc0d6a3e78713",
|
| 94 |
+
"test": "9f258e1549c5fc1d1f21a2204f0dbcc46b0f3af489f8845309bcc0d6a3e78713"
|
| 95 |
+
},
|
| 96 |
+
"slurm_job_id": "12252896",
|
| 97 |
+
"slurm_array_task_id": "1",
|
| 98 |
+
"slurm_restart_count": null,
|
| 99 |
+
"node": "nova20-amp-1",
|
| 100 |
+
"gpu": "NVIDIA A100-PCIE-40GB"
|
| 101 |
+
}
|
releases/2026-10-02/provenance/affinose_cells/affinose_mof_20260909_mof_B_protein_s44/results.json
ADDED
|
@@ -0,0 +1,324 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"task_type": "regression",
|
| 3 |
+
"architecture": "cross-attention=True pooling=mean interaction=concat + live Bertose",
|
| 4 |
+
"best_metric": 0.2619743701834269,
|
| 5 |
+
"best_metric_is": "validation",
|
| 6 |
+
"best_epoch": 7,
|
| 7 |
+
"early_stopped": true,
|
| 8 |
+
"epochs_ran": 18,
|
| 9 |
+
"test_metrics": {
|
| 10 |
+
"spearman": 0.2522903089693993,
|
| 11 |
+
"pearson": 0.27707183361053467,
|
| 12 |
+
"mse": 0.07991175353527069,
|
| 13 |
+
"macro_spearman": 0.2619743701834269,
|
| 14 |
+
"macro_assays_eligible": 246,
|
| 15 |
+
"macro_assays_total": 246
|
| 16 |
+
},
|
| 17 |
+
"test_loss": 0.07990999335522735,
|
| 18 |
+
"history": [
|
| 19 |
+
{
|
| 20 |
+
"epoch": 1,
|
| 21 |
+
"train_loss": 0.07981738362739721,
|
| 22 |
+
"val_loss": 0.07805284763032773,
|
| 23 |
+
"val_metrics": {
|
| 24 |
+
"spearman": 0.22559178242900987,
|
| 25 |
+
"pearson": 0.2486092448234558,
|
| 26 |
+
"mse": 0.07805142551660538,
|
| 27 |
+
"macro_spearman": 0.20130664561426273,
|
| 28 |
+
"macro_assays_eligible": 246,
|
| 29 |
+
"macro_assays_total": 246
|
| 30 |
+
},
|
| 31 |
+
"lr_encoder": 7.600386589840024e-06,
|
| 32 |
+
"lr_head": 3.8001932949200124e-05
|
| 33 |
+
},
|
| 34 |
+
{
|
| 35 |
+
"epoch": 2,
|
| 36 |
+
"train_loss": 0.07078751392609924,
|
| 37 |
+
"val_loss": 0.07947275961931898,
|
| 38 |
+
"val_metrics": {
|
| 39 |
+
"spearman": 0.24995568370609297,
|
| 40 |
+
"pearson": 0.28168702125549316,
|
| 41 |
+
"mse": 0.07947273552417755,
|
| 42 |
+
"macro_spearman": 0.23893393270644228,
|
| 43 |
+
"macro_assays_eligible": 246,
|
| 44 |
+
"macro_assays_total": 246
|
| 45 |
+
},
|
| 46 |
+
"lr_encoder": 9.992405590165015e-06,
|
| 47 |
+
"lr_head": 4.996202795082508e-05
|
| 48 |
+
},
|
| 49 |
+
{
|
| 50 |
+
"epoch": 3,
|
| 51 |
+
"train_loss": 0.0660612302130991,
|
| 52 |
+
"val_loss": 0.07649334600554535,
|
| 53 |
+
"val_metrics": {
|
| 54 |
+
"spearman": 0.2534524155438286,
|
| 55 |
+
"pearson": 0.283633828163147,
|
| 56 |
+
"mse": 0.07649430632591248,
|
| 57 |
+
"macro_spearman": 0.25244388911037446,
|
| 58 |
+
"macro_assays_eligible": 246,
|
| 59 |
+
"macro_assays_total": 246
|
| 60 |
+
},
|
| 61 |
+
"lr_encoder": 9.931800747491785e-06,
|
| 62 |
+
"lr_head": 4.965900373745893e-05
|
| 63 |
+
},
|
| 64 |
+
{
|
| 65 |
+
"epoch": 4,
|
| 66 |
+
"train_loss": 0.06302868131366045,
|
| 67 |
+
"val_loss": 0.07701158229068429,
|
| 68 |
+
"val_metrics": {
|
| 69 |
+
"spearman": 0.25958664299609535,
|
| 70 |
+
"pearson": 0.2883581519126892,
|
| 71 |
+
"mse": 0.07701101154088974,
|
| 72 |
+
"macro_spearman": 0.2571741323432227,
|
| 73 |
+
"macro_assays_eligible": 246,
|
| 74 |
+
"macro_assays_total": 246
|
| 75 |
+
},
|
| 76 |
+
"lr_encoder": 9.811330767311252e-06,
|
| 77 |
+
"lr_head": 4.905665383655626e-05
|
| 78 |
+
},
|
| 79 |
+
{
|
| 80 |
+
"epoch": 5,
|
| 81 |
+
"train_loss": 0.06085977359548701,
|
| 82 |
+
"val_loss": 0.07774806868985319,
|
| 83 |
+
"val_metrics": {
|
| 84 |
+
"spearman": 0.25843513345166563,
|
| 85 |
+
"pearson": 0.28806793689727783,
|
| 86 |
+
"mse": 0.07775115966796875,
|
| 87 |
+
"macro_spearman": 0.25360786179010825,
|
| 88 |
+
"macro_assays_eligible": 246,
|
| 89 |
+
"macro_assays_total": 246
|
| 90 |
+
},
|
| 91 |
+
"lr_encoder": 9.632457991989846e-06,
|
| 92 |
+
"lr_head": 4.816228995994923e-05
|
| 93 |
+
},
|
| 94 |
+
{
|
| 95 |
+
"epoch": 6,
|
| 96 |
+
"train_loss": 0.0592839516819901,
|
| 97 |
+
"val_loss": 0.07740682547208604,
|
| 98 |
+
"val_metrics": {
|
| 99 |
+
"spearman": 0.2630817552232598,
|
| 100 |
+
"pearson": 0.287427693605423,
|
| 101 |
+
"mse": 0.07740595936775208,
|
| 102 |
+
"macro_spearman": 0.26120600347796635,
|
| 103 |
+
"macro_assays_eligible": 246,
|
| 104 |
+
"macro_assays_total": 246
|
| 105 |
+
},
|
| 106 |
+
"lr_encoder": 9.397353694712487e-06,
|
| 107 |
+
"lr_head": 4.6986768473562434e-05
|
| 108 |
+
},
|
| 109 |
+
{
|
| 110 |
+
"epoch": 7,
|
| 111 |
+
"train_loss": 0.057865291745236296,
|
| 112 |
+
"val_loss": 0.07692075606037047,
|
| 113 |
+
"val_metrics": {
|
| 114 |
+
"spearman": 0.25688249514777667,
|
| 115 |
+
"pearson": 0.28290003538131714,
|
| 116 |
+
"mse": 0.07692264020442963,
|
| 117 |
+
"macro_spearman": 0.2534613235639173,
|
| 118 |
+
"macro_assays_eligible": 246,
|
| 119 |
+
"macro_assays_total": 246
|
| 120 |
+
},
|
| 121 |
+
"lr_encoder": 9.108871723167402e-06,
|
| 122 |
+
"lr_head": 4.554435861583701e-05
|
| 123 |
+
},
|
| 124 |
+
{
|
| 125 |
+
"epoch": 8,
|
| 126 |
+
"train_loss": 0.0565786789235537,
|
| 127 |
+
"val_loss": 0.07990999335522735,
|
| 128 |
+
"val_metrics": {
|
| 129 |
+
"spearman": 0.2522903089693993,
|
| 130 |
+
"pearson": 0.27707183361053467,
|
| 131 |
+
"mse": 0.07991175353527069,
|
| 132 |
+
"macro_spearman": 0.2619743701834269,
|
| 133 |
+
"macro_assays_eligible": 246,
|
| 134 |
+
"macro_assays_total": 246
|
| 135 |
+
},
|
| 136 |
+
"lr_encoder": 8.770513857701111e-06,
|
| 137 |
+
"lr_head": 4.385256928850556e-05
|
| 138 |
+
},
|
| 139 |
+
{
|
| 140 |
+
"epoch": 9,
|
| 141 |
+
"train_loss": 0.05532620246784516,
|
| 142 |
+
"val_loss": 0.07763330655163411,
|
| 143 |
+
"val_metrics": {
|
| 144 |
+
"spearman": 0.25102246262105943,
|
| 145 |
+
"pearson": 0.2788107693195343,
|
| 146 |
+
"mse": 0.07763587683439255,
|
| 147 |
+
"macro_spearman": 0.2544694050064656,
|
| 148 |
+
"macro_assays_eligible": 246,
|
| 149 |
+
"macro_assays_total": 246
|
| 150 |
+
},
|
| 151 |
+
"lr_encoder": 8.386387304448665e-06,
|
| 152 |
+
"lr_head": 4.193193652224333e-05
|
| 153 |
+
},
|
| 154 |
+
{
|
| 155 |
+
"epoch": 10,
|
| 156 |
+
"train_loss": 0.05405828924989818,
|
| 157 |
+
"val_loss": 0.07833248711337533,
|
| 158 |
+
"val_metrics": {
|
| 159 |
+
"spearman": 0.2438800982818175,
|
| 160 |
+
"pearson": 0.2745583653450012,
|
| 161 |
+
"mse": 0.07832974940538406,
|
| 162 |
+
"macro_spearman": 0.2523447986921982,
|
| 163 |
+
"macro_assays_eligible": 246,
|
| 164 |
+
"macro_assays_total": 246
|
| 165 |
+
},
|
| 166 |
+
"lr_encoder": 7.961154839414931e-06,
|
| 167 |
+
"lr_head": 3.9805774197074656e-05
|
| 168 |
+
},
|
| 169 |
+
{
|
| 170 |
+
"epoch": 11,
|
| 171 |
+
"train_loss": 0.0528427298379628,
|
| 172 |
+
"val_loss": 0.08058726410056967,
|
| 173 |
+
"val_metrics": {
|
| 174 |
+
"spearman": 0.23660560596604926,
|
| 175 |
+
"pearson": 0.26180699467658997,
|
| 176 |
+
"mse": 0.08058898150920868,
|
| 177 |
+
"macro_spearman": 0.23424278398802012,
|
| 178 |
+
"macro_assays_eligible": 246,
|
| 179 |
+
"macro_assays_total": 246
|
| 180 |
+
},
|
| 181 |
+
"lr_encoder": 7.4999782086902555e-06,
|
| 182 |
+
"lr_head": 3.749989104345127e-05
|
| 183 |
+
},
|
| 184 |
+
{
|
| 185 |
+
"epoch": 12,
|
| 186 |
+
"train_loss": 0.05164120228723162,
|
| 187 |
+
"val_loss": 0.07976167026538902,
|
| 188 |
+
"val_metrics": {
|
| 189 |
+
"spearman": 0.23261825638111633,
|
| 190 |
+
"pearson": 0.2558090090751648,
|
| 191 |
+
"mse": 0.07976232469081879,
|
| 192 |
+
"macro_spearman": 0.23266531292423337,
|
| 193 |
+
"macro_assays_eligible": 246,
|
| 194 |
+
"macro_assays_total": 246
|
| 195 |
+
},
|
| 196 |
+
"lr_encoder": 7.008455471845214e-06,
|
| 197 |
+
"lr_head": 3.504227735922606e-05
|
| 198 |
+
},
|
| 199 |
+
{
|
| 200 |
+
"epoch": 13,
|
| 201 |
+
"train_loss": 0.0503626140305333,
|
| 202 |
+
"val_loss": 0.08149432827457423,
|
| 203 |
+
"val_metrics": {
|
| 204 |
+
"spearman": 0.2278419512374733,
|
| 205 |
+
"pearson": 0.2485179454088211,
|
| 206 |
+
"mse": 0.08149101585149765,
|
| 207 |
+
"macro_spearman": 0.23217940116093283,
|
| 208 |
+
"macro_assays_eligible": 246,
|
| 209 |
+
"macro_assays_total": 246
|
| 210 |
+
},
|
| 211 |
+
"lr_encoder": 6.4925530490707626e-06,
|
| 212 |
+
"lr_head": 3.246276524535381e-05
|
| 213 |
+
},
|
| 214 |
+
{
|
| 215 |
+
"epoch": 14,
|
| 216 |
+
"train_loss": 0.04906632403745221,
|
| 217 |
+
"val_loss": 0.08259034495818847,
|
| 218 |
+
"val_metrics": {
|
| 219 |
+
"spearman": 0.21830880884551201,
|
| 220 |
+
"pearson": 0.24247127771377563,
|
| 221 |
+
"mse": 0.08259105682373047,
|
| 222 |
+
"macro_spearman": 0.22567405660753373,
|
| 223 |
+
"macro_assays_eligible": 246,
|
| 224 |
+
"macro_assays_total": 246
|
| 225 |
+
},
|
| 226 |
+
"lr_encoder": 5.958533296919441e-06,
|
| 227 |
+
"lr_head": 2.97926664845972e-05
|
| 228 |
+
},
|
| 229 |
+
{
|
| 230 |
+
"epoch": 15,
|
| 231 |
+
"train_loss": 0.047798247342370724,
|
| 232 |
+
"val_loss": 0.0822906217340084,
|
| 233 |
+
"val_metrics": {
|
| 234 |
+
"spearman": 0.22129417925423603,
|
| 235 |
+
"pearson": 0.24620899558067322,
|
| 236 |
+
"mse": 0.08228731155395508,
|
| 237 |
+
"macro_spearman": 0.224604572584952,
|
| 238 |
+
"macro_assays_eligible": 246,
|
| 239 |
+
"macro_assays_total": 246
|
| 240 |
+
},
|
| 241 |
+
"lr_encoder": 5.41287849178004e-06,
|
| 242 |
+
"lr_head": 2.7064392458900194e-05
|
| 243 |
+
},
|
| 244 |
+
{
|
| 245 |
+
"epoch": 16,
|
| 246 |
+
"train_loss": 0.046463664239008225,
|
| 247 |
+
"val_loss": 0.08506318003035829,
|
| 248 |
+
"val_metrics": {
|
| 249 |
+
"spearman": 0.2028253755057865,
|
| 250 |
+
"pearson": 0.2229027897119522,
|
| 251 |
+
"mse": 0.08505822718143463,
|
| 252 |
+
"macro_spearman": 0.21227674417314193,
|
| 253 |
+
"macro_assays_eligible": 246,
|
| 254 |
+
"macro_assays_total": 246
|
| 255 |
+
},
|
| 256 |
+
"lr_encoder": 4.862212143823363e-06,
|
| 257 |
+
"lr_head": 2.4311060719116812e-05
|
| 258 |
+
},
|
| 259 |
+
{
|
| 260 |
+
"epoch": 17,
|
| 261 |
+
"train_loss": 0.0452233674025144,
|
| 262 |
+
"val_loss": 0.08821694987767181,
|
| 263 |
+
"val_metrics": {
|
| 264 |
+
"spearman": 0.20229581542185188,
|
| 265 |
+
"pearson": 0.22442831099033356,
|
| 266 |
+
"mse": 0.08821789920330048,
|
| 267 |
+
"macro_spearman": 0.20634215615444548,
|
| 268 |
+
"macro_assays_eligible": 246,
|
| 269 |
+
"macro_assays_total": 246
|
| 270 |
+
},
|
| 271 |
+
"lr_encoder": 4.3132185965612014e-06,
|
| 272 |
+
"lr_head": 2.1566092982806e-05
|
| 273 |
+
},
|
| 274 |
+
{
|
| 275 |
+
"epoch": 18,
|
| 276 |
+
"train_loss": 0.04388836729720501,
|
| 277 |
+
"val_loss": 0.09027578428121981,
|
| 278 |
+
"val_metrics": {
|
| 279 |
+
"spearman": 0.193795332135738,
|
| 280 |
+
"pearson": 0.2129238247871399,
|
| 281 |
+
"mse": 0.09027887880802155,
|
| 282 |
+
"macro_spearman": 0.20139275176325294,
|
| 283 |
+
"macro_assays_eligible": 246,
|
| 284 |
+
"macro_assays_total": 246
|
| 285 |
+
},
|
| 286 |
+
"lr_encoder": 3.7725618879709492e-06,
|
| 287 |
+
"lr_head": 1.8862809439854746e-05
|
| 288 |
+
}
|
| 289 |
+
],
|
| 290 |
+
"fingerprint": "b50035032c9c5017afd6328b7c1e4ab3f6ff7eeb8a1d126c918c5567e207115e",
|
| 291 |
+
"input_hashes": {
|
| 292 |
+
"csv": "db08ac7409ae5f119a706f8acb7c486154f10f70f59571fa7306178032ec6990",
|
| 293 |
+
"roles_tsv": "6ae90f6fed8e1874479b007d1537531b1a9f9f4db5a89855a9d48947ee0a88bc",
|
| 294 |
+
"protein_emb_h5": "529ae25ecac7c03d0fc33f8f52f6cacec2db5103f27088d25e9adc06133fdef4",
|
| 295 |
+
"vocabulary": "918c73a55adeb603614112d75bb02033e5823fd9c8a70d43f6c0a4a9c78e360b",
|
| 296 |
+
"upstream_checkpoint": "8e7d95ee492df6d843f495dd4708c97ee16a947e75b5cd8f83b23e4f4a0d6d82",
|
| 297 |
+
"dataset_v8.py": "0cafa57d2b468e1c5ac9d0e9285565de05500fc78ebac467cd09aeceb0e1b6c4",
|
| 298 |
+
"training_v8.py": "6f2ac53d3af2002a8eb42f3b4dc046659a261cdf6fe5eef158724c3527610949",
|
| 299 |
+
"bertint_v8.py": "4df5fcf330bbb4d7d766a141179a5fea76a4e75fc9eef0e403cb567d97dd4564",
|
| 300 |
+
"a1111_encoder_adapter.py": "52c790c24e10061b5890260aad39cefdb6c2c615b8b9c167cc23d86393e41d98",
|
| 301 |
+
"feature_token_ids": "9dbdf73149ce8a3a1d4e1a5322f8a3de68e0f2e1a2e6a73733641e02a9b32ccd",
|
| 302 |
+
"feature_branch_depths": "afa8b69797891b529b212da41726c1d1269e06f26396370e2fcc0b77f25a5086",
|
| 303 |
+
"feature_linkage_types": "3440fc0db96dc3ecdfa315e390fe354c398ded75db8b9017569db7bf6c61610f",
|
| 304 |
+
"feature_attention_mask": "43cdb6ccd9c5e5ecc46aed5ed0c29801144526486e89ba3f611537cea13e8282",
|
| 305 |
+
"feature_tree_channels_valid": "0c867a6e6fdf3a0b72d5fdb76023556d998ad286ef14f0f8f661d760b8f18a2c",
|
| 306 |
+
"feature_motif_features": "d88c2d1342d27f572a27ec030579341a59d72bad89d552695d4db419ff3ceae2",
|
| 307 |
+
"feature_index": "986c4282f79ba621afdd4ad8cfe58d29d79d819946e75d0eb2d9c2316d637a3d",
|
| 308 |
+
"_imported_modules": {
|
| 309 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/training_v8.py": "6f2ac53d3af2002a8eb42f3b4dc046659a261cdf6fe5eef158724c3527610949",
|
| 310 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/bertint_v8.py": "4df5fcf330bbb4d7d766a141179a5fea76a4e75fc9eef0e403cb567d97dd4564",
|
| 311 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/dataset_v8.py": "0cafa57d2b468e1c5ac9d0e9285565de05500fc78ebac467cd09aeceb0e1b6c4",
|
| 312 |
+
"/work/ratul1/supantha/glycan-SD-VS/bert_training_v3/v3.1_cluster_training/bert_training_v4/model/__init__.py": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
| 313 |
+
"/work/ratul1/supantha/glycan-SD-VS/bert_training_v3/v3.1_cluster_training/bert_training_v4/model/glycan_bert.py": "b69f14c9976951325e3a0a4e8107a16126e67d410e966650f513f1f538a732bb",
|
| 314 |
+
"/work/ratul1/supantha/glycan-SD-VS/bert_training_v3/v3.1_cluster_training/bert_training_v4/model/multimodal_glycan_bert_v3.py": "83fde1c18cd6547a6ea026017296b5c94d209ac8f0e125057f03d507b3b65190",
|
| 315 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/a5_tokenizer_shim.py": "771759e04c6c8aabdb928c7a2396fc07af3aefb917b857e07c5c2a0dd77ae96e",
|
| 316 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/a1111_encoder_adapter.py": "52c790c24e10061b5890260aad39cefdb6c2c615b8b9c167cc23d86393e41d98"
|
| 317 |
+
},
|
| 318 |
+
"_roster_digests": {
|
| 319 |
+
"train": "fb872366d7c824122b62d484a9a90f41ac7b7998b4213bfbdc03702086090c27",
|
| 320 |
+
"val": "9f258e1549c5fc1d1f21a2204f0dbcc46b0f3af489f8845309bcc0d6a3e78713",
|
| 321 |
+
"test": "9f258e1549c5fc1d1f21a2204f0dbcc46b0f3af489f8845309bcc0d6a3e78713"
|
| 322 |
+
}
|
| 323 |
+
}
|
| 324 |
+
}
|
releases/2026-10-02/provenance/affinose_cells/affinose_mof_20260909_mof_C_doubly_s43/receipt.json
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"cell_id": "mof_C_doubly_s43",
|
| 3 |
+
"fingerprint": "788c8377637edb8cc4ba7bde154a1663f648db547dd0bc721c369dab7d8a8d5a",
|
| 4 |
+
"manifest_sha256": "mof_20260909_moC_doubly",
|
| 5 |
+
"args": {
|
| 6 |
+
"csv_path": "/work/ratul1/supantha/Bertint/v2_artifacts/review_affinose_C_doubly_binding.csv",
|
| 7 |
+
"split_path": "/work/ratul1/supantha/Bertint/v2_artifacts/affinose_v2_splits_direct_edit_guarded.json",
|
| 8 |
+
"protein_emb_path": "/work/ratul1/supantha/Bertint/affinose_v2_esmc_by_seqhash_r2.h5",
|
| 9 |
+
"vocab_path": "/work/ratul1/supantha/glycan-SD-VS/bert_training_v3/v3.1_cluster_training/data/review_sequences_a5_non_iar_later_role_official_array_v4_20260721_r1/review_bpe_vocabulary.json",
|
| 10 |
+
"bertose_checkpoint": "/work/ratul1/supantha/bertose_a5_static_precache_20260723_r2c4_closure31_py310_3c8d5299a4af15bc/writing/review/multimodal/outputs/a5_wa345_pretraining_20260817_r1/production/review_md20x6_md20x6-a1111-wa345-20260817-r1_A1111_wa3_seed42/review_checkpoints/review_md20x6_checkpoint_best.pt",
|
| 11 |
+
"output_dir": "/work/ratul1/supantha/Bertint/checkpoints/affinose_mof_20260909_mof_C_doubly_s43",
|
| 12 |
+
"freeze_layers": 4,
|
| 13 |
+
"shared_dim": 512,
|
| 14 |
+
"num_cross_layers": 2,
|
| 15 |
+
"num_heads": 8,
|
| 16 |
+
"swe_slices": 512,
|
| 17 |
+
"dropout": 0.1,
|
| 18 |
+
"protein_dim": 960,
|
| 19 |
+
"separate_swe": false,
|
| 20 |
+
"lr_encoder": 1e-05,
|
| 21 |
+
"lr_head": 5e-05,
|
| 22 |
+
"weight_decay": 0.01,
|
| 23 |
+
"max_grad_norm": 1.0,
|
| 24 |
+
"batch_size": 32,
|
| 25 |
+
"epochs": 30,
|
| 26 |
+
"patience": 10,
|
| 27 |
+
"max_glycan_length": 256,
|
| 28 |
+
"max_protein_length": 1024,
|
| 29 |
+
"protein_mode": "real",
|
| 30 |
+
"ranking_loss": false,
|
| 31 |
+
"assays_per_batch": 4,
|
| 32 |
+
"rows_per_assay": 8,
|
| 33 |
+
"protein_binding_channel": false,
|
| 34 |
+
"glycan_only": false,
|
| 35 |
+
"protein_attentive_pool": false,
|
| 36 |
+
"motif_additive_dim": 165,
|
| 37 |
+
"glycan_size_channel": false,
|
| 38 |
+
"seed": 43,
|
| 39 |
+
"roles_tsv": "/work/ratul1/supantha/Bertint/v2_artifacts/review_affinose_C_doubly_roles.tsv.gz",
|
| 40 |
+
"train_stratum": "fit_train",
|
| 41 |
+
"val_stratum": "val_doubly_cold",
|
| 42 |
+
"test_stratum": "val_doubly_cold",
|
| 43 |
+
"features_dir": "/work/ratul1/supantha/Bertint/data/review_affinose_glycan_features_20260824_r1",
|
| 44 |
+
"expected_train_rows": 406483,
|
| 45 |
+
"expected_val_rows": 3822,
|
| 46 |
+
"expected_test_rows": 3822,
|
| 47 |
+
"manifest_sha256": "mof_20260909_moC_doubly",
|
| 48 |
+
"cell_id": "mof_C_doubly_s43",
|
| 49 |
+
"input_hashes": "/work/ratul1/supantha/Bertint/manifests/affinose_input_hashes_moC_doubly_20260908.json",
|
| 50 |
+
"warmup_pct": 0.05,
|
| 51 |
+
"target_col": "target_rank",
|
| 52 |
+
"checkpoint_interval": 1,
|
| 53 |
+
"resume": false,
|
| 54 |
+
"pooling_mode": "mean",
|
| 55 |
+
"interaction_mode": "concat",
|
| 56 |
+
"no_cross_attention": false
|
| 57 |
+
},
|
| 58 |
+
"input_hashes": {
|
| 59 |
+
"csv": "e43e150423cb998a77037ad6d82c158a65431b59c46b168febf263ad36267df4",
|
| 60 |
+
"roles_tsv": "e82fb6d73d3ce3ff33e32bd0a8d2e81a0aa4b19b8819bf18339c4aa0382dc5fd",
|
| 61 |
+
"protein_emb_h5": "529ae25ecac7c03d0fc33f8f52f6cacec2db5103f27088d25e9adc06133fdef4",
|
| 62 |
+
"vocabulary": "918c73a55adeb603614112d75bb02033e5823fd9c8a70d43f6c0a4a9c78e360b",
|
| 63 |
+
"upstream_checkpoint": "8e7d95ee492df6d843f495dd4708c97ee16a947e75b5cd8f83b23e4f4a0d6d82",
|
| 64 |
+
"dataset_v8.py": "0cafa57d2b468e1c5ac9d0e9285565de05500fc78ebac467cd09aeceb0e1b6c4",
|
| 65 |
+
"training_v8.py": "6f2ac53d3af2002a8eb42f3b4dc046659a261cdf6fe5eef158724c3527610949",
|
| 66 |
+
"bertint_v8.py": "4df5fcf330bbb4d7d766a141179a5fea76a4e75fc9eef0e403cb567d97dd4564",
|
| 67 |
+
"a1111_encoder_adapter.py": "52c790c24e10061b5890260aad39cefdb6c2c615b8b9c167cc23d86393e41d98",
|
| 68 |
+
"feature_token_ids": "9dbdf73149ce8a3a1d4e1a5322f8a3de68e0f2e1a2e6a73733641e02a9b32ccd",
|
| 69 |
+
"feature_branch_depths": "afa8b69797891b529b212da41726c1d1269e06f26396370e2fcc0b77f25a5086",
|
| 70 |
+
"feature_linkage_types": "3440fc0db96dc3ecdfa315e390fe354c398ded75db8b9017569db7bf6c61610f",
|
| 71 |
+
"feature_attention_mask": "43cdb6ccd9c5e5ecc46aed5ed0c29801144526486e89ba3f611537cea13e8282",
|
| 72 |
+
"feature_tree_channels_valid": "0c867a6e6fdf3a0b72d5fdb76023556d998ad286ef14f0f8f661d760b8f18a2c",
|
| 73 |
+
"feature_motif_features": "d88c2d1342d27f572a27ec030579341a59d72bad89d552695d4db419ff3ceae2",
|
| 74 |
+
"feature_index": "986c4282f79ba621afdd4ad8cfe58d29d79d819946e75d0eb2d9c2316d637a3d",
|
| 75 |
+
"_imported_modules": {
|
| 76 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/training_v8.py": "6f2ac53d3af2002a8eb42f3b4dc046659a261cdf6fe5eef158724c3527610949",
|
| 77 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/bertint_v8.py": "4df5fcf330bbb4d7d766a141179a5fea76a4e75fc9eef0e403cb567d97dd4564",
|
| 78 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/dataset_v8.py": "0cafa57d2b468e1c5ac9d0e9285565de05500fc78ebac467cd09aeceb0e1b6c4",
|
| 79 |
+
"/work/ratul1/supantha/glycan-SD-VS/bert_training_v3/v3.1_cluster_training/bert_training_v4/model/__init__.py": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
| 80 |
+
"/work/ratul1/supantha/glycan-SD-VS/bert_training_v3/v3.1_cluster_training/bert_training_v4/model/glycan_bert.py": "b69f14c9976951325e3a0a4e8107a16126e67d410e966650f513f1f538a732bb",
|
| 81 |
+
"/work/ratul1/supantha/glycan-SD-VS/bert_training_v3/v3.1_cluster_training/bert_training_v4/model/multimodal_glycan_bert_v3.py": "83fde1c18cd6547a6ea026017296b5c94d209ac8f0e125057f03d507b3b65190",
|
| 82 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/a5_tokenizer_shim.py": "771759e04c6c8aabdb928c7a2396fc07af3aefb917b857e07c5c2a0dd77ae96e",
|
| 83 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/a1111_encoder_adapter.py": "52c790c24e10061b5890260aad39cefdb6c2c615b8b9c167cc23d86393e41d98"
|
| 84 |
+
},
|
| 85 |
+
"_roster_digests": {
|
| 86 |
+
"train": "f6ec937bb55813139ed1b26e07953c95d78fd1fe99ccec1f03bb74c09b7960f5",
|
| 87 |
+
"val": "c537ff22ab74b5b6c6ec94e76ef3de2b6ffc1e17086c11657e5f29b0d88da391",
|
| 88 |
+
"test": "c537ff22ab74b5b6c6ec94e76ef3de2b6ffc1e17086c11657e5f29b0d88da391"
|
| 89 |
+
}
|
| 90 |
+
},
|
| 91 |
+
"roster_digests": {
|
| 92 |
+
"train": "f6ec937bb55813139ed1b26e07953c95d78fd1fe99ccec1f03bb74c09b7960f5",
|
| 93 |
+
"val": "c537ff22ab74b5b6c6ec94e76ef3de2b6ffc1e17086c11657e5f29b0d88da391",
|
| 94 |
+
"test": "c537ff22ab74b5b6c6ec94e76ef3de2b6ffc1e17086c11657e5f29b0d88da391"
|
| 95 |
+
},
|
| 96 |
+
"slurm_job_id": "12252897",
|
| 97 |
+
"slurm_array_task_id": "2",
|
| 98 |
+
"slurm_restart_count": null,
|
| 99 |
+
"node": "nova21-amp-3",
|
| 100 |
+
"gpu": "NVIDIA A100-PCIE-40GB"
|
| 101 |
+
}
|
releases/2026-10-02/provenance/affinose_cells/affinose_mof_20260909_mof_C_doubly_s43/results.json
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"task_type": "regression",
|
| 3 |
+
"architecture": "cross-attention=True pooling=mean interaction=concat + live Bertose",
|
| 4 |
+
"best_metric": 0.2278161550103475,
|
| 5 |
+
"best_metric_is": "validation",
|
| 6 |
+
"best_epoch": 1,
|
| 7 |
+
"early_stopped": true,
|
| 8 |
+
"epochs_ran": 12,
|
| 9 |
+
"test_metrics": {
|
| 10 |
+
"spearman": 0.24371231429579024,
|
| 11 |
+
"pearson": 0.24978864192962646,
|
| 12 |
+
"mse": 0.07957296073436737,
|
| 13 |
+
"macro_spearman": 0.2278161550103475,
|
| 14 |
+
"macro_assays_eligible": 218,
|
| 15 |
+
"macro_assays_total": 218
|
| 16 |
+
},
|
| 17 |
+
"test_loss": 0.07959918103491266,
|
| 18 |
+
"history": [
|
| 19 |
+
{
|
| 20 |
+
"epoch": 1,
|
| 21 |
+
"train_loss": 0.08217019368176276,
|
| 22 |
+
"val_loss": 0.080513754611214,
|
| 23 |
+
"val_metrics": {
|
| 24 |
+
"spearman": 0.18197313252266425,
|
| 25 |
+
"pearson": 0.19518351554870605,
|
| 26 |
+
"mse": 0.08036746084690094,
|
| 27 |
+
"macro_spearman": 0.13920416257310053,
|
| 28 |
+
"macro_assays_eligible": 218,
|
| 29 |
+
"macro_assays_total": 218
|
| 30 |
+
},
|
| 31 |
+
"lr_encoder": 7.600456921860401e-06,
|
| 32 |
+
"lr_head": 3.800228460930201e-05
|
| 33 |
+
},
|
| 34 |
+
{
|
| 35 |
+
"epoch": 2,
|
| 36 |
+
"train_loss": 0.07321907142764479,
|
| 37 |
+
"val_loss": 0.07959918103491266,
|
| 38 |
+
"val_metrics": {
|
| 39 |
+
"spearman": 0.24371231429579024,
|
| 40 |
+
"pearson": 0.24978864192962646,
|
| 41 |
+
"mse": 0.07957296073436737,
|
| 42 |
+
"macro_spearman": 0.2278161550103475,
|
| 43 |
+
"macro_assays_eligible": 218,
|
| 44 |
+
"macro_assays_total": 218
|
| 45 |
+
},
|
| 46 |
+
"lr_encoder": 9.992405222215124e-06,
|
| 47 |
+
"lr_head": 4.996202611107562e-05
|
| 48 |
+
},
|
| 49 |
+
{
|
| 50 |
+
"epoch": 3,
|
| 51 |
+
"train_loss": 0.06850780602590001,
|
| 52 |
+
"val_loss": 0.08010787678261598,
|
| 53 |
+
"val_metrics": {
|
| 54 |
+
"spearman": 0.22582728258155255,
|
| 55 |
+
"pearson": 0.22293958067893982,
|
| 56 |
+
"mse": 0.07997935265302658,
|
| 57 |
+
"macro_spearman": 0.18212787907544617,
|
| 58 |
+
"macro_assays_eligible": 218,
|
| 59 |
+
"macro_assays_total": 218
|
| 60 |
+
},
|
| 61 |
+
"lr_encoder": 9.93179964821535e-06,
|
| 62 |
+
"lr_head": 4.9658998241076745e-05
|
| 63 |
+
},
|
| 64 |
+
{
|
| 65 |
+
"epoch": 4,
|
| 66 |
+
"train_loss": 0.06562513827228887,
|
| 67 |
+
"val_loss": 0.08135794155920545,
|
| 68 |
+
"val_metrics": {
|
| 69 |
+
"spearman": 0.20973701944665502,
|
| 70 |
+
"pearson": 0.2167285680770874,
|
| 71 |
+
"mse": 0.08122111111879349,
|
| 72 |
+
"macro_spearman": 0.1680262191228166,
|
| 73 |
+
"macro_assays_eligible": 218,
|
| 74 |
+
"macro_assays_total": 218
|
| 75 |
+
},
|
| 76 |
+
"lr_encoder": 9.811328950051998e-06,
|
| 77 |
+
"lr_head": 4.905664475025999e-05
|
| 78 |
+
},
|
| 79 |
+
{
|
| 80 |
+
"epoch": 5,
|
| 81 |
+
"train_loss": 0.06357526822885308,
|
| 82 |
+
"val_loss": 0.08136990948890646,
|
| 83 |
+
"val_metrics": {
|
| 84 |
+
"spearman": 0.2147511192432372,
|
| 85 |
+
"pearson": 0.20993298292160034,
|
| 86 |
+
"mse": 0.0812588557600975,
|
| 87 |
+
"macro_spearman": 0.17879476431653582,
|
| 88 |
+
"macro_assays_eligible": 218,
|
| 89 |
+
"macro_assays_total": 218
|
| 90 |
+
},
|
| 91 |
+
"lr_encoder": 9.632455478806839e-06,
|
| 92 |
+
"lr_head": 4.816227739403419e-05
|
| 93 |
+
},
|
| 94 |
+
{
|
| 95 |
+
"epoch": 6,
|
| 96 |
+
"train_loss": 0.06198898692786375,
|
| 97 |
+
"val_loss": 0.08343257292484244,
|
| 98 |
+
"val_metrics": {
|
| 99 |
+
"spearman": 0.1942465614715496,
|
| 100 |
+
"pearson": 0.19803641736507416,
|
| 101 |
+
"mse": 0.08329526335000992,
|
| 102 |
+
"macro_spearman": 0.1478931661753686,
|
| 103 |
+
"macro_assays_eligible": 218,
|
| 104 |
+
"macro_assays_total": 218
|
| 105 |
+
},
|
| 106 |
+
"lr_encoder": 9.397350516112365e-06,
|
| 107 |
+
"lr_head": 4.698675258056182e-05
|
| 108 |
+
},
|
| 109 |
+
{
|
| 110 |
+
"epoch": 7,
|
| 111 |
+
"train_loss": 0.06052576813641251,
|
| 112 |
+
"val_loss": 0.08325061357269685,
|
| 113 |
+
"val_metrics": {
|
| 114 |
+
"spearman": 0.19448283762838364,
|
| 115 |
+
"pearson": 0.20482441782951355,
|
| 116 |
+
"mse": 0.08314784616231918,
|
| 117 |
+
"macro_spearman": 0.14600984283451282,
|
| 118 |
+
"macro_assays_eligible": 218,
|
| 119 |
+
"macro_assays_total": 218
|
| 120 |
+
},
|
| 121 |
+
"lr_encoder": 9.108867917734062e-06,
|
| 122 |
+
"lr_head": 4.554433958867031e-05
|
| 123 |
+
},
|
| 124 |
+
{
|
| 125 |
+
"epoch": 8,
|
| 126 |
+
"train_loss": 0.059245914784017056,
|
| 127 |
+
"val_loss": 0.08221773185456792,
|
| 128 |
+
"val_metrics": {
|
| 129 |
+
"spearman": 0.21589636690321976,
|
| 130 |
+
"pearson": 0.22401371598243713,
|
| 131 |
+
"mse": 0.08215607702732086,
|
| 132 |
+
"macro_spearman": 0.19273642448412445,
|
| 133 |
+
"macro_assays_eligible": 218,
|
| 134 |
+
"macro_assays_total": 218
|
| 135 |
+
},
|
| 136 |
+
"lr_encoder": 8.770509471627362e-06,
|
| 137 |
+
"lr_head": 4.385254735813681e-05
|
| 138 |
+
},
|
| 139 |
+
{
|
| 140 |
+
"epoch": 9,
|
| 141 |
+
"train_loss": 0.05797236338407353,
|
| 142 |
+
"val_loss": 0.08278422035897771,
|
| 143 |
+
"val_metrics": {
|
| 144 |
+
"spearman": 0.20207701461652208,
|
| 145 |
+
"pearson": 0.2028491199016571,
|
| 146 |
+
"mse": 0.08269399404525757,
|
| 147 |
+
"macro_spearman": 0.18161633571304941,
|
| 148 |
+
"macro_assays_eligible": 218,
|
| 149 |
+
"macro_assays_total": 218
|
| 150 |
+
},
|
| 151 |
+
"lr_encoder": 8.3863823909755e-06,
|
| 152 |
+
"lr_head": 4.1931911954877495e-05
|
| 153 |
+
},
|
| 154 |
+
{
|
| 155 |
+
"epoch": 10,
|
| 156 |
+
"train_loss": 0.05678273152126263,
|
| 157 |
+
"val_loss": 0.08959366163859765,
|
| 158 |
+
"val_metrics": {
|
| 159 |
+
"spearman": 0.16949282307127173,
|
| 160 |
+
"pearson": 0.17482900619506836,
|
| 161 |
+
"mse": 0.08958856016397476,
|
| 162 |
+
"macro_spearman": 0.15269489273804726,
|
| 163 |
+
"macro_assays_eligible": 218,
|
| 164 |
+
"macro_assays_total": 218
|
| 165 |
+
},
|
| 166 |
+
"lr_encoder": 7.961149458185257e-06,
|
| 167 |
+
"lr_head": 3.9805747290926286e-05
|
| 168 |
+
},
|
| 169 |
+
{
|
| 170 |
+
"epoch": 11,
|
| 171 |
+
"train_loss": 0.055409021762098595,
|
| 172 |
+
"val_loss": 0.08639660604918996,
|
| 173 |
+
"val_metrics": {
|
| 174 |
+
"spearman": 0.17912118331172416,
|
| 175 |
+
"pearson": 0.1813514530658722,
|
| 176 |
+
"mse": 0.08641572296619415,
|
| 177 |
+
"macro_spearman": 0.14887737256820655,
|
| 178 |
+
"macro_assays_eligible": 218,
|
| 179 |
+
"macro_assays_total": 218
|
| 180 |
+
},
|
| 181 |
+
"lr_encoder": 7.499972425024911e-06,
|
| 182 |
+
"lr_head": 3.7499862125124546e-05
|
| 183 |
+
},
|
| 184 |
+
{
|
| 185 |
+
"epoch": 12,
|
| 186 |
+
"train_loss": 0.05418257805815219,
|
| 187 |
+
"val_loss": 0.09123583193868398,
|
| 188 |
+
"val_metrics": {
|
| 189 |
+
"spearman": 0.17283292579872125,
|
| 190 |
+
"pearson": 0.17656531929969788,
|
| 191 |
+
"mse": 0.0911729484796524,
|
| 192 |
+
"macro_spearman": 0.1595232903648669,
|
| 193 |
+
"macro_assays_eligible": 218,
|
| 194 |
+
"macro_assays_total": 218
|
| 195 |
+
},
|
| 196 |
+
"lr_encoder": 7.008449355950063e-06,
|
| 197 |
+
"lr_head": 3.504224677975031e-05
|
| 198 |
+
}
|
| 199 |
+
],
|
| 200 |
+
"fingerprint": "788c8377637edb8cc4ba7bde154a1663f648db547dd0bc721c369dab7d8a8d5a",
|
| 201 |
+
"input_hashes": {
|
| 202 |
+
"csv": "e43e150423cb998a77037ad6d82c158a65431b59c46b168febf263ad36267df4",
|
| 203 |
+
"roles_tsv": "e82fb6d73d3ce3ff33e32bd0a8d2e81a0aa4b19b8819bf18339c4aa0382dc5fd",
|
| 204 |
+
"protein_emb_h5": "529ae25ecac7c03d0fc33f8f52f6cacec2db5103f27088d25e9adc06133fdef4",
|
| 205 |
+
"vocabulary": "918c73a55adeb603614112d75bb02033e5823fd9c8a70d43f6c0a4a9c78e360b",
|
| 206 |
+
"upstream_checkpoint": "8e7d95ee492df6d843f495dd4708c97ee16a947e75b5cd8f83b23e4f4a0d6d82",
|
| 207 |
+
"dataset_v8.py": "0cafa57d2b468e1c5ac9d0e9285565de05500fc78ebac467cd09aeceb0e1b6c4",
|
| 208 |
+
"training_v8.py": "6f2ac53d3af2002a8eb42f3b4dc046659a261cdf6fe5eef158724c3527610949",
|
| 209 |
+
"bertint_v8.py": "4df5fcf330bbb4d7d766a141179a5fea76a4e75fc9eef0e403cb567d97dd4564",
|
| 210 |
+
"a1111_encoder_adapter.py": "52c790c24e10061b5890260aad39cefdb6c2c615b8b9c167cc23d86393e41d98",
|
| 211 |
+
"feature_token_ids": "9dbdf73149ce8a3a1d4e1a5322f8a3de68e0f2e1a2e6a73733641e02a9b32ccd",
|
| 212 |
+
"feature_branch_depths": "afa8b69797891b529b212da41726c1d1269e06f26396370e2fcc0b77f25a5086",
|
| 213 |
+
"feature_linkage_types": "3440fc0db96dc3ecdfa315e390fe354c398ded75db8b9017569db7bf6c61610f",
|
| 214 |
+
"feature_attention_mask": "43cdb6ccd9c5e5ecc46aed5ed0c29801144526486e89ba3f611537cea13e8282",
|
| 215 |
+
"feature_tree_channels_valid": "0c867a6e6fdf3a0b72d5fdb76023556d998ad286ef14f0f8f661d760b8f18a2c",
|
| 216 |
+
"feature_motif_features": "d88c2d1342d27f572a27ec030579341a59d72bad89d552695d4db419ff3ceae2",
|
| 217 |
+
"feature_index": "986c4282f79ba621afdd4ad8cfe58d29d79d819946e75d0eb2d9c2316d637a3d",
|
| 218 |
+
"_imported_modules": {
|
| 219 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/training_v8.py": "6f2ac53d3af2002a8eb42f3b4dc046659a261cdf6fe5eef158724c3527610949",
|
| 220 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/bertint_v8.py": "4df5fcf330bbb4d7d766a141179a5fea76a4e75fc9eef0e403cb567d97dd4564",
|
| 221 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/dataset_v8.py": "0cafa57d2b468e1c5ac9d0e9285565de05500fc78ebac467cd09aeceb0e1b6c4",
|
| 222 |
+
"/work/ratul1/supantha/glycan-SD-VS/bert_training_v3/v3.1_cluster_training/bert_training_v4/model/__init__.py": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
| 223 |
+
"/work/ratul1/supantha/glycan-SD-VS/bert_training_v3/v3.1_cluster_training/bert_training_v4/model/glycan_bert.py": "b69f14c9976951325e3a0a4e8107a16126e67d410e966650f513f1f538a732bb",
|
| 224 |
+
"/work/ratul1/supantha/glycan-SD-VS/bert_training_v3/v3.1_cluster_training/bert_training_v4/model/multimodal_glycan_bert_v3.py": "83fde1c18cd6547a6ea026017296b5c94d209ac8f0e125057f03d507b3b65190",
|
| 225 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/a5_tokenizer_shim.py": "771759e04c6c8aabdb928c7a2396fc07af3aefb917b857e07c5c2a0dd77ae96e",
|
| 226 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/a1111_encoder_adapter.py": "52c790c24e10061b5890260aad39cefdb6c2c615b8b9c167cc23d86393e41d98"
|
| 227 |
+
},
|
| 228 |
+
"_roster_digests": {
|
| 229 |
+
"train": "f6ec937bb55813139ed1b26e07953c95d78fd1fe99ccec1f03bb74c09b7960f5",
|
| 230 |
+
"val": "c537ff22ab74b5b6c6ec94e76ef3de2b6ffc1e17086c11657e5f29b0d88da391",
|
| 231 |
+
"test": "c537ff22ab74b5b6c6ec94e76ef3de2b6ffc1e17086c11657e5f29b0d88da391"
|
| 232 |
+
}
|
| 233 |
+
}
|
| 234 |
+
}
|
releases/2026-10-02/provenance/affinose_cells/affinose_mof_20260909_mof_C_doubly_s44/receipt.json
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"cell_id": "mof_C_doubly_s44",
|
| 3 |
+
"fingerprint": "feb493f3bf5da120bfada3ab639b04a9e0cd89d0f00633e01c99a89664971d49",
|
| 4 |
+
"manifest_sha256": "mof_20260909_moC_doubly",
|
| 5 |
+
"args": {
|
| 6 |
+
"csv_path": "/work/ratul1/supantha/Bertint/v2_artifacts/review_affinose_C_doubly_binding.csv",
|
| 7 |
+
"split_path": "/work/ratul1/supantha/Bertint/v2_artifacts/affinose_v2_splits_direct_edit_guarded.json",
|
| 8 |
+
"protein_emb_path": "/work/ratul1/supantha/Bertint/affinose_v2_esmc_by_seqhash_r2.h5",
|
| 9 |
+
"vocab_path": "/work/ratul1/supantha/glycan-SD-VS/bert_training_v3/v3.1_cluster_training/data/review_sequences_a5_non_iar_later_role_official_array_v4_20260721_r1/review_bpe_vocabulary.json",
|
| 10 |
+
"bertose_checkpoint": "/work/ratul1/supantha/bertose_a5_static_precache_20260723_r2c4_closure31_py310_3c8d5299a4af15bc/writing/review/multimodal/outputs/a5_wa345_pretraining_20260817_r1/production/review_md20x6_md20x6-a1111-wa345-20260817-r1_A1111_wa3_seed42/review_checkpoints/review_md20x6_checkpoint_best.pt",
|
| 11 |
+
"output_dir": "/work/ratul1/supantha/Bertint/checkpoints/affinose_mof_20260909_mof_C_doubly_s44",
|
| 12 |
+
"freeze_layers": 4,
|
| 13 |
+
"shared_dim": 512,
|
| 14 |
+
"num_cross_layers": 2,
|
| 15 |
+
"num_heads": 8,
|
| 16 |
+
"swe_slices": 512,
|
| 17 |
+
"dropout": 0.1,
|
| 18 |
+
"protein_dim": 960,
|
| 19 |
+
"separate_swe": false,
|
| 20 |
+
"lr_encoder": 1e-05,
|
| 21 |
+
"lr_head": 5e-05,
|
| 22 |
+
"weight_decay": 0.01,
|
| 23 |
+
"max_grad_norm": 1.0,
|
| 24 |
+
"batch_size": 32,
|
| 25 |
+
"epochs": 30,
|
| 26 |
+
"patience": 10,
|
| 27 |
+
"max_glycan_length": 256,
|
| 28 |
+
"max_protein_length": 1024,
|
| 29 |
+
"protein_mode": "real",
|
| 30 |
+
"ranking_loss": false,
|
| 31 |
+
"assays_per_batch": 4,
|
| 32 |
+
"rows_per_assay": 8,
|
| 33 |
+
"protein_binding_channel": false,
|
| 34 |
+
"glycan_only": false,
|
| 35 |
+
"protein_attentive_pool": false,
|
| 36 |
+
"motif_additive_dim": 165,
|
| 37 |
+
"glycan_size_channel": false,
|
| 38 |
+
"seed": 44,
|
| 39 |
+
"roles_tsv": "/work/ratul1/supantha/Bertint/v2_artifacts/review_affinose_C_doubly_roles.tsv.gz",
|
| 40 |
+
"train_stratum": "fit_train",
|
| 41 |
+
"val_stratum": "val_doubly_cold",
|
| 42 |
+
"test_stratum": "val_doubly_cold",
|
| 43 |
+
"features_dir": "/work/ratul1/supantha/Bertint/data/review_affinose_glycan_features_20260824_r1",
|
| 44 |
+
"expected_train_rows": 406483,
|
| 45 |
+
"expected_val_rows": 3822,
|
| 46 |
+
"expected_test_rows": 3822,
|
| 47 |
+
"manifest_sha256": "mof_20260909_moC_doubly",
|
| 48 |
+
"cell_id": "mof_C_doubly_s44",
|
| 49 |
+
"input_hashes": "/work/ratul1/supantha/Bertint/manifests/affinose_input_hashes_moC_doubly_20260908.json",
|
| 50 |
+
"warmup_pct": 0.05,
|
| 51 |
+
"target_col": "target_rank",
|
| 52 |
+
"checkpoint_interval": 1,
|
| 53 |
+
"resume": false,
|
| 54 |
+
"pooling_mode": "mean",
|
| 55 |
+
"interaction_mode": "concat",
|
| 56 |
+
"no_cross_attention": false
|
| 57 |
+
},
|
| 58 |
+
"input_hashes": {
|
| 59 |
+
"csv": "e43e150423cb998a77037ad6d82c158a65431b59c46b168febf263ad36267df4",
|
| 60 |
+
"roles_tsv": "e82fb6d73d3ce3ff33e32bd0a8d2e81a0aa4b19b8819bf18339c4aa0382dc5fd",
|
| 61 |
+
"protein_emb_h5": "529ae25ecac7c03d0fc33f8f52f6cacec2db5103f27088d25e9adc06133fdef4",
|
| 62 |
+
"vocabulary": "918c73a55adeb603614112d75bb02033e5823fd9c8a70d43f6c0a4a9c78e360b",
|
| 63 |
+
"upstream_checkpoint": "8e7d95ee492df6d843f495dd4708c97ee16a947e75b5cd8f83b23e4f4a0d6d82",
|
| 64 |
+
"dataset_v8.py": "0cafa57d2b468e1c5ac9d0e9285565de05500fc78ebac467cd09aeceb0e1b6c4",
|
| 65 |
+
"training_v8.py": "6f2ac53d3af2002a8eb42f3b4dc046659a261cdf6fe5eef158724c3527610949",
|
| 66 |
+
"bertint_v8.py": "4df5fcf330bbb4d7d766a141179a5fea76a4e75fc9eef0e403cb567d97dd4564",
|
| 67 |
+
"a1111_encoder_adapter.py": "52c790c24e10061b5890260aad39cefdb6c2c615b8b9c167cc23d86393e41d98",
|
| 68 |
+
"feature_token_ids": "9dbdf73149ce8a3a1d4e1a5322f8a3de68e0f2e1a2e6a73733641e02a9b32ccd",
|
| 69 |
+
"feature_branch_depths": "afa8b69797891b529b212da41726c1d1269e06f26396370e2fcc0b77f25a5086",
|
| 70 |
+
"feature_linkage_types": "3440fc0db96dc3ecdfa315e390fe354c398ded75db8b9017569db7bf6c61610f",
|
| 71 |
+
"feature_attention_mask": "43cdb6ccd9c5e5ecc46aed5ed0c29801144526486e89ba3f611537cea13e8282",
|
| 72 |
+
"feature_tree_channels_valid": "0c867a6e6fdf3a0b72d5fdb76023556d998ad286ef14f0f8f661d760b8f18a2c",
|
| 73 |
+
"feature_motif_features": "d88c2d1342d27f572a27ec030579341a59d72bad89d552695d4db419ff3ceae2",
|
| 74 |
+
"feature_index": "986c4282f79ba621afdd4ad8cfe58d29d79d819946e75d0eb2d9c2316d637a3d",
|
| 75 |
+
"_imported_modules": {
|
| 76 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/training_v8.py": "6f2ac53d3af2002a8eb42f3b4dc046659a261cdf6fe5eef158724c3527610949",
|
| 77 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/bertint_v8.py": "4df5fcf330bbb4d7d766a141179a5fea76a4e75fc9eef0e403cb567d97dd4564",
|
| 78 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/dataset_v8.py": "0cafa57d2b468e1c5ac9d0e9285565de05500fc78ebac467cd09aeceb0e1b6c4",
|
| 79 |
+
"/work/ratul1/supantha/glycan-SD-VS/bert_training_v3/v3.1_cluster_training/bert_training_v4/model/__init__.py": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
| 80 |
+
"/work/ratul1/supantha/glycan-SD-VS/bert_training_v3/v3.1_cluster_training/bert_training_v4/model/glycan_bert.py": "b69f14c9976951325e3a0a4e8107a16126e67d410e966650f513f1f538a732bb",
|
| 81 |
+
"/work/ratul1/supantha/glycan-SD-VS/bert_training_v3/v3.1_cluster_training/bert_training_v4/model/multimodal_glycan_bert_v3.py": "83fde1c18cd6547a6ea026017296b5c94d209ac8f0e125057f03d507b3b65190",
|
| 82 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/a5_tokenizer_shim.py": "771759e04c6c8aabdb928c7a2396fc07af3aefb917b857e07c5c2a0dd77ae96e",
|
| 83 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/a1111_encoder_adapter.py": "52c790c24e10061b5890260aad39cefdb6c2c615b8b9c167cc23d86393e41d98"
|
| 84 |
+
},
|
| 85 |
+
"_roster_digests": {
|
| 86 |
+
"train": "f6ec937bb55813139ed1b26e07953c95d78fd1fe99ccec1f03bb74c09b7960f5",
|
| 87 |
+
"val": "c537ff22ab74b5b6c6ec94e76ef3de2b6ffc1e17086c11657e5f29b0d88da391",
|
| 88 |
+
"test": "c537ff22ab74b5b6c6ec94e76ef3de2b6ffc1e17086c11657e5f29b0d88da391"
|
| 89 |
+
}
|
| 90 |
+
},
|
| 91 |
+
"roster_digests": {
|
| 92 |
+
"train": "f6ec937bb55813139ed1b26e07953c95d78fd1fe99ccec1f03bb74c09b7960f5",
|
| 93 |
+
"val": "c537ff22ab74b5b6c6ec94e76ef3de2b6ffc1e17086c11657e5f29b0d88da391",
|
| 94 |
+
"test": "c537ff22ab74b5b6c6ec94e76ef3de2b6ffc1e17086c11657e5f29b0d88da391"
|
| 95 |
+
},
|
| 96 |
+
"slurm_job_id": "12252894",
|
| 97 |
+
"slurm_array_task_id": "3",
|
| 98 |
+
"slurm_restart_count": null,
|
| 99 |
+
"node": "nova21-amp-3",
|
| 100 |
+
"gpu": "NVIDIA A100-PCIE-40GB"
|
| 101 |
+
}
|
releases/2026-10-02/provenance/affinose_cells/affinose_mof_20260909_mof_C_doubly_s44/results.json
ADDED
|
@@ -0,0 +1,264 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"task_type": "regression",
|
| 3 |
+
"architecture": "cross-attention=True pooling=mean interaction=concat + live Bertose",
|
| 4 |
+
"best_metric": 0.21062218506431446,
|
| 5 |
+
"best_metric_is": "validation",
|
| 6 |
+
"best_epoch": 3,
|
| 7 |
+
"early_stopped": true,
|
| 8 |
+
"epochs_ran": 14,
|
| 9 |
+
"test_metrics": {
|
| 10 |
+
"spearman": 0.23531327082857056,
|
| 11 |
+
"pearson": 0.23060324788093567,
|
| 12 |
+
"mse": 0.08090551197528839,
|
| 13 |
+
"macro_spearman": 0.21062218506431446,
|
| 14 |
+
"macro_assays_eligible": 218,
|
| 15 |
+
"macro_assays_total": 218
|
| 16 |
+
},
|
| 17 |
+
"test_loss": 0.08097927542403341,
|
| 18 |
+
"history": [
|
| 19 |
+
{
|
| 20 |
+
"epoch": 1,
|
| 21 |
+
"train_loss": 0.0823811714034573,
|
| 22 |
+
"val_loss": 0.08316954768573244,
|
| 23 |
+
"val_metrics": {
|
| 24 |
+
"spearman": 0.19923863389392296,
|
| 25 |
+
"pearson": 0.20312944054603577,
|
| 26 |
+
"mse": 0.08306817710399628,
|
| 27 |
+
"macro_spearman": 0.14979364049573743,
|
| 28 |
+
"macro_assays_eligible": 218,
|
| 29 |
+
"macro_assays_total": 218
|
| 30 |
+
},
|
| 31 |
+
"lr_encoder": 7.600456921860401e-06,
|
| 32 |
+
"lr_head": 3.800228460930201e-05
|
| 33 |
+
},
|
| 34 |
+
{
|
| 35 |
+
"epoch": 2,
|
| 36 |
+
"train_loss": 0.07352196992131037,
|
| 37 |
+
"val_loss": 0.08194014184797803,
|
| 38 |
+
"val_metrics": {
|
| 39 |
+
"spearman": 0.23002782642760716,
|
| 40 |
+
"pearson": 0.23304009437561035,
|
| 41 |
+
"mse": 0.08179230988025665,
|
| 42 |
+
"macro_spearman": 0.19135672277353788,
|
| 43 |
+
"macro_assays_eligible": 218,
|
| 44 |
+
"macro_assays_total": 218
|
| 45 |
+
},
|
| 46 |
+
"lr_encoder": 9.992405222215124e-06,
|
| 47 |
+
"lr_head": 4.996202611107562e-05
|
| 48 |
+
},
|
| 49 |
+
{
|
| 50 |
+
"epoch": 3,
|
| 51 |
+
"train_loss": 0.06890469362752077,
|
| 52 |
+
"val_loss": 0.08131420062854885,
|
| 53 |
+
"val_metrics": {
|
| 54 |
+
"spearman": 0.2344376640032703,
|
| 55 |
+
"pearson": 0.23378324508666992,
|
| 56 |
+
"mse": 0.08125484734773636,
|
| 57 |
+
"macro_spearman": 0.19768865575292732,
|
| 58 |
+
"macro_assays_eligible": 218,
|
| 59 |
+
"macro_assays_total": 218
|
| 60 |
+
},
|
| 61 |
+
"lr_encoder": 9.93179964821535e-06,
|
| 62 |
+
"lr_head": 4.9658998241076745e-05
|
| 63 |
+
},
|
| 64 |
+
{
|
| 65 |
+
"epoch": 4,
|
| 66 |
+
"train_loss": 0.06594055111535461,
|
| 67 |
+
"val_loss": 0.08097927542403341,
|
| 68 |
+
"val_metrics": {
|
| 69 |
+
"spearman": 0.23531327082857056,
|
| 70 |
+
"pearson": 0.23060324788093567,
|
| 71 |
+
"mse": 0.08090551197528839,
|
| 72 |
+
"macro_spearman": 0.21062218506431446,
|
| 73 |
+
"macro_assays_eligible": 218,
|
| 74 |
+
"macro_assays_total": 218
|
| 75 |
+
},
|
| 76 |
+
"lr_encoder": 9.811328950051998e-06,
|
| 77 |
+
"lr_head": 4.905664475025999e-05
|
| 78 |
+
},
|
| 79 |
+
{
|
| 80 |
+
"epoch": 5,
|
| 81 |
+
"train_loss": 0.06386762665527351,
|
| 82 |
+
"val_loss": 0.08328413100292285,
|
| 83 |
+
"val_metrics": {
|
| 84 |
+
"spearman": 0.21344337077969475,
|
| 85 |
+
"pearson": 0.21080267429351807,
|
| 86 |
+
"mse": 0.08322741836309433,
|
| 87 |
+
"macro_spearman": 0.1906273111501897,
|
| 88 |
+
"macro_assays_eligible": 218,
|
| 89 |
+
"macro_assays_total": 218
|
| 90 |
+
},
|
| 91 |
+
"lr_encoder": 9.632455478806839e-06,
|
| 92 |
+
"lr_head": 4.816227739403419e-05
|
| 93 |
+
},
|
| 94 |
+
{
|
| 95 |
+
"epoch": 6,
|
| 96 |
+
"train_loss": 0.062316317219027036,
|
| 97 |
+
"val_loss": 0.08544459746529659,
|
| 98 |
+
"val_metrics": {
|
| 99 |
+
"spearman": 0.21378404878560708,
|
| 100 |
+
"pearson": 0.21021392941474915,
|
| 101 |
+
"mse": 0.08542674779891968,
|
| 102 |
+
"macro_spearman": 0.1841262975097498,
|
| 103 |
+
"macro_assays_eligible": 218,
|
| 104 |
+
"macro_assays_total": 218
|
| 105 |
+
},
|
| 106 |
+
"lr_encoder": 9.397350516112365e-06,
|
| 107 |
+
"lr_head": 4.698675258056182e-05
|
| 108 |
+
},
|
| 109 |
+
{
|
| 110 |
+
"epoch": 7,
|
| 111 |
+
"train_loss": 0.06089970052883347,
|
| 112 |
+
"val_loss": 0.08304940707360704,
|
| 113 |
+
"val_metrics": {
|
| 114 |
+
"spearman": 0.2142924318507679,
|
| 115 |
+
"pearson": 0.20584237575531006,
|
| 116 |
+
"mse": 0.08305490761995316,
|
| 117 |
+
"macro_spearman": 0.20147768236632793,
|
| 118 |
+
"macro_assays_eligible": 218,
|
| 119 |
+
"macro_assays_total": 218
|
| 120 |
+
},
|
| 121 |
+
"lr_encoder": 9.108867917734062e-06,
|
| 122 |
+
"lr_head": 4.554433958867031e-05
|
| 123 |
+
},
|
| 124 |
+
{
|
| 125 |
+
"epoch": 8,
|
| 126 |
+
"train_loss": 0.05954349656158016,
|
| 127 |
+
"val_loss": 0.0856317674741149,
|
| 128 |
+
"val_metrics": {
|
| 129 |
+
"spearman": 0.20605229263914857,
|
| 130 |
+
"pearson": 0.20229709148406982,
|
| 131 |
+
"mse": 0.0855521708726883,
|
| 132 |
+
"macro_spearman": 0.15801575910924295,
|
| 133 |
+
"macro_assays_eligible": 218,
|
| 134 |
+
"macro_assays_total": 218
|
| 135 |
+
},
|
| 136 |
+
"lr_encoder": 8.770509471627362e-06,
|
| 137 |
+
"lr_head": 4.385254735813681e-05
|
| 138 |
+
},
|
| 139 |
+
{
|
| 140 |
+
"epoch": 9,
|
| 141 |
+
"train_loss": 0.05828532947726342,
|
| 142 |
+
"val_loss": 0.09087766061226527,
|
| 143 |
+
"val_metrics": {
|
| 144 |
+
"spearman": 0.17898921602789444,
|
| 145 |
+
"pearson": 0.17833471298217773,
|
| 146 |
+
"mse": 0.0906767025589943,
|
| 147 |
+
"macro_spearman": 0.14823934961313195,
|
| 148 |
+
"macro_assays_eligible": 218,
|
| 149 |
+
"macro_assays_total": 218
|
| 150 |
+
},
|
| 151 |
+
"lr_encoder": 8.3863823909755e-06,
|
| 152 |
+
"lr_head": 4.1931911954877495e-05
|
| 153 |
+
},
|
| 154 |
+
{
|
| 155 |
+
"epoch": 10,
|
| 156 |
+
"train_loss": 0.0570728823543768,
|
| 157 |
+
"val_loss": 0.08991672083114584,
|
| 158 |
+
"val_metrics": {
|
| 159 |
+
"spearman": 0.18307338675239052,
|
| 160 |
+
"pearson": 0.18055406212806702,
|
| 161 |
+
"mse": 0.08965384215116501,
|
| 162 |
+
"macro_spearman": 0.1408365513344764,
|
| 163 |
+
"macro_assays_eligible": 218,
|
| 164 |
+
"macro_assays_total": 218
|
| 165 |
+
},
|
| 166 |
+
"lr_encoder": 7.961149458185257e-06,
|
| 167 |
+
"lr_head": 3.9805747290926286e-05
|
| 168 |
+
},
|
| 169 |
+
{
|
| 170 |
+
"epoch": 11,
|
| 171 |
+
"train_loss": 0.0557709243132436,
|
| 172 |
+
"val_loss": 0.09227961363891761,
|
| 173 |
+
"val_metrics": {
|
| 174 |
+
"spearman": 0.16599375190389218,
|
| 175 |
+
"pearson": 0.1591390073299408,
|
| 176 |
+
"mse": 0.09232576191425323,
|
| 177 |
+
"macro_spearman": 0.1580101290572493,
|
| 178 |
+
"macro_assays_eligible": 218,
|
| 179 |
+
"macro_assays_total": 218
|
| 180 |
+
},
|
| 181 |
+
"lr_encoder": 7.499972425024911e-06,
|
| 182 |
+
"lr_head": 3.7499862125124546e-05
|
| 183 |
+
},
|
| 184 |
+
{
|
| 185 |
+
"epoch": 12,
|
| 186 |
+
"train_loss": 0.05454512665595613,
|
| 187 |
+
"val_loss": 0.09188498885681232,
|
| 188 |
+
"val_metrics": {
|
| 189 |
+
"spearman": 0.17033978684464768,
|
| 190 |
+
"pearson": 0.1680733561515808,
|
| 191 |
+
"mse": 0.09179382771253586,
|
| 192 |
+
"macro_spearman": 0.14625690534575364,
|
| 193 |
+
"macro_assays_eligible": 218,
|
| 194 |
+
"macro_assays_total": 218
|
| 195 |
+
},
|
| 196 |
+
"lr_encoder": 7.008449355950063e-06,
|
| 197 |
+
"lr_head": 3.504224677975031e-05
|
| 198 |
+
},
|
| 199 |
+
{
|
| 200 |
+
"epoch": 13,
|
| 201 |
+
"train_loss": 0.0532016348550355,
|
| 202 |
+
"val_loss": 0.0945957535567383,
|
| 203 |
+
"val_metrics": {
|
| 204 |
+
"spearman": 0.15632833853849673,
|
| 205 |
+
"pearson": 0.15771374106407166,
|
| 206 |
+
"mse": 0.09457787126302719,
|
| 207 |
+
"macro_spearman": 0.14414718978591468,
|
| 208 |
+
"macro_assays_eligible": 218,
|
| 209 |
+
"macro_assays_total": 218
|
| 210 |
+
},
|
| 211 |
+
"lr_encoder": 6.492546675184488e-06,
|
| 212 |
+
"lr_head": 3.246273337592243e-05
|
| 213 |
+
},
|
| 214 |
+
{
|
| 215 |
+
"epoch": 14,
|
| 216 |
+
"train_loss": 0.05184374296895343,
|
| 217 |
+
"val_loss": 0.09580712212870518,
|
| 218 |
+
"val_metrics": {
|
| 219 |
+
"spearman": 0.1508608569678843,
|
| 220 |
+
"pearson": 0.14708638191223145,
|
| 221 |
+
"mse": 0.09580221027135849,
|
| 222 |
+
"macro_spearman": 0.13152231787081284,
|
| 223 |
+
"macro_assays_eligible": 218,
|
| 224 |
+
"macro_assays_total": 218
|
| 225 |
+
},
|
| 226 |
+
"lr_encoder": 5.958526742412386e-06,
|
| 227 |
+
"lr_head": 2.9792633712061927e-05
|
| 228 |
+
}
|
| 229 |
+
],
|
| 230 |
+
"fingerprint": "feb493f3bf5da120bfada3ab639b04a9e0cd89d0f00633e01c99a89664971d49",
|
| 231 |
+
"input_hashes": {
|
| 232 |
+
"csv": "e43e150423cb998a77037ad6d82c158a65431b59c46b168febf263ad36267df4",
|
| 233 |
+
"roles_tsv": "e82fb6d73d3ce3ff33e32bd0a8d2e81a0aa4b19b8819bf18339c4aa0382dc5fd",
|
| 234 |
+
"protein_emb_h5": "529ae25ecac7c03d0fc33f8f52f6cacec2db5103f27088d25e9adc06133fdef4",
|
| 235 |
+
"vocabulary": "918c73a55adeb603614112d75bb02033e5823fd9c8a70d43f6c0a4a9c78e360b",
|
| 236 |
+
"upstream_checkpoint": "8e7d95ee492df6d843f495dd4708c97ee16a947e75b5cd8f83b23e4f4a0d6d82",
|
| 237 |
+
"dataset_v8.py": "0cafa57d2b468e1c5ac9d0e9285565de05500fc78ebac467cd09aeceb0e1b6c4",
|
| 238 |
+
"training_v8.py": "6f2ac53d3af2002a8eb42f3b4dc046659a261cdf6fe5eef158724c3527610949",
|
| 239 |
+
"bertint_v8.py": "4df5fcf330bbb4d7d766a141179a5fea76a4e75fc9eef0e403cb567d97dd4564",
|
| 240 |
+
"a1111_encoder_adapter.py": "52c790c24e10061b5890260aad39cefdb6c2c615b8b9c167cc23d86393e41d98",
|
| 241 |
+
"feature_token_ids": "9dbdf73149ce8a3a1d4e1a5322f8a3de68e0f2e1a2e6a73733641e02a9b32ccd",
|
| 242 |
+
"feature_branch_depths": "afa8b69797891b529b212da41726c1d1269e06f26396370e2fcc0b77f25a5086",
|
| 243 |
+
"feature_linkage_types": "3440fc0db96dc3ecdfa315e390fe354c398ded75db8b9017569db7bf6c61610f",
|
| 244 |
+
"feature_attention_mask": "43cdb6ccd9c5e5ecc46aed5ed0c29801144526486e89ba3f611537cea13e8282",
|
| 245 |
+
"feature_tree_channels_valid": "0c867a6e6fdf3a0b72d5fdb76023556d998ad286ef14f0f8f661d760b8f18a2c",
|
| 246 |
+
"feature_motif_features": "d88c2d1342d27f572a27ec030579341a59d72bad89d552695d4db419ff3ceae2",
|
| 247 |
+
"feature_index": "986c4282f79ba621afdd4ad8cfe58d29d79d819946e75d0eb2d9c2316d637a3d",
|
| 248 |
+
"_imported_modules": {
|
| 249 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/training_v8.py": "6f2ac53d3af2002a8eb42f3b4dc046659a261cdf6fe5eef158724c3527610949",
|
| 250 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/bertint_v8.py": "4df5fcf330bbb4d7d766a141179a5fea76a4e75fc9eef0e403cb567d97dd4564",
|
| 251 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/dataset_v8.py": "0cafa57d2b468e1c5ac9d0e9285565de05500fc78ebac467cd09aeceb0e1b6c4",
|
| 252 |
+
"/work/ratul1/supantha/glycan-SD-VS/bert_training_v3/v3.1_cluster_training/bert_training_v4/model/__init__.py": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
| 253 |
+
"/work/ratul1/supantha/glycan-SD-VS/bert_training_v3/v3.1_cluster_training/bert_training_v4/model/glycan_bert.py": "b69f14c9976951325e3a0a4e8107a16126e67d410e966650f513f1f538a732bb",
|
| 254 |
+
"/work/ratul1/supantha/glycan-SD-VS/bert_training_v3/v3.1_cluster_training/bert_training_v4/model/multimodal_glycan_bert_v3.py": "83fde1c18cd6547a6ea026017296b5c94d209ac8f0e125057f03d507b3b65190",
|
| 255 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/a5_tokenizer_shim.py": "771759e04c6c8aabdb928c7a2396fc07af3aefb917b857e07c5c2a0dd77ae96e",
|
| 256 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/a1111_encoder_adapter.py": "52c790c24e10061b5890260aad39cefdb6c2c615b8b9c167cc23d86393e41d98"
|
| 257 |
+
},
|
| 258 |
+
"_roster_digests": {
|
| 259 |
+
"train": "f6ec937bb55813139ed1b26e07953c95d78fd1fe99ccec1f03bb74c09b7960f5",
|
| 260 |
+
"val": "c537ff22ab74b5b6c6ec94e76ef3de2b6ffc1e17086c11657e5f29b0d88da391",
|
| 261 |
+
"test": "c537ff22ab74b5b6c6ec94e76ef3de2b6ffc1e17086c11657e5f29b0d88da391"
|
| 262 |
+
}
|
| 263 |
+
}
|
| 264 |
+
}
|
releases/2026-10-02/provenance/affinose_cells/affinose_sa_20260908_mo_B_protein_s42/receipt.json
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"cell_id": "mo_B_protein_s42",
|
| 3 |
+
"fingerprint": "b01428c0a518f3d479eae47e01fb9f753829678e902ef19b2318139159d22b05",
|
| 4 |
+
"manifest_sha256": "mo_20260908_moB_protein",
|
| 5 |
+
"args": {
|
| 6 |
+
"csv_path": "/work/ratul1/supantha/Bertint/v2_artifacts/review_affinose_B_protein_binding.csv",
|
| 7 |
+
"split_path": "/work/ratul1/supantha/Bertint/v2_artifacts/affinose_v2_splits_direct_edit_guarded.json",
|
| 8 |
+
"protein_emb_path": "/work/ratul1/supantha/Bertint/affinose_v2_esmc_by_seqhash_r2.h5",
|
| 9 |
+
"vocab_path": "/work/ratul1/supantha/glycan-SD-VS/bert_training_v3/v3.1_cluster_training/data/review_sequences_a5_non_iar_later_role_official_array_v4_20260721_r1/review_bpe_vocabulary.json",
|
| 10 |
+
"bertose_checkpoint": "/work/ratul1/supantha/bertose_a5_static_precache_20260723_r2c4_closure31_py310_3c8d5299a4af15bc/writing/review/multimodal/outputs/a5_wa345_pretraining_20260817_r1/production/review_md20x6_md20x6-a1111-wa345-20260817-r1_A1111_wa3_seed42/review_checkpoints/review_md20x6_checkpoint_best.pt",
|
| 11 |
+
"output_dir": "/work/ratul1/supantha/Bertint/checkpoints/affinose_sa_20260908_mo_B_protein_s42",
|
| 12 |
+
"freeze_layers": 4,
|
| 13 |
+
"shared_dim": 512,
|
| 14 |
+
"num_cross_layers": 2,
|
| 15 |
+
"num_heads": 8,
|
| 16 |
+
"swe_slices": 512,
|
| 17 |
+
"dropout": 0.1,
|
| 18 |
+
"protein_dim": 960,
|
| 19 |
+
"separate_swe": false,
|
| 20 |
+
"lr_encoder": 1e-05,
|
| 21 |
+
"lr_head": 5e-05,
|
| 22 |
+
"weight_decay": 0.01,
|
| 23 |
+
"max_grad_norm": 1.0,
|
| 24 |
+
"batch_size": 32,
|
| 25 |
+
"epochs": 30,
|
| 26 |
+
"patience": 10,
|
| 27 |
+
"max_glycan_length": 256,
|
| 28 |
+
"max_protein_length": 1024,
|
| 29 |
+
"protein_mode": "real",
|
| 30 |
+
"ranking_loss": false,
|
| 31 |
+
"assays_per_batch": 4,
|
| 32 |
+
"rows_per_assay": 8,
|
| 33 |
+
"protein_binding_channel": false,
|
| 34 |
+
"glycan_only": false,
|
| 35 |
+
"protein_attentive_pool": false,
|
| 36 |
+
"motif_additive_dim": 165,
|
| 37 |
+
"glycan_size_channel": false,
|
| 38 |
+
"seed": 42,
|
| 39 |
+
"roles_tsv": "/work/ratul1/supantha/Bertint/v2_artifacts/review_affinose_B_protein_roles.tsv.gz",
|
| 40 |
+
"train_stratum": "fit_train",
|
| 41 |
+
"val_stratum": "val_protein_cold",
|
| 42 |
+
"test_stratum": "val_protein_cold",
|
| 43 |
+
"features_dir": "/work/ratul1/supantha/Bertint/data/review_affinose_glycan_features_20260824_r1",
|
| 44 |
+
"expected_train_rows": 480431,
|
| 45 |
+
"expected_val_rows": 39477,
|
| 46 |
+
"expected_test_rows": 39477,
|
| 47 |
+
"manifest_sha256": "mo_20260908_moB_protein",
|
| 48 |
+
"cell_id": "mo_B_protein_s42",
|
| 49 |
+
"input_hashes": "/work/ratul1/supantha/Bertint/manifests/affinose_input_hashes_moB_protein_20260908.json",
|
| 50 |
+
"warmup_pct": 0.05,
|
| 51 |
+
"target_col": "target_rank",
|
| 52 |
+
"checkpoint_interval": 1,
|
| 53 |
+
"resume": false,
|
| 54 |
+
"pooling_mode": "mean",
|
| 55 |
+
"interaction_mode": "concat",
|
| 56 |
+
"no_cross_attention": false
|
| 57 |
+
},
|
| 58 |
+
"input_hashes": {
|
| 59 |
+
"csv": "db08ac7409ae5f119a706f8acb7c486154f10f70f59571fa7306178032ec6990",
|
| 60 |
+
"roles_tsv": "6ae90f6fed8e1874479b007d1537531b1a9f9f4db5a89855a9d48947ee0a88bc",
|
| 61 |
+
"protein_emb_h5": "529ae25ecac7c03d0fc33f8f52f6cacec2db5103f27088d25e9adc06133fdef4",
|
| 62 |
+
"vocabulary": "918c73a55adeb603614112d75bb02033e5823fd9c8a70d43f6c0a4a9c78e360b",
|
| 63 |
+
"upstream_checkpoint": "8e7d95ee492df6d843f495dd4708c97ee16a947e75b5cd8f83b23e4f4a0d6d82",
|
| 64 |
+
"dataset_v8.py": "0cafa57d2b468e1c5ac9d0e9285565de05500fc78ebac467cd09aeceb0e1b6c4",
|
| 65 |
+
"training_v8.py": "b7cb8a39e167f2cc9e35476dcdcad56320b02c1898d13db3236a41bbb2ed4852",
|
| 66 |
+
"bertint_v8.py": "4df5fcf330bbb4d7d766a141179a5fea76a4e75fc9eef0e403cb567d97dd4564",
|
| 67 |
+
"a1111_encoder_adapter.py": "52c790c24e10061b5890260aad39cefdb6c2c615b8b9c167cc23d86393e41d98",
|
| 68 |
+
"feature_token_ids": "9dbdf73149ce8a3a1d4e1a5322f8a3de68e0f2e1a2e6a73733641e02a9b32ccd",
|
| 69 |
+
"feature_branch_depths": "afa8b69797891b529b212da41726c1d1269e06f26396370e2fcc0b77f25a5086",
|
| 70 |
+
"feature_linkage_types": "3440fc0db96dc3ecdfa315e390fe354c398ded75db8b9017569db7bf6c61610f",
|
| 71 |
+
"feature_attention_mask": "43cdb6ccd9c5e5ecc46aed5ed0c29801144526486e89ba3f611537cea13e8282",
|
| 72 |
+
"feature_tree_channels_valid": "0c867a6e6fdf3a0b72d5fdb76023556d998ad286ef14f0f8f661d760b8f18a2c",
|
| 73 |
+
"feature_motif_features": "d88c2d1342d27f572a27ec030579341a59d72bad89d552695d4db419ff3ceae2",
|
| 74 |
+
"feature_index": "986c4282f79ba621afdd4ad8cfe58d29d79d819946e75d0eb2d9c2316d637a3d",
|
| 75 |
+
"_imported_modules": {
|
| 76 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/training_v8.py": "b7cb8a39e167f2cc9e35476dcdcad56320b02c1898d13db3236a41bbb2ed4852",
|
| 77 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/bertint_v8.py": "4df5fcf330bbb4d7d766a141179a5fea76a4e75fc9eef0e403cb567d97dd4564",
|
| 78 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/dataset_v8.py": "0cafa57d2b468e1c5ac9d0e9285565de05500fc78ebac467cd09aeceb0e1b6c4",
|
| 79 |
+
"/work/ratul1/supantha/glycan-SD-VS/bert_training_v3/v3.1_cluster_training/bert_training_v4/model/__init__.py": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
| 80 |
+
"/work/ratul1/supantha/glycan-SD-VS/bert_training_v3/v3.1_cluster_training/bert_training_v4/model/glycan_bert.py": "b69f14c9976951325e3a0a4e8107a16126e67d410e966650f513f1f538a732bb",
|
| 81 |
+
"/work/ratul1/supantha/glycan-SD-VS/bert_training_v3/v3.1_cluster_training/bert_training_v4/model/multimodal_glycan_bert_v3.py": "83fde1c18cd6547a6ea026017296b5c94d209ac8f0e125057f03d507b3b65190",
|
| 82 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/a5_tokenizer_shim.py": "771759e04c6c8aabdb928c7a2396fc07af3aefb917b857e07c5c2a0dd77ae96e",
|
| 83 |
+
"/work/ratul1/supantha/Bertint/model_motif_20260908/a1111_encoder_adapter.py": "52c790c24e10061b5890260aad39cefdb6c2c615b8b9c167cc23d86393e41d98"
|
| 84 |
+
},
|
| 85 |
+
"_roster_digests": {
|
| 86 |
+
"train": "fb872366d7c824122b62d484a9a90f41ac7b7998b4213bfbdc03702086090c27",
|
| 87 |
+
"val": "9f258e1549c5fc1d1f21a2204f0dbcc46b0f3af489f8845309bcc0d6a3e78713",
|
| 88 |
+
"test": "9f258e1549c5fc1d1f21a2204f0dbcc46b0f3af489f8845309bcc0d6a3e78713"
|
| 89 |
+
}
|
| 90 |
+
},
|
| 91 |
+
"roster_digests": {
|
| 92 |
+
"train": "fb872366d7c824122b62d484a9a90f41ac7b7998b4213bfbdc03702086090c27",
|
| 93 |
+
"val": "9f258e1549c5fc1d1f21a2204f0dbcc46b0f3af489f8845309bcc0d6a3e78713",
|
| 94 |
+
"test": "9f258e1549c5fc1d1f21a2204f0dbcc46b0f3af489f8845309bcc0d6a3e78713"
|
| 95 |
+
},
|
| 96 |
+
"slurm_job_id": "12246887",
|
| 97 |
+
"slurm_array_task_id": "1",
|
| 98 |
+
"slurm_restart_count": null,
|
| 99 |
+
"node": "nova22-amp-4",
|
| 100 |
+
"gpu": "NVIDIA A100-PCIE-40GB"
|
| 101 |
+
}
|