wuxing0105 commited on
Commit
3a8e4d3
·
verified ·
1 Parent(s): b2cb4a0

Add files using upload-large-folder tool

Browse files
Files changed (50) hide show
  1. config/callbacks/default.yaml +5 -0
  2. config/callbacks/model_summary.yaml +5 -0
  3. config/data/apo.yaml +3 -0
  4. config/data/pdb_sp_afesm.yaml +66 -0
  5. config/data/pdb_sp_afesme.yaml +67 -0
  6. config/experiment/test.yaml +30 -0
  7. config/experiment/train.yaml +55 -0
  8. config/experiment/train_plddt.yaml +85 -0
  9. config/extras/default.yaml +5 -0
  10. config/model/architecture/default.yaml +101 -0
  11. config/model/architecture/foldingdit_1.6B.yaml +99 -0
  12. config/model/architecture/plddt_module.yaml +24 -0
  13. config/model/default.yaml +39 -0
  14. config/model/processor/default.yaml +2 -0
  15. config/model/processor/protein_processor.yaml +2 -0
  16. config/model/simplefold.yaml +39 -0
  17. config/trainer/fsdp.yaml +18 -0
  18. models/__pycache__/__init__.cpython-310.pyc +0 -0
  19. models/__pycache__/__init__.cpython-311.pyc +0 -0
  20. models/esm/__init__.py +13 -0
  21. models/esm/__pycache__/__init__.cpython-311.pyc +0 -0
  22. models/esm/__pycache__/esm2.cpython-310.pyc +0 -0
  23. models/esm/__pycache__/msa_transformer.cpython-310.pyc +0 -0
  24. models/esm/__pycache__/version.cpython-310.pyc +0 -0
  25. models/esm/__pycache__/version.cpython-311.pyc +0 -0
  26. models/esm/esm2.py +152 -0
  27. models/esm/esmfold/__init__.py +0 -0
  28. models/esm/esmfold/v1/esmfold.py +364 -0
  29. models/esm/msa_transformer.py +238 -0
  30. models/esm/pretrained.py +545 -0
  31. models/esm/version.py +6 -0
  32. models/simplefold/mlx/__pycache__/esm_network.cpython-310.pyc +0 -0
  33. models/simplefold/mlx/__pycache__/esm_rotary_embedding.cpython-310.pyc +0 -0
  34. models/simplefold/mlx/__pycache__/sampler.cpython-310.pyc +0 -0
  35. models/simplefold/torch/__pycache__/__init__.cpython-310.pyc +0 -0
  36. models/simplefold/torch/__pycache__/architecture.cpython-310.pyc +0 -0
  37. models/simplefold/torch/__pycache__/architecture.cpython-311.pyc +0 -0
  38. models/simplefold/torch/__pycache__/blocks.cpython-310.pyc +0 -0
  39. models/simplefold/torch/__pycache__/blocks.cpython-311.pyc +0 -0
  40. models/simplefold/torch/__pycache__/confidence_module.cpython-310.pyc +0 -0
  41. models/simplefold/torch/__pycache__/confidence_module.cpython-311.pyc +0 -0
  42. models/simplefold/torch/__pycache__/layers.cpython-310.pyc +0 -0
  43. models/simplefold/torch/__pycache__/layers.cpython-311.pyc +0 -0
  44. models/simplefold/torch/__pycache__/pos_embed.cpython-310.pyc +0 -0
  45. models/simplefold/torch/__pycache__/sampler.cpython-310.pyc +0 -0
  46. models/simplefold/torch/__pycache__/sampler.cpython-311.pyc +0 -0
  47. models/simplefold/torch/blocks.py +146 -0
  48. models/simplefold/torch/confidence_module.py +85 -0
  49. models/simplefold/torch/sampler.py +108 -0
  50. weight/ccd.pkl +3 -0
config/callbacks/default.yaml ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ defaults:
2
+ - model_checkpoint
3
+ - model_summary
4
+ - _self_
5
+
config/callbacks/model_summary.yaml ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ # https://lightning.ai/docs/pytorch/stable/api/lightning.pytorch.callbacks.RichModelSummary.html
2
+
3
+ model_summary:
4
+ _target_: lightning.pytorch.callbacks.RichModelSummary
5
+ max_depth: -1 # the maximum depth of layer nesting that the summary will include
config/data/apo.yaml ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ _target_: onescience.datapipes.simplefold.test_datamodule.SimpleFoldInferenceDataModule
2
+ target_dir: data/apo/
3
+ num_workers: 1
config/data/pdb_sp_afesm.yaml ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ _target_: onescience.datapipes.simplefold.train_datamodule.SimpleFoldTrainingDataModule
2
+
3
+ datasets:
4
+ - _target_: onescience.datapipes.simplefold.train_datamodule.DatasetConfig
5
+ data_name: rcsb_protein
6
+ tokenized_dir: data/rcsb_protein_tokenized
7
+ target_dir: data/rcsb_processed_targets
8
+ manifest_path: data/rcsb_protein_tokenized/manifest.json
9
+ cropper:
10
+ _target_: onescience.datapipes.boltz_data_pipeline.crop.boltz.BoltzCropper
11
+ min_neighborhood: 0
12
+ max_neighborhood: 40
13
+ filters:
14
+ - _target_: onescience.datapipes.boltz_data_pipeline.filter.dynamic.resolution.ResolutionFilter
15
+ resolution: 5.0
16
+ - _target_: onescience.datapipes.boltz_data_pipeline.filter.dynamic.date.DateFilter
17
+ date: "2020-05-01"
18
+ ref: released
19
+
20
+ - _target_: onescience.datapipes.simplefold.train_datamodule.DatasetConfig
21
+ data_name: swissprot
22
+ tokenized_dir: data/swissprot_tokenized
23
+ target_dir: data/swissprot_pdb_v4_boltz
24
+ manifest_path: data/swissprot_tokenized/manifest.json
25
+ record_list: data/swissprot_filtered.txt
26
+ cropper:
27
+ _target_: onescience.datapipes.boltz_data_pipeline.crop.boltz.BoltzCropper
28
+ min_neighborhood: 0
29
+ max_neighborhood: 40
30
+
31
+ - _target_: onescience.datapipes.simplefold.train_datamodule.DatasetConfig
32
+ data_name: processed_afesm
33
+ tokenized_dir: data/processed_afesm
34
+ target_dir: data/processed_afesm
35
+ manifest_path: data/processed_afesm/manifest.json
36
+ cropper:
37
+ _target_: onescience.datapipes.boltz_data_pipeline.crop.boltz.BoltzCropper
38
+ min_neighborhood: 0
39
+ max_neighborhood: 40
40
+
41
+ filters:
42
+ - _target_: onescience.datapipes.boltz_data_pipeline.filter.dynamic.size.SizeFilter
43
+ min_chains: 1
44
+ max_chains: 300
45
+
46
+ tokenizer:
47
+ _target_: onescience.datapipes.boltz_data_pipeline.tokenize.boltz_protein.BoltzTokenizer
48
+
49
+ featurizer:
50
+ _target_: onescience.datapipes.boltz_data_pipeline.feature.featurizer.BoltzFeaturizer
51
+
52
+ symmetries: data/symmetry.pkl
53
+ max_tokens: 256
54
+ max_atoms: 2304
55
+ pad_to_max_tokens: False
56
+ pad_to_max_atoms: False
57
+ batch_size: 256
58
+ num_workers: 16
59
+ pin_memory: True
60
+ return_train_symmetries: False
61
+ min_dist: 2.0
62
+ max_dist: 22.0
63
+ num_bins: 64
64
+ atoms_per_window_queries: 32
65
+ rotation_augment_ref_pos: False
66
+ rotation_augment_coords: True
config/data/pdb_sp_afesme.yaml ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ _target_: onescience.datapipes.simplefold.train_datamodule.SimpleFoldTrainingDataModule
2
+
3
+ datasets:
4
+ - _target_: onescience.datapipes.simplefold.train_datamodule.DatasetConfig
5
+ data_name: rcsb_protein
6
+ tokenized_dir: data/rcsb_protein_tokenized
7
+ target_dir: data/rcsb_processed_targets
8
+ manifest_path: data/rcsb_protein_tokenized/manifest.json
9
+ cropper:
10
+ _target_: onescience.datapipes.boltz_data_pipeline.crop.boltz.BoltzCropper
11
+ min_neighborhood: 0
12
+ max_neighborhood: 40
13
+ filters:
14
+ - _target_: onescience.datapipes.boltz_data_pipeline.filter.dynamic.resolution.ResolutionFilter
15
+ resolution: 5.0
16
+ - _target_: onescience.datapipes.boltz_data_pipeline.filter.dynamic.date.DateFilter
17
+ date: "2020-05-01"
18
+ ref: released
19
+
20
+ - _target_: onescience.datapipes.simplefold.train_datamodule.DatasetConfig
21
+ data_name: swissprot
22
+ tokenized_dir: data/swissprot_tokenized
23
+ target_dir: data/swissprot_pdb_v4_boltz
24
+ manifest_path: data/swissprot_tokenized/manifest.json
25
+ record_list: data/swissprot_filtered.txt
26
+ cropper:
27
+ _target_: onescience.datapipes.boltz_data_pipeline.crop.boltz.BoltzCropper
28
+ min_neighborhood: 0
29
+ max_neighborhood: 40
30
+
31
+ - _target_: onescience.datapipes.simplefold.train_datamodule.DatasetConfig
32
+ data_name: processed_afesm_cluster
33
+ tokenized_dir: data/tokenized_afesm_cluster
34
+ target_dir: data/processed_afesm_cluster
35
+ manifest_path: data/processed_afesm_cluster/manifest.json
36
+ cluster: data/filtered_afesm_cluster.json
37
+ cropper:
38
+ _target_: onescience.datapipes.boltz_data_pipeline.crop.boltz.BoltzCropper
39
+ min_neighborhood: 0
40
+ max_neighborhood: 40
41
+
42
+ filters:
43
+ - _target_: onescience.datapipes.boltz_data_pipeline.filter.dynamic.size.SizeFilter
44
+ min_chains: 1
45
+ max_chains: 300
46
+
47
+ tokenizer:
48
+ _target_: onescience.datapipes.boltz_data_pipeline.tokenize.boltz_protein.BoltzTokenizer
49
+
50
+ featurizer:
51
+ _target_: onescience.datapipes.boltz_data_pipeline.feature.featurizer.BoltzFeaturizer
52
+
53
+ symmetries: data/symmetry.pkl
54
+ max_tokens: 256
55
+ max_atoms: 2304
56
+ pad_to_max_tokens: False
57
+ pad_to_max_atoms: False
58
+ batch_size: 256
59
+ num_workers: 16
60
+ pin_memory: True
61
+ return_train_symmetries: False
62
+ min_dist: 2.0
63
+ max_dist: 22.0
64
+ num_bins: 64
65
+ atoms_per_window_queries: 32
66
+ rotation_augment_ref_pos: False
67
+ rotation_augment_coords: True
config/experiment/test.yaml ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # @package _global_
2
+ defaults:
3
+ - override /data: cameo22
4
+ - override /model: simplefold
5
+ - override /model/architecture: foldingdit_100M
6
+ - override /model/sampler: euler_maruyama
7
+ - override /model/processor: protein_processor
8
+ - override /callbacks: default
9
+ - override /trainer: default
10
+
11
+ load_ckpt_path: artifacts/simplefold_100M.ckpt
12
+ seed: 12345
13
+
14
+ data:
15
+ num_repeats: 1
16
+ filters:
17
+ - _target_: onescience.datapipes.boltz_data_pipeline.filter.dynamic.max_residues.MaxResiduesFilter
18
+ min_residues: 1
19
+ max_residues: 1000 # filter out T1044 in CASP14
20
+
21
+ model:
22
+ sampler:
23
+ num_timesteps: 500
24
+ t_start: 1e-4
25
+ tau: 0.01
26
+ log_timesteps: True
27
+ w_cutoff: 0.99
28
+
29
+ processor:
30
+ inference_multiplicity: 1
config/experiment/train.yaml ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # @package _global_
2
+
3
+ # All parameters below will be merged with parameters from default configurations set above
4
+ # this allows you to overwrite only specified parameters
5
+
6
+ # Options for training:
7
+ # - /data: [pdb, pdb_sp, pdb_sp_afesm, pdb_sp_afesme]
8
+ # - /model/architecture:
9
+ # [foldingdit_100M, foldingdit_360M, foldingdit_700M,
10
+ # foldingdit_1.1B, foldingdit_1.6B, foldingdit_3B]
11
+ # - /trainer: [default, fsdp]
12
+
13
+ defaults:
14
+ - override /data: pdb
15
+ - override /model: simplefold
16
+ - override /model/architecture: foldingdit_100M
17
+ - override /model/sampler: euler_maruyama
18
+ - override /model/processor: protein_processor
19
+ - override /callbacks: default
20
+ - override /trainer: default
21
+ - override /logger: tensorboard
22
+
23
+ # load_ckpt_path: [PATH_TO_YOUR_CKPT] # uncomment to load a checkpoint
24
+ seed: 12345
25
+
26
+ trainer:
27
+ max_steps: 300000
28
+ val_check_interval: 10000 # this controls BOTH checkpoint steps and validation
29
+ accumulate_grad_batches: 1 # gradient accumulation
30
+
31
+ data:
32
+ batch_size: 1 # should be the same as the number of GPUs
33
+ num_workers: 16
34
+
35
+ model:
36
+ _target_: models.simplefold.simplefold.SimpleFold
37
+ ema_decay: 0.999
38
+ clip_grad_norm_val: 2.0
39
+ esm_model: "esm2_3B"
40
+ lddt_weight_schedule: False # set to True in finetuning phase
41
+
42
+ scheduler:
43
+ _target_: onescience.utils.simplefold.lr_scheduler.LinearWarmup
44
+ _partial_: true
45
+ min_lr: 1e-6
46
+ max_lr: ${model.optimizer.lr}
47
+ warmup_steps: 5000
48
+
49
+ architecture:
50
+ esm_model: ${model.esm_model}
51
+
52
+ processor:
53
+ scale: 16.0
54
+ ref_scale: 5.0
55
+ multiplicity: 16 # number of copies per GPU
config/experiment/train_plddt.yaml ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # @package _global_
2
+
3
+ # All parameters below will be merged with parameters from default configurations set above
4
+ # this allows you to overwrite only specified parameters
5
+
6
+ # Options for training:
7
+ # - /data: [pdb, pdb_sp, pdb_sp_afesm, pdb_sp_afesme]
8
+ # - /model/architecture:
9
+ # [foldingdit_100M, foldingdit_360M, foldingdit_700M,
10
+ # foldingdit_1.1B, foldingdit_1.6B, foldingdit_3B]
11
+ # - /trainer: [default, fsdp]
12
+
13
+ defaults:
14
+ - override /data: pdb
15
+ - override /model: simplefold
16
+ - override /model/architecture: foldingdit_100M
17
+ - override /model/sampler: euler_maruyama
18
+ - override /model/processor: protein_processor
19
+ - override /callbacks: default
20
+ - override /trainer: default
21
+ - override /logger: tensorboard
22
+
23
+ # load_ckpt_path: [PATH_TO_YOUR_CKPT] # uncomment to load a checkpoint
24
+ seed: 12345
25
+
26
+ trainer:
27
+ max_steps: 10000
28
+ val_check_interval: 1000 # this controls BOTH checkpoint steps and validation
29
+ accumulate_grad_batches: 1 # gradient accumulation
30
+
31
+ data:
32
+ batch_size: 8 # should be the same as the number of GPUs
33
+ num_workers: 16
34
+
35
+ model:
36
+ _target_: models.simplefold.simplefold.SimpleFold
37
+ ema_decay: 0.999
38
+ clip_grad_norm_val: 2.0
39
+ esm_model: "esm2_3B"
40
+ plddt_training: True
41
+
42
+ plddt_module:
43
+ _target_: models.simplefold.torch.confidence_module.ConfidenceModule
44
+ hidden_size: ${model.architecture.hidden_size}
45
+ num_plddt_bins: 50
46
+ transformer_blocks:
47
+ _target_: models.simplefold.torch.blocks.HomogenTrunk
48
+ depth: 4
49
+ block:
50
+ _target_: models.simplefold.torch.blocks.TransformerBlock
51
+ _partial_: true
52
+ hidden_size: ${model.architecture.hidden_size}
53
+ mlp_ratio: 4.0
54
+ use_swiglu: True # SwiGLU FFN
55
+ self_attention_layer:
56
+ _target_: models.simplefold.torch.layers.EfficientSelfAttentionLayer
57
+ _partial_: True
58
+ hidden_size: ${model.architecture.hidden_size}
59
+ num_heads: ${model.architecture.num_heads}
60
+ qk_norm: True
61
+ pos_embedder:
62
+ _target_: models.simplefold.torch.pos_embed.AxialRotaryPositionEncoding
63
+ in_dim: 4
64
+ embed_dim: ${model.architecture.hidden_size}
65
+ num_heads: ${model.architecture.num_heads}
66
+ base: 100.0
67
+
68
+ scheduler:
69
+ _target_: onescience.utils.simplefold.lr_scheduler.LinearWarmup
70
+ _partial_: true
71
+ min_lr: 1e-6
72
+ max_lr: ${model.optimizer.lr}
73
+ warmup_steps: 5000
74
+
75
+ architecture:
76
+ esm_model: ${model.esm_model}
77
+
78
+ sampler:
79
+ num_timesteps: 150
80
+ tau: 0.3
81
+
82
+ processor:
83
+ scale: 16.0
84
+ ref_scale: 5.0
85
+ multiplicity: 16 # number of copies per GPU
config/extras/default.yaml ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ # disable python warnings if they annoy you
2
+ ignore_warnings: False
3
+
4
+ # pretty print config tree at the start of the run using Rich library
5
+ print_config: True
config/model/architecture/default.yaml ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ _target_: models.simplefold.torch.architecture.FoldingDiT
2
+
3
+ hidden_size: 768
4
+ num_heads: 12
5
+ atom_num_heads: 4
6
+ output_channels: 3
7
+ use_atom_mask: False
8
+ use_length_condition: True
9
+ esm_dropout_prob: 0.0
10
+ esm_model: esm2_3B
11
+
12
+ time_embedder:
13
+ _target_: models.simplefold.torch.layers.TimestepEmbedder
14
+ hidden_size: 768
15
+
16
+ aminoacid_pos_embedder:
17
+ _target_: models.simplefold.torch.pos_embed.AbsolutePositionEncoding
18
+ in_dim: 1
19
+ embed_dim: 768
20
+ include_input: True
21
+
22
+ pos_embedder:
23
+ _target_: models.simplefold.torch.pos_embed.FourierPositionEncoding
24
+ in_dim: 3
25
+ include_input: True
26
+ min_freq_log2: 0
27
+ max_freq_log2: 12
28
+ num_freqs: 128
29
+ log_sampling: True
30
+
31
+ trunk:
32
+ _target_: models.simplefold.torch.blocks.HomogenTrunk
33
+ depth: 8
34
+ block:
35
+ _target_: models.simplefold.torch.blocks.DiTBlock
36
+ _partial_: True
37
+ hidden_size: 768
38
+ mlp_ratio: 4.0
39
+ use_swiglu: True
40
+ self_attention_layer:
41
+ _target_: models.simplefold.torch.layers.EfficientSelfAttentionLayer
42
+ _partial_: True
43
+ hidden_size: 768
44
+ num_heads: 12
45
+ qk_norm: True
46
+ pos_embedder:
47
+ _target_: models.simplefold.torch.pos_embed.AxialRotaryPositionEncoding
48
+ in_dim: 4
49
+ embed_dim: 768
50
+ num_heads: 12
51
+ base: 100.0
52
+
53
+ atom_hidden_size_enc: 256
54
+ atom_n_queries_enc: 32
55
+ atom_n_keys_enc: 128
56
+ atom_encoder_transformer:
57
+ _target_: models.simplefold.torch.blocks.HomogenTrunk
58
+ depth: 1
59
+ block:
60
+ _target_: models.simplefold.torch.blocks.DiTBlock
61
+ _partial_: True
62
+ hidden_size: 256
63
+ mlp_ratio: 4.0
64
+ use_swiglu: True
65
+ self_attention_layer:
66
+ _target_: models.simplefold.torch.layers.EfficientSelfAttentionLayer
67
+ _partial_: True
68
+ hidden_size: 256
69
+ num_heads: 4
70
+ qk_norm: True
71
+ pos_embedder:
72
+ _target_: models.simplefold.torch.pos_embed.AxialRotaryPositionEncoding
73
+ in_dim: 4
74
+ embed_dim: 256
75
+ num_heads: 4
76
+ base: 100.0
77
+
78
+ atom_hidden_size_dec: 256
79
+ atom_n_queries_dec: 32
80
+ atom_n_keys_dec: 128
81
+ atom_decoder_transformer:
82
+ _target_: models.simplefold.torch.blocks.HomogenTrunk
83
+ depth: 1
84
+ block:
85
+ _target_: models.simplefold.torch.blocks.DiTBlock
86
+ _partial_: True
87
+ hidden_size: 256
88
+ mlp_ratio: 4.0
89
+ use_swiglu: True
90
+ self_attention_layer:
91
+ _target_: models.simplefold.torch.layers.EfficientSelfAttentionLayer
92
+ _partial_: True
93
+ hidden_size: 256
94
+ num_heads: 4
95
+ qk_norm: True
96
+ pos_embedder:
97
+ _target_: models.simplefold.torch.pos_embed.AxialRotaryPositionEncoding
98
+ in_dim: 4
99
+ embed_dim: 256
100
+ num_heads: 4
101
+ base: 100.0
config/model/architecture/foldingdit_1.6B.yaml ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ _target_: models.simplefold.torch.architecture.FoldingDiT
2
+
3
+ hidden_size: 1536
4
+ num_heads: 24
5
+ atom_num_heads: 8
6
+ output_channels: 3
7
+ use_atom_mask: False
8
+ use_length_condition: True
9
+ esm_dropout_prob: 0.0
10
+ esm_model: esm2_3B
11
+
12
+ time_embedder:
13
+ _target_: models.simplefold.torch.layers.TimestepEmbedder
14
+ hidden_size: 1536
15
+ aminoacid_pos_embedder:
16
+ _target_: models.simplefold.torch.pos_embed.AbsolutePositionEncoding
17
+ in_dim: 1
18
+ embed_dim: 1536
19
+ include_input: True
20
+ pos_embedder:
21
+ _target_: models.simplefold.torch.pos_embed.FourierPositionEncoding
22
+ in_dim: 3
23
+ include_input: True
24
+ min_freq_log2: 0
25
+ max_freq_log2: 12
26
+ num_freqs: 128
27
+ log_sampling: True
28
+
29
+ trunk:
30
+ _target_: models.simplefold.torch.blocks.HomogenTrunk
31
+ depth: 36
32
+ block:
33
+ _target_: models.simplefold.torch.blocks.DiTBlock
34
+ _partial_: True # because in the for loop we create a new module
35
+ hidden_size: 1536
36
+ mlp_ratio: 4.0
37
+ use_swiglu: True # SwiGLU FFN
38
+ self_attention_layer:
39
+ _target_: models.simplefold.torch.layers.EfficientSelfAttentionLayer
40
+ _partial_: True
41
+ hidden_size: 1536
42
+ num_heads: 24
43
+ qk_norm: True
44
+ pos_embedder:
45
+ _target_: models.simplefold.torch.pos_embed.AxialRotaryPositionEncoding
46
+ in_dim: 4
47
+ embed_dim: 1536
48
+ num_heads: 24
49
+ base: 100.0
50
+
51
+ atom_hidden_size_enc: 512
52
+ atom_n_queries_enc: 32
53
+ atom_n_keys_enc: 128
54
+ atom_encoder_transformer:
55
+ _target_: models.simplefold.torch.blocks.HomogenTrunk
56
+ depth: 3
57
+ block:
58
+ _target_: models.simplefold.torch.blocks.DiTBlock
59
+ _partial_: True # because in the for loop we create a new module
60
+ hidden_size: 512
61
+ mlp_ratio: 4.0
62
+ use_swiglu: True # SwiGLU FFN
63
+ self_attention_layer:
64
+ _target_: models.simplefold.torch.layers.EfficientSelfAttentionLayer
65
+ _partial_: True
66
+ hidden_size: 512
67
+ num_heads: 8
68
+ qk_norm: True
69
+ pos_embedder:
70
+ _target_: models.simplefold.torch.pos_embed.AxialRotaryPositionEncoding
71
+ in_dim: 4
72
+ embed_dim: 512
73
+ num_heads: 8
74
+ base: 100.0
75
+
76
+ atom_hidden_size_dec: 512
77
+ atom_n_queries_dec: 32
78
+ atom_n_keys_dec: 128
79
+ atom_decoder_transformer:
80
+ _target_: models.simplefold.torch.blocks.HomogenTrunk
81
+ depth: 3
82
+ block:
83
+ _target_: models.simplefold.torch.blocks.DiTBlock
84
+ _partial_: True # because in the for loop we create a new module
85
+ hidden_size: 512
86
+ mlp_ratio: 4.0
87
+ use_swiglu: True # SwiGLU FFN
88
+ self_attention_layer:
89
+ _target_: models.simplefold.torch.layers.EfficientSelfAttentionLayer
90
+ _partial_: True
91
+ hidden_size: 512
92
+ num_heads: 8
93
+ qk_norm: True
94
+ pos_embedder:
95
+ _target_: models.simplefold.torch.pos_embed.AxialRotaryPositionEncoding
96
+ in_dim: 4
97
+ embed_dim: 512
98
+ num_heads: 8
99
+ base: 100.0
config/model/architecture/plddt_module.yaml ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ _target_: models.simplefold.torch.confidence_module.ConfidenceModule
2
+ hidden_size: 1536
3
+ num_plddt_bins: 50
4
+ transformer_blocks:
5
+ _target_: models.simplefold.torch.blocks.HomogenTrunk
6
+ depth: 4
7
+ block:
8
+ _target_: models.simplefold.torch.blocks.TransformerBlock
9
+ _partial_: true
10
+ hidden_size: 1536
11
+ mlp_ratio: 4.0
12
+ use_swiglu: True # SwiGLU FFN
13
+ self_attention_layer:
14
+ _target_: models.simplefold.torch.layers.EfficientSelfAttentionLayer
15
+ _partial_: True
16
+ hidden_size: 1536
17
+ num_heads: 24
18
+ qk_norm: True
19
+ pos_embedder:
20
+ _target_: models.simplefold.torch.pos_embed.AxialRotaryPositionEncoding
21
+ in_dim: 4
22
+ embed_dim: 1536
23
+ num_heads: 24
24
+ base: 100.0
config/model/default.yaml ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ _target_: models.simplefold.simplefold.SimpleFold
2
+ ema_decay: 0.999
3
+ clip_grad_norm_val: 2.0
4
+ use_rigid_align: True
5
+ smooth_lddt_loss_weight: 1.0
6
+ lddt_cutoff: 15.0
7
+ esm_model: "esm2_3B"
8
+ lddt_weight_schedule: False
9
+ sample_dir: ${paths.sample_dir}
10
+
11
+ architecture:
12
+ esm_model: ${model.esm_model}
13
+
14
+ path:
15
+ _target_: models.simplefold.flow.LinearPath
16
+
17
+ loss:
18
+ _target_: torch.nn.MSELoss
19
+ reduction: 'none'
20
+ reduce: False
21
+
22
+ optimizer:
23
+ _target_: torch.optim.AdamW
24
+ _partial_: true
25
+ lr: 1e-4
26
+ weight_decay: 0.0
27
+ max_steps: ???
28
+
29
+ scheduler:
30
+ _target_: onescience.utils.simplefold.lr_scheduler.LinearWarmup
31
+ _partial_: true
32
+ min_lr: 1e-6
33
+ max_lr: ${model.optimizer.lr}
34
+ warmup_steps: 10
35
+
36
+ processor:
37
+ scale: 16.0
38
+ ref_scale: 5.0
39
+ multiplicity: 16
config/model/processor/default.yaml ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ _target_: onescience.datapipes.simplefold.processor.protein_processor.ProteinDataProcessor
2
+ _partial_: True
config/model/processor/protein_processor.yaml ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ _target_: onescience.datapipes.simplefold.processor.protein_processor.ProteinDataProcessor
2
+ _partial_: True
config/model/simplefold.yaml ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ _target_: models.simplefold.simplefold.SimpleFold
2
+ ema_decay: 0.999
3
+ clip_grad_norm_val: 2.0
4
+ use_rigid_align: True
5
+ smooth_lddt_loss_weight: 1.0
6
+ lddt_cutoff: 15.0
7
+ esm_model: "esm2_3B"
8
+ lddt_weight_schedule: False
9
+ sample_dir: ${paths.sample_dir}
10
+
11
+ architecture:
12
+ esm_model: ${model.esm_model}
13
+
14
+ path:
15
+ _target_: models.simplefold.flow.LinearPath
16
+
17
+ loss:
18
+ _target_: torch.nn.MSELoss
19
+ reduction: 'none'
20
+ reduce: False
21
+
22
+ optimizer:
23
+ _target_: torch.optim.AdamW
24
+ _partial_: true
25
+ lr: 1e-4
26
+ weight_decay: 0.0
27
+ max_steps: ???
28
+
29
+ scheduler:
30
+ _target_: onescience.utils.simplefold.lr_scheduler.LinearWarmup
31
+ _partial_: true
32
+ min_lr: 1e-6
33
+ max_lr: ${model.optimizer.lr}
34
+ warmup_steps: 10
35
+
36
+ processor:
37
+ scale: 16.0
38
+ ref_scale: 5.0
39
+ multiplicity: 16
config/trainer/fsdp.yaml ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ _target_: lightning.pytorch.trainer.Trainer
2
+
3
+ default_root_dir: ${paths.output_dir}
4
+
5
+ # set True to to ensure deterministic results
6
+ # makes training slower but gives more reproducibility than just setting seeds
7
+ deterministic: False
8
+
9
+ accelerator: gpu
10
+ devices: auto
11
+ num_nodes: 1
12
+ min_epochs: 1 # prevents early stopping
13
+ max_steps: 100000
14
+ precision: bf16-mixed
15
+ val_check_interval: 5000
16
+ check_val_every_n_epoch: null
17
+ num_sanity_val_steps: 0
18
+ limit_val_batches: 0.0
models/__pycache__/__init__.cpython-310.pyc ADDED
Binary file (188 Bytes). View file
 
models/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (206 Bytes). View file
 
models/esm/__init__.py ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Facebook, Inc. and its affiliates.
2
+ #
3
+ # This source code is licensed under the MIT license found in the
4
+ # LICENSE file in the root directory of this source tree.
5
+
6
+ from onescience.datapipes import esm as data # noqa
7
+ from onescience.datapipes.esm import Alphabet, BatchConverter, FastaBatchedDataset # noqa
8
+
9
+ from .version import version as __version__ # noqa
10
+ from .esm1 import ProteinBertModel # noqa
11
+ from .esm2 import ESM2 # noqa
12
+ from .msa_transformer import MSATransformer #noqa
13
+ from . import pretrained # noqa
models/esm/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (679 Bytes). View file
 
models/esm/__pycache__/esm2.cpython-310.pyc ADDED
Binary file (3.46 kB). View file
 
models/esm/__pycache__/msa_transformer.cpython-310.pyc ADDED
Binary file (5.5 kB). View file
 
models/esm/__pycache__/version.cpython-310.pyc ADDED
Binary file (139 Bytes). View file
 
models/esm/__pycache__/version.cpython-311.pyc ADDED
Binary file (191 Bytes). View file
 
models/esm/esm2.py ADDED
@@ -0,0 +1,152 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ #
3
+ # This source code is licensed under the MIT license found in the
4
+ # LICENSE file in the root directory of this source tree.
5
+
6
+ from typing import Union
7
+ import torch
8
+ import torch.nn as nn
9
+
10
+ from onescience.datapipes.esm import Alphabet
11
+ from onescience.modules.esm import (
12
+ ContactPredictionHead,
13
+ ESM1bLayerNorm,
14
+ RobertaLMHead,
15
+ TransformerLayer,
16
+ )
17
+
18
+
19
+ class ESM2(nn.Module):
20
+ def __init__(
21
+ self,
22
+ num_layers: int = 33,
23
+ embed_dim: int = 1280,
24
+ attention_heads: int = 20,
25
+ alphabet: Union[Alphabet, str] = "ESM-1b",
26
+ token_dropout: bool = True,
27
+ ):
28
+ super().__init__()
29
+ self.num_layers = num_layers
30
+ self.embed_dim = embed_dim
31
+ self.attention_heads = attention_heads
32
+ if not isinstance(alphabet, Alphabet):
33
+ alphabet = Alphabet.from_architecture(alphabet)
34
+ self.alphabet = alphabet
35
+ self.alphabet_size = len(alphabet)
36
+ self.padding_idx = alphabet.padding_idx
37
+ self.mask_idx = alphabet.mask_idx
38
+ self.cls_idx = alphabet.cls_idx
39
+ self.eos_idx = alphabet.eos_idx
40
+ self.prepend_bos = alphabet.prepend_bos
41
+ self.append_eos = alphabet.append_eos
42
+ self.token_dropout = token_dropout
43
+
44
+ self._init_submodules()
45
+
46
+ def _init_submodules(self):
47
+ self.embed_scale = 1
48
+ self.embed_tokens = nn.Embedding(
49
+ self.alphabet_size,
50
+ self.embed_dim,
51
+ padding_idx=self.padding_idx,
52
+ )
53
+
54
+ self.layers = nn.ModuleList(
55
+ [
56
+ TransformerLayer(
57
+ self.embed_dim,
58
+ 4 * self.embed_dim,
59
+ self.attention_heads,
60
+ add_bias_kv=False,
61
+ use_esm1b_layer_norm=True,
62
+ use_rotary_embeddings=True,
63
+ )
64
+ for _ in range(self.num_layers)
65
+ ]
66
+ )
67
+
68
+ self.contact_head = ContactPredictionHead(
69
+ self.num_layers * self.attention_heads,
70
+ self.prepend_bos,
71
+ self.append_eos,
72
+ eos_idx=self.eos_idx,
73
+ )
74
+ self.emb_layer_norm_after = ESM1bLayerNorm(self.embed_dim)
75
+
76
+ self.lm_head = RobertaLMHead(
77
+ embed_dim=self.embed_dim,
78
+ output_dim=self.alphabet_size,
79
+ weight=self.embed_tokens.weight,
80
+ )
81
+
82
+ def forward(self, tokens, repr_layers=[], need_head_weights=False, return_contacts=False):
83
+ if return_contacts:
84
+ need_head_weights = True
85
+
86
+ assert tokens.ndim == 2
87
+ padding_mask = tokens.eq(self.padding_idx) # B, T
88
+
89
+ x = self.embed_scale * self.embed_tokens(tokens)
90
+
91
+ if self.token_dropout:
92
+ x.masked_fill_((tokens == self.mask_idx).unsqueeze(-1), 0.0)
93
+ # x: B x T x C
94
+ mask_ratio_train = 0.15 * 0.8
95
+ src_lengths = (~padding_mask).sum(-1)
96
+ mask_ratio_observed = (tokens == self.mask_idx).sum(-1).to(x.dtype) / src_lengths
97
+ x = x * (1 - mask_ratio_train) / (1 - mask_ratio_observed)[:, None, None]
98
+
99
+ if padding_mask is not None:
100
+ x = x * (1 - padding_mask.unsqueeze(-1).type_as(x))
101
+
102
+ repr_layers = set(repr_layers)
103
+ hidden_representations = {}
104
+ if 0 in repr_layers:
105
+ hidden_representations[0] = x
106
+
107
+ if need_head_weights:
108
+ attn_weights = []
109
+
110
+ # (B, T, E) => (T, B, E)
111
+ x = x.transpose(0, 1)
112
+
113
+ if not padding_mask.any():
114
+ padding_mask = None
115
+
116
+ for layer_idx, layer in enumerate(self.layers):
117
+ x, attn = layer(
118
+ x,
119
+ self_attn_padding_mask=padding_mask,
120
+ need_head_weights=need_head_weights,
121
+ )
122
+ if (layer_idx + 1) in repr_layers:
123
+ hidden_representations[layer_idx + 1] = x.transpose(0, 1)
124
+ if need_head_weights:
125
+ # (H, B, T, T) => (B, H, T, T)
126
+ attn_weights.append(attn.transpose(1, 0))
127
+
128
+ x = self.emb_layer_norm_after(x)
129
+ x = x.transpose(0, 1) # (T, B, E) => (B, T, E)
130
+
131
+ # last hidden representation should have layer norm applied
132
+ if (layer_idx + 1) in repr_layers:
133
+ hidden_representations[layer_idx + 1] = x
134
+ x = self.lm_head(x)
135
+
136
+ result = {"logits": x, "representations": hidden_representations}
137
+ if need_head_weights:
138
+ # attentions: B x L x H x T x T
139
+ attentions = torch.stack(attn_weights, 1)
140
+ if padding_mask is not None:
141
+ attention_mask = 1 - padding_mask.type_as(attentions)
142
+ attention_mask = attention_mask.unsqueeze(1) * attention_mask.unsqueeze(2)
143
+ attentions = attentions * attention_mask[:, None, None, :, :]
144
+ result["attentions"] = attentions
145
+ if return_contacts:
146
+ contacts = self.contact_head(tokens, attentions)
147
+ result["contacts"] = contacts
148
+
149
+ return result
150
+
151
+ def predict_contacts(self, tokens):
152
+ return self(tokens, return_contacts=True)["contacts"]
models/esm/esmfold/__init__.py ADDED
File without changes
models/esm/esmfold/v1/esmfold.py ADDED
@@ -0,0 +1,364 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ #
3
+ # This source code is licensed under the MIT license found in the
4
+ # LICENSE file in the root directory of this source tree.
5
+ import typing as T
6
+ from dataclasses import dataclass, field
7
+ from functools import partial
8
+
9
+ import torch
10
+ import torch.nn as nn
11
+ from torch import nn
12
+ from torch.nn import LayerNorm
13
+
14
+ import onescience.models.esm as esm
15
+ from onescience.models.esm import Alphabet
16
+ from onescience.models.esm.esmfold.v1.categorical_mixture import categorical_lddt
17
+ from onescience.models.esm.esmfold.v1.misc import (
18
+ batch_encode_sequences,
19
+ collate_dense_tensors,
20
+ output_to_pdb,
21
+ )
22
+ from onescience.models.esm.esmfold.v1.trunk import FoldingTrunk, FoldingTrunkConfig
23
+ from onescience.datapipes.openfold.data_transforms import make_atom14_masks
24
+ from onescience.utils.openfold.np import residue_constants
25
+ from onescience.utils.openfold.loss import compute_predicted_aligned_error, compute_tm
26
+
27
+
28
+ @dataclass
29
+ class ESMFoldConfig:
30
+ trunk: T.Any = field(default_factory=FoldingTrunkConfig)
31
+ lddt_head_hid_dim: int = 128
32
+
33
+
34
+ load_fn = esm.pretrained.load_model_and_alphabet
35
+ esm_registry = {
36
+ "esm2_8M": partial(load_fn, "esm2_t6_8M_UR50D_500K"),
37
+ "esm2_8M_270K": esm.pretrained.esm2_t6_8M_UR50D,
38
+ "esm2_35M": partial(load_fn, "esm2_t12_35M_UR50D_500K"),
39
+ "esm2_35M_270K": esm.pretrained.esm2_t12_35M_UR50D,
40
+ "esm2_150M": partial(load_fn, "esm2_t30_150M_UR50D_500K"),
41
+ "esm2_150M_270K": partial(load_fn, "esm2_t30_150M_UR50D_270K"),
42
+ "esm2_650M": esm.pretrained.esm2_t33_650M_UR50D,
43
+ "esm2_650M_270K": partial(load_fn, "esm2_t33_650M_270K_UR50D"),
44
+ "esm2_3B": esm.pretrained.esm2_t36_3B_UR50D,
45
+ "esm2_3B_270K": partial(load_fn, "esm2_t36_3B_UR50D_500K"),
46
+ "esm2_15B": esm.pretrained.esm2_t48_15B_UR50D,
47
+ }
48
+
49
+
50
+ class ESMFold(nn.Module):
51
+ def __init__(self, esmfold_config=None, **kwargs):
52
+ super().__init__()
53
+
54
+ self.cfg = esmfold_config if esmfold_config else ESMFoldConfig(**kwargs)
55
+ cfg = self.cfg
56
+
57
+ self.distogram_bins = 64
58
+
59
+ self.esm, self.esm_dict = esm_registry.get(cfg.esm_type)()
60
+
61
+ self.esm.requires_grad_(False)
62
+ self.esm.half()
63
+
64
+ self.esm_feats = self.esm.embed_dim
65
+ self.esm_attns = self.esm.num_layers * self.esm.attention_heads
66
+ self.register_buffer("af2_to_esm", ESMFold._af2_to_esm(self.esm_dict))
67
+ self.esm_s_combine = nn.Parameter(torch.zeros(self.esm.num_layers + 1))
68
+
69
+ c_s = cfg.trunk.sequence_state_dim
70
+ c_z = cfg.trunk.pairwise_state_dim
71
+
72
+ self.esm_s_mlp = nn.Sequential(
73
+ LayerNorm(self.esm_feats),
74
+ nn.Linear(self.esm_feats, c_s),
75
+ nn.ReLU(),
76
+ nn.Linear(c_s, c_s),
77
+ )
78
+ if cfg.use_esm_attn_map:
79
+ self.esm_z_mlp = nn.Sequential(
80
+ LayerNorm(self.esm_attns),
81
+ nn.Linear(self.esm_attns, c_z),
82
+ nn.ReLU(),
83
+ nn.Linear(c_z, c_z),
84
+ )
85
+
86
+ # 0 is padding, N is unknown residues, N + 1 is mask.
87
+ self.n_tokens_embed = residue_constants.restype_num + 3
88
+ self.pad_idx = 0
89
+ self.unk_idx = self.n_tokens_embed - 2
90
+ self.mask_idx = self.n_tokens_embed - 1
91
+ self.embedding = nn.Embedding(self.n_tokens_embed, c_s, padding_idx=0)
92
+
93
+ self.trunk = FoldingTrunk(**cfg.trunk)
94
+
95
+ self.distogram_head = nn.Linear(c_z, self.distogram_bins)
96
+ self.ptm_head = nn.Linear(c_z, self.distogram_bins)
97
+ self.lm_head = nn.Linear(c_s, self.n_tokens_embed)
98
+ self.lddt_bins = 50
99
+ self.lddt_head = nn.Sequential(
100
+ nn.LayerNorm(cfg.trunk.structure_module.c_s),
101
+ nn.Linear(cfg.trunk.structure_module.c_s, cfg.lddt_head_hid_dim),
102
+ nn.Linear(cfg.lddt_head_hid_dim, cfg.lddt_head_hid_dim),
103
+ nn.Linear(cfg.lddt_head_hid_dim, 37 * self.lddt_bins),
104
+ )
105
+
106
+ @staticmethod
107
+ def _af2_to_esm(d: Alphabet):
108
+ # Remember that t is shifted from residue_constants by 1 (0 is padding).
109
+ esm_reorder = [d.padding_idx] + [
110
+ d.get_idx(v) for v in residue_constants.restypes_with_x
111
+ ]
112
+ return torch.tensor(esm_reorder)
113
+
114
+ def _af2_idx_to_esm_idx(self, aa, mask):
115
+ aa = (aa + 1).masked_fill(mask != 1, 0)
116
+ return self.af2_to_esm[aa]
117
+
118
+ def _compute_language_model_representations(
119
+ self, esmaa: torch.Tensor
120
+ ) -> torch.Tensor:
121
+ """Adds bos/eos tokens for the language model, since the structure module doesn't use these."""
122
+ batch_size = esmaa.size(0)
123
+
124
+ bosi, eosi = self.esm_dict.cls_idx, self.esm_dict.eos_idx
125
+ bos = esmaa.new_full((batch_size, 1), bosi)
126
+ eos = esmaa.new_full((batch_size, 1), self.esm_dict.padding_idx)
127
+ esmaa = torch.cat([bos, esmaa, eos], dim=1)
128
+ # Use the first padding index as eos during inference.
129
+ esmaa[range(batch_size), (esmaa != 1).sum(1)] = eosi
130
+
131
+ res = self.esm(
132
+ esmaa,
133
+ repr_layers=range(self.esm.num_layers + 1),
134
+ need_head_weights=self.cfg.use_esm_attn_map,
135
+ )
136
+ esm_s = torch.stack(
137
+ [v for _, v in sorted(res["representations"].items())], dim=2
138
+ )
139
+ esm_s = esm_s[:, 1:-1] # B, L, nLayers, C
140
+ esm_z = (
141
+ res["attentions"].permute(0, 4, 3, 1, 2).flatten(3, 4)[:, 1:-1, 1:-1, :]
142
+ if self.cfg.use_esm_attn_map
143
+ else None
144
+ )
145
+ return esm_s, esm_z
146
+
147
+ def _mask_inputs_to_esm(self, esmaa, pattern):
148
+ new_esmaa = esmaa.clone()
149
+ new_esmaa[pattern == 1] = self.esm_dict.mask_idx
150
+ return new_esmaa
151
+
152
+ def forward(
153
+ self,
154
+ aa: torch.Tensor,
155
+ mask: T.Optional[torch.Tensor] = None,
156
+ residx: T.Optional[torch.Tensor] = None,
157
+ masking_pattern: T.Optional[torch.Tensor] = None,
158
+ num_recycles: T.Optional[int] = None,
159
+ ):
160
+ """Runs a forward pass given input tokens. Use `model.infer` to
161
+ run inference from a sequence.
162
+
163
+ Args:
164
+ aa (torch.Tensor): Tensor containing indices corresponding to amino acids. Indices match
165
+ modules.utils.openfold.np.residue_constants.restype_order_with_x.
166
+ mask (torch.Tensor): Binary tensor with 1 meaning position is unmasked and 0 meaning position is masked.
167
+ residx (torch.Tensor): Residue indices of amino acids. Will assume contiguous if not provided.
168
+ masking_pattern (torch.Tensor): Optional masking to pass to the input. Binary tensor of the same size
169
+ as `aa`. Positions with 1 will be masked. ESMFold sometimes produces different samples when
170
+ different masks are provided.
171
+ num_recycles (int): How many recycle iterations to perform. If None, defaults to training max
172
+ recycles, which is 3.
173
+ """
174
+
175
+ if mask is None:
176
+ mask = torch.ones_like(aa)
177
+
178
+ B = aa.shape[0]
179
+ L = aa.shape[1]
180
+ device = aa.device
181
+
182
+ if residx is None:
183
+ residx = torch.arange(L, device=device).expand_as(aa)
184
+
185
+ # === ESM ===
186
+ esmaa = self._af2_idx_to_esm_idx(aa, mask)
187
+
188
+ if masking_pattern is not None:
189
+ esmaa = self._mask_inputs_to_esm(esmaa, masking_pattern)
190
+
191
+ esm_s, esm_z = self._compute_language_model_representations(esmaa)
192
+
193
+ # Convert esm_s to the precision used by the trunk and
194
+ # the structure module. These tensors may be a lower precision if, for example,
195
+ # we're running the language model in fp16 precision.
196
+ esm_s = esm_s.to(self.esm_s_combine.dtype)
197
+ esm_s = esm_s.detach()
198
+
199
+ # === preprocessing ===
200
+ esm_s = (self.esm_s_combine.softmax(0).unsqueeze(0) @ esm_s).squeeze(2)
201
+
202
+ s_s_0 = self.esm_s_mlp(esm_s)
203
+ if self.cfg.use_esm_attn_map:
204
+ esm_z = esm_z.to(self.esm_s_combine.dtype)
205
+ esm_z = esm_z.detach()
206
+ s_z_0 = self.esm_z_mlp(esm_z)
207
+ else:
208
+ s_z_0 = s_s_0.new_zeros(B, L, L, self.cfg.trunk.pairwise_state_dim)
209
+
210
+ s_s_0 += self.embedding(aa)
211
+
212
+ structure: dict = self.trunk(
213
+ s_s_0, s_z_0, aa, residx, mask, no_recycles=num_recycles
214
+ )
215
+ # Documenting what we expect:
216
+ structure = {
217
+ k: v
218
+ for k, v in structure.items()
219
+ if k
220
+ in [
221
+ "s_z",
222
+ "s_s",
223
+ "frames",
224
+ "sidechain_frames",
225
+ "unnormalized_angles",
226
+ "angles",
227
+ "positions",
228
+ "states",
229
+ ]
230
+ }
231
+
232
+ disto_logits = self.distogram_head(structure["s_z"])
233
+ disto_logits = (disto_logits + disto_logits.transpose(1, 2)) / 2
234
+ structure["distogram_logits"] = disto_logits
235
+
236
+ lm_logits = self.lm_head(structure["s_s"])
237
+ structure["lm_logits"] = lm_logits
238
+
239
+ structure["aatype"] = aa
240
+ make_atom14_masks(structure)
241
+
242
+ for k in [
243
+ "atom14_atom_exists",
244
+ "atom37_atom_exists",
245
+ ]:
246
+ structure[k] *= mask.unsqueeze(-1)
247
+ structure["residue_index"] = residx
248
+
249
+ lddt_head = self.lddt_head(structure["states"]).reshape(
250
+ structure["states"].shape[0], B, L, -1, self.lddt_bins
251
+ )
252
+ structure["lddt_head"] = lddt_head
253
+ plddt = categorical_lddt(lddt_head[-1], bins=self.lddt_bins)
254
+ structure["plddt"] = (
255
+ 100 * plddt
256
+ ) # we predict plDDT between 0 and 1, scale to be between 0 and 100.
257
+
258
+ ptm_logits = self.ptm_head(structure["s_z"])
259
+
260
+ seqlen = mask.type(torch.int64).sum(1)
261
+ structure["ptm_logits"] = ptm_logits
262
+ structure["ptm"] = torch.stack(
263
+ [
264
+ compute_tm(
265
+ batch_ptm_logits[None, :sl, :sl],
266
+ max_bins=31,
267
+ no_bins=self.distogram_bins,
268
+ )
269
+ for batch_ptm_logits, sl in zip(ptm_logits, seqlen)
270
+ ]
271
+ )
272
+ structure.update(
273
+ compute_predicted_aligned_error(
274
+ ptm_logits, max_bin=31, no_bins=self.distogram_bins
275
+ )
276
+ )
277
+
278
+ return structure
279
+
280
+ @torch.no_grad()
281
+ def infer(
282
+ self,
283
+ sequences: T.Union[str, T.List[str]],
284
+ residx=None,
285
+ masking_pattern: T.Optional[torch.Tensor] = None,
286
+ num_recycles: T.Optional[int] = None,
287
+ residue_index_offset: T.Optional[int] = 512,
288
+ chain_linker: T.Optional[str] = "G" * 25,
289
+ ):
290
+ """Runs a forward pass given input sequences.
291
+
292
+ Args:
293
+ sequences (Union[str, List[str]]): A list of sequences to make predictions for. Multimers can also be passed in,
294
+ each chain should be separated by a ':' token (e.g. "<chain1>:<chain2>:<chain3>").
295
+ residx (torch.Tensor): Residue indices of amino acids. Will assume contiguous if not provided.
296
+ masking_pattern (torch.Tensor): Optional masking to pass to the input. Binary tensor of the same size
297
+ as `aa`. Positions with 1 will be masked. ESMFold sometimes produces different samples when
298
+ different masks are provided.
299
+ num_recycles (int): How many recycle iterations to perform. If None, defaults to training max
300
+ recycles (cfg.trunk.max_recycles), which is 4.
301
+ residue_index_offset (int): Residue index separation between chains if predicting a multimer. Has no effect on
302
+ single chain predictions. Default: 512.
303
+ chain_linker (str): Linker to use between chains if predicting a multimer. Has no effect on single chain
304
+ predictions. Default: length-25 poly-G ("G" * 25).
305
+ """
306
+ if isinstance(sequences, str):
307
+ sequences = [sequences]
308
+
309
+ aatype, mask, _residx, linker_mask, chain_index = batch_encode_sequences(
310
+ sequences, residue_index_offset, chain_linker
311
+ )
312
+
313
+ if residx is None:
314
+ residx = _residx
315
+ elif not isinstance(residx, torch.Tensor):
316
+ residx = collate_dense_tensors(residx)
317
+
318
+ aatype, mask, residx, linker_mask = map(
319
+ lambda x: x.to(self.device), (aatype, mask, residx, linker_mask)
320
+ )
321
+
322
+ output = self.forward(
323
+ aatype,
324
+ mask=mask,
325
+ residx=residx,
326
+ masking_pattern=masking_pattern,
327
+ num_recycles=num_recycles,
328
+ )
329
+
330
+ output["atom37_atom_exists"] = output[
331
+ "atom37_atom_exists"
332
+ ] * linker_mask.unsqueeze(2)
333
+
334
+ output["mean_plddt"] = (output["plddt"] * output["atom37_atom_exists"]).sum(
335
+ dim=(1, 2)
336
+ ) / output["atom37_atom_exists"].sum(dim=(1, 2))
337
+ output["chain_index"] = chain_index
338
+
339
+ return output
340
+
341
+ def output_to_pdb(self, output: T.Dict) -> T.List[str]:
342
+ """Returns the pbd (file) string from the model given the model output."""
343
+ return output_to_pdb(output)
344
+
345
+ def infer_pdbs(self, seqs: T.List[str], *args, **kwargs) -> T.List[str]:
346
+ """Returns list of pdb (files) strings from the model given a list of input sequences."""
347
+ output = self.infer(seqs, *args, **kwargs)
348
+ return self.output_to_pdb(output)
349
+
350
+ def infer_pdb(self, sequence: str, *args, **kwargs) -> str:
351
+ """Returns the pdb (file) string from the model given an input sequence."""
352
+ return self.infer_pdbs([sequence], *args, **kwargs)[0]
353
+
354
+ def set_chunk_size(self, chunk_size: T.Optional[int]):
355
+ # This parameter means the axial attention will be computed
356
+ # in a chunked manner. This should make the memory used more or less O(L) instead of O(L^2).
357
+ # It's equivalent to running a for loop over chunks of the dimension we're iterative over,
358
+ # where the chunk_size is the size of the chunks, so 128 would mean to parse 128-lengthed chunks.
359
+ # Setting the value to None will return to default behavior, disable chunking.
360
+ self.trunk.set_chunk_size(chunk_size)
361
+
362
+ @property
363
+ def device(self):
364
+ return self.esm_s_combine.device
models/esm/msa_transformer.py ADDED
@@ -0,0 +1,238 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ #
3
+ # This source code is licensed under the MIT license found in the
4
+ # LICENSE file in the root directory of this source tree.
5
+
6
+ import torch
7
+ import torch.nn as nn
8
+
9
+ from onescience.modules.esm import (
10
+ AxialTransformerLayer,
11
+ LearnedPositionalEmbedding,
12
+ RobertaLMHead,
13
+ ESM1bLayerNorm,
14
+ ContactPredictionHead,
15
+ )
16
+
17
+ from onescience.modules.attention import RowSelfAttention, ColumnSelfAttention
18
+
19
+
20
+
21
+ class MSATransformer(nn.Module):
22
+ @classmethod
23
+ def add_args(cls, parser):
24
+ # fmt: off
25
+ parser.add_argument(
26
+ "--num_layers",
27
+ default=12,
28
+ type=int,
29
+ metavar="N",
30
+ help="number of layers"
31
+ )
32
+ parser.add_argument(
33
+ "--embed_dim",
34
+ default=768,
35
+ type=int,
36
+ metavar="N",
37
+ help="embedding dimension"
38
+ )
39
+ parser.add_argument(
40
+ "--logit_bias",
41
+ action="store_true",
42
+ help="whether to apply bias to logits"
43
+ )
44
+ parser.add_argument(
45
+ "--ffn_embed_dim",
46
+ default=3072,
47
+ type=int,
48
+ metavar="N",
49
+ help="embedding dimension for FFN",
50
+ )
51
+ parser.add_argument(
52
+ "--attention_heads",
53
+ default=12,
54
+ type=int,
55
+ metavar="N",
56
+ help="number of attention heads",
57
+ )
58
+ parser.add_argument(
59
+ "--dropout",
60
+ default=0.1,
61
+ type=float,
62
+ help="Dropout to apply."
63
+ )
64
+ parser.add_argument(
65
+ "--attention_dropout",
66
+ default=0.1,
67
+ type=float,
68
+ help="Dropout to apply."
69
+ )
70
+ parser.add_argument(
71
+ "--activation_dropout",
72
+ default=0.1,
73
+ type=float,
74
+ help="Dropout to apply."
75
+ )
76
+ parser.add_argument(
77
+ "--max_tokens_per_msa",
78
+ default=2 ** 14,
79
+ type=int,
80
+ help=(
81
+ "Used during inference to batch attention computations in a single "
82
+ "forward pass. This allows increased input sizes with less memory."
83
+ ),
84
+ )
85
+ # fmt: on
86
+
87
+ def __init__(self, args, alphabet):
88
+ super().__init__()
89
+ self.args = args
90
+ self.alphabet_size = len(alphabet)
91
+ self.padding_idx = alphabet.padding_idx
92
+ self.mask_idx = alphabet.mask_idx
93
+ self.cls_idx = alphabet.cls_idx
94
+ self.eos_idx = alphabet.eos_idx
95
+ self.prepend_bos = alphabet.prepend_bos
96
+ self.append_eos = alphabet.append_eos
97
+
98
+ self.embed_tokens = nn.Embedding(
99
+ self.alphabet_size, self.args.embed_dim, padding_idx=self.padding_idx
100
+ )
101
+
102
+ if getattr(self.args, "embed_positions_msa", False):
103
+ emb_dim = getattr(self.args, "embed_positions_msa_dim", self.args.embed_dim)
104
+ self.msa_position_embedding = nn.Parameter(
105
+ 0.01 * torch.randn(1, 1024, 1, emb_dim),
106
+ requires_grad=True,
107
+ )
108
+ else:
109
+ self.register_parameter("msa_position_embedding", None)
110
+
111
+ self.dropout_module = nn.Dropout(self.args.dropout)
112
+ self.layers = nn.ModuleList(
113
+ [
114
+ AxialTransformerLayer(
115
+ self.args.embed_dim,
116
+ self.args.ffn_embed_dim,
117
+ self.args.attention_heads,
118
+ self.args.dropout,
119
+ self.args.attention_dropout,
120
+ self.args.activation_dropout,
121
+ getattr(self.args, "max_tokens_per_msa", self.args.max_tokens),
122
+ )
123
+ for _ in range(self.args.layers)
124
+ ]
125
+ )
126
+
127
+ self.contact_head = ContactPredictionHead(
128
+ self.args.layers * self.args.attention_heads,
129
+ self.prepend_bos,
130
+ self.append_eos,
131
+ eos_idx=self.eos_idx,
132
+ )
133
+ self.embed_positions = LearnedPositionalEmbedding(
134
+ self.args.max_positions,
135
+ self.args.embed_dim,
136
+ self.padding_idx,
137
+ )
138
+ self.emb_layer_norm_before = ESM1bLayerNorm(self.args.embed_dim)
139
+ self.emb_layer_norm_after = ESM1bLayerNorm(self.args.embed_dim)
140
+ self.lm_head = RobertaLMHead(
141
+ embed_dim=self.args.embed_dim,
142
+ output_dim=self.alphabet_size,
143
+ weight=self.embed_tokens.weight,
144
+ )
145
+
146
+ def forward(self, tokens, repr_layers=[], need_head_weights=False, return_contacts=False):
147
+ if return_contacts:
148
+ need_head_weights = True
149
+
150
+ assert tokens.ndim == 3
151
+ batch_size, num_alignments, seqlen = tokens.size()
152
+ padding_mask = tokens.eq(self.padding_idx) # B, R, C
153
+ if not padding_mask.any():
154
+ padding_mask = None
155
+
156
+ x = self.embed_tokens(tokens)
157
+ x += self.embed_positions(tokens.view(batch_size * num_alignments, seqlen)).view(x.size())
158
+ if self.msa_position_embedding is not None:
159
+ if x.size(1) > 1024:
160
+ raise RuntimeError(
161
+ "Using model with MSA position embedding trained on maximum MSA "
162
+ f"depth of 1024, but received {x.size(1)} alignments."
163
+ )
164
+ x += self.msa_position_embedding[:, :num_alignments]
165
+
166
+ x = self.emb_layer_norm_before(x)
167
+
168
+ x = self.dropout_module(x)
169
+
170
+ if padding_mask is not None:
171
+ x = x * (1 - padding_mask.unsqueeze(-1).type_as(x))
172
+
173
+ repr_layers = set(repr_layers)
174
+ hidden_representations = {}
175
+ if 0 in repr_layers:
176
+ hidden_representations[0] = x
177
+
178
+ if need_head_weights:
179
+ row_attn_weights = []
180
+ col_attn_weights = []
181
+
182
+ # B x R x C x D -> R x C x B x D
183
+ x = x.permute(1, 2, 0, 3)
184
+
185
+ for layer_idx, layer in enumerate(self.layers):
186
+ x = layer(
187
+ x,
188
+ self_attn_padding_mask=padding_mask,
189
+ need_head_weights=need_head_weights,
190
+ )
191
+ if need_head_weights:
192
+ x, col_attn, row_attn = x
193
+ # H x C x B x R x R -> B x H x C x R x R
194
+ col_attn_weights.append(col_attn.permute(2, 0, 1, 3, 4))
195
+ # H x B x C x C -> B x H x C x C
196
+ row_attn_weights.append(row_attn.permute(1, 0, 2, 3))
197
+ if (layer_idx + 1) in repr_layers:
198
+ hidden_representations[layer_idx + 1] = x.permute(2, 0, 1, 3)
199
+
200
+ x = self.emb_layer_norm_after(x)
201
+ x = x.permute(2, 0, 1, 3) # R x C x B x D -> B x R x C x D
202
+
203
+ # last hidden representation should have layer norm applied
204
+ if (layer_idx + 1) in repr_layers:
205
+ hidden_representations[layer_idx + 1] = x
206
+ x = self.lm_head(x)
207
+
208
+ result = {"logits": x, "representations": hidden_representations}
209
+ if need_head_weights:
210
+ # col_attentions: B x L x H x C x R x R
211
+ col_attentions = torch.stack(col_attn_weights, 1)
212
+ # row_attentions: B x L x H x C x C
213
+ row_attentions = torch.stack(row_attn_weights, 1)
214
+ result["col_attentions"] = col_attentions
215
+ result["row_attentions"] = row_attentions
216
+ if return_contacts:
217
+ contacts = self.contact_head(tokens, row_attentions)
218
+ result["contacts"] = contacts
219
+
220
+ return result
221
+
222
+ def predict_contacts(self, tokens):
223
+ return self(tokens, return_contacts=True)["contacts"]
224
+
225
+ @property
226
+ def num_layers(self):
227
+ return self.args.layers
228
+
229
+ def max_tokens_per_msa_(self, value: int) -> None:
230
+ """The MSA Transformer automatically batches attention computations when
231
+ gradients are disabled to allow you to pass in larger MSAs at test time than
232
+ you can fit in GPU memory. By default this occurs when more than 2^14 tokens
233
+ are passed in the input MSA. You can set this value to infinity to disable
234
+ this behavior.
235
+ """
236
+ for module in self.modules():
237
+ if isinstance(module, (RowSelfAttention, ColumnSelfAttention)):
238
+ module.max_tokens_per_msa = value
models/esm/pretrained.py ADDED
@@ -0,0 +1,545 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ #
3
+ # This source code is licensed under the MIT license found in the
4
+ # LICENSE file in the root directory of this source tree.
5
+
6
+ import re
7
+ import urllib
8
+ import warnings
9
+ from argparse import Namespace
10
+ from pathlib import Path
11
+
12
+ import torch
13
+
14
+ import onescience.models.esm as esm
15
+ from onescience.datapipes.esm import Alphabet
16
+ from models.esm.esm2 import ESM2
17
+
18
+
19
+ def _has_regression_weights(model_name):
20
+ """Return whether we expect / require regression weights;
21
+ Right now that is all models except ESM-1v, ESM-IF, and partially trained ESM2 models"""
22
+ return not ("esm1v" in model_name or "esm_if" in model_name or "270K" in model_name or "500K" in model_name)
23
+
24
+
25
+ def load_model_and_alphabet(model_name):
26
+ if model_name.endswith(".pt"): # treat as filepath
27
+ return load_model_and_alphabet_local(model_name)
28
+ else:
29
+ return load_model_and_alphabet_hub(model_name)
30
+
31
+
32
+ def load_hub_workaround(url):
33
+ raise FileNotFoundError(
34
+ "Remote ESM download is disabled in the packaged SimpleFold runtime. "
35
+ "Use load_model_and_alphabet_local() with a file under weight/esm_models."
36
+ )
37
+
38
+
39
+ def load_regression_hub(model_name):
40
+ raise FileNotFoundError(
41
+ f"Remote ESM regression download is disabled: {model_name}. "
42
+ "Place the contact-regression file under weight/esm_models."
43
+ )
44
+
45
+
46
+ def _download_model_and_regression_data(model_name):
47
+ raise FileNotFoundError(
48
+ f"Remote ESM download is disabled: {model_name}. "
49
+ "Place the required ESM files under weight/esm_models."
50
+ )
51
+
52
+
53
+ def load_model_and_alphabet_hub(model_name):
54
+ raise FileNotFoundError(
55
+ f"Remote ESM download is disabled in the packaged SimpleFold runtime: {model_name}. "
56
+ "Place the required ESM .pt file and contact-regression file under weight/esm_models."
57
+ )
58
+
59
+
60
+ def load_model_and_alphabet_local(model_location):
61
+ """Load from local path. The regression weights need to be co-located"""
62
+ model_location = Path(model_location)
63
+ model_data = torch.load(str(model_location), map_location="cpu")
64
+ model_name = model_location.stem
65
+ if _has_regression_weights(model_name):
66
+ regression_location = str(model_location.with_suffix("")) + "-contact-regression.pt"
67
+ regression_data = torch.load(regression_location, map_location="cpu")
68
+ else:
69
+ regression_data = None
70
+ return load_model_and_alphabet_core(model_name, model_data, regression_data)
71
+
72
+
73
+ def has_emb_layer_norm_before(model_state):
74
+ """Determine whether layer norm needs to be applied before the encoder"""
75
+ return any(k.startswith("emb_layer_norm_before") for k, param in model_state.items())
76
+
77
+
78
+ def _load_model_and_alphabet_core_v1(model_data):
79
+ import models.esm as esm # since esm.inverse_folding is imported below, you actually have to re-import esm here
80
+
81
+ alphabet = esm.Alphabet.from_architecture(model_data["args"].arch)
82
+
83
+ if model_data["args"].arch == "roberta_large":
84
+ # upgrade state dict
85
+ pra = lambda s: "".join(s.split("encoder_")[1:] if "encoder" in s else s)
86
+ prs1 = lambda s: "".join(s.split("encoder.")[1:] if "encoder" in s else s)
87
+ prs2 = lambda s: "".join(
88
+ s.split("sentence_encoder.")[1:] if "sentence_encoder" in s else s
89
+ )
90
+ model_args = {pra(arg[0]): arg[1] for arg in vars(model_data["args"]).items()}
91
+ model_state = {prs1(prs2(arg[0])): arg[1] for arg in model_data["model"].items()}
92
+ model_state["embed_tokens.weight"][alphabet.mask_idx].zero_() # For token drop
93
+ model_args["emb_layer_norm_before"] = has_emb_layer_norm_before(model_state)
94
+ model_type = esm.ProteinBertModel
95
+
96
+ elif model_data["args"].arch == "protein_bert_base":
97
+
98
+ # upgrade state dict
99
+ pra = lambda s: "".join(s.split("decoder_")[1:] if "decoder" in s else s)
100
+ prs = lambda s: "".join(s.split("decoder.")[1:] if "decoder" in s else s)
101
+ model_args = {pra(arg[0]): arg[1] for arg in vars(model_data["args"]).items()}
102
+ model_state = {prs(arg[0]): arg[1] for arg in model_data["model"].items()}
103
+ model_type = esm.ProteinBertModel
104
+ elif model_data["args"].arch == "msa_transformer":
105
+
106
+ # upgrade state dict
107
+ pra = lambda s: "".join(s.split("encoder_")[1:] if "encoder" in s else s)
108
+ prs1 = lambda s: "".join(s.split("encoder.")[1:] if "encoder" in s else s)
109
+ prs2 = lambda s: "".join(
110
+ s.split("sentence_encoder.")[1:] if "sentence_encoder" in s else s
111
+ )
112
+ prs3 = lambda s: s.replace("row", "column") if "row" in s else s.replace("column", "row")
113
+ model_args = {pra(arg[0]): arg[1] for arg in vars(model_data["args"]).items()}
114
+ model_state = {prs1(prs2(prs3(arg[0]))): arg[1] for arg in model_data["model"].items()}
115
+ if model_args.get("embed_positions_msa", False):
116
+ emb_dim = model_state["msa_position_embedding"].size(-1)
117
+ model_args["embed_positions_msa_dim"] = emb_dim # initial release, bug: emb_dim==1
118
+
119
+ model_type = esm.MSATransformer
120
+
121
+ elif "invariant_gvp" in model_data["args"].arch:
122
+ import models.esm.inverse_folding
123
+
124
+ model_type = esm.inverse_folding.gvp_transformer.GVPTransformerModel
125
+ model_args = vars(model_data["args"]) # convert Namespace -> dict
126
+
127
+ def update_name(s):
128
+ # Map the module names in checkpoints trained with internal code to
129
+ # the updated module names in open source code
130
+ s = s.replace("W_v", "embed_graph.embed_node")
131
+ s = s.replace("W_e", "embed_graph.embed_edge")
132
+ s = s.replace("embed_scores.0", "embed_confidence")
133
+ s = s.replace("embed_score.", "embed_graph.embed_confidence.")
134
+ s = s.replace("seq_logits_projection.", "")
135
+ s = s.replace("embed_ingraham_features", "embed_dihedrals")
136
+ s = s.replace("embed_gvp_in_local_frame.0", "embed_gvp_output")
137
+ s = s.replace("embed_features_in_local_frame.0", "embed_gvp_input_features")
138
+ return s
139
+
140
+ model_state = {
141
+ update_name(sname): svalue
142
+ for sname, svalue in model_data["model"].items()
143
+ if "version" not in sname
144
+ }
145
+
146
+ else:
147
+ raise ValueError("Unknown architecture selected")
148
+
149
+ model = model_type(
150
+ Namespace(**model_args),
151
+ alphabet,
152
+ )
153
+
154
+ return model, alphabet, model_state
155
+
156
+
157
+ def _load_model_and_alphabet_core_v2(model_data):
158
+ def upgrade_state_dict(state_dict):
159
+ """Removes prefixes 'model.encoder.sentence_encoder.' and 'model.encoder.'."""
160
+ prefixes = ["encoder.sentence_encoder.", "encoder."]
161
+ pattern = re.compile("^" + "|".join(prefixes))
162
+ state_dict = {pattern.sub("", name): param for name, param in state_dict.items()}
163
+ return state_dict
164
+
165
+ cfg = model_data["cfg"]["model"]
166
+ state_dict = model_data["model"]
167
+ state_dict = upgrade_state_dict(state_dict)
168
+ alphabet = Alphabet.from_architecture("ESM-1b")
169
+ model = ESM2(
170
+ num_layers=cfg.encoder_layers,
171
+ embed_dim=cfg.encoder_embed_dim,
172
+ attention_heads=cfg.encoder_attention_heads,
173
+ alphabet=alphabet,
174
+ token_dropout=cfg.token_dropout,
175
+ )
176
+ return model, alphabet, state_dict
177
+
178
+
179
+ def load_model_and_alphabet_core(model_name, model_data, regression_data=None):
180
+ if regression_data is not None:
181
+ model_data["model"].update(regression_data["model"])
182
+
183
+ if model_name.startswith("esm2"):
184
+ model, alphabet, model_state = _load_model_and_alphabet_core_v2(model_data)
185
+ else:
186
+ model, alphabet, model_state = _load_model_and_alphabet_core_v1(model_data)
187
+
188
+ expected_keys = set(model.state_dict().keys())
189
+ found_keys = set(model_state.keys())
190
+
191
+ if regression_data is None:
192
+ expected_missing = {"contact_head.regression.weight", "contact_head.regression.bias"}
193
+ error_msgs = []
194
+ missing = (expected_keys - found_keys) - expected_missing
195
+ if missing:
196
+ error_msgs.append(f"Missing key(s) in state_dict: {missing}.")
197
+ unexpected = found_keys - expected_keys
198
+ if unexpected:
199
+ error_msgs.append(f"Unexpected key(s) in state_dict: {unexpected}.")
200
+
201
+ if error_msgs:
202
+ raise RuntimeError(
203
+ "Error(s) in loading state_dict for {}:\n\t{}".format(
204
+ model.__class__.__name__, "\n\t".join(error_msgs)
205
+ )
206
+ )
207
+ if expected_missing - found_keys:
208
+ warnings.warn(
209
+ "Regression weights not found, predicting contacts will not produce correct results."
210
+ )
211
+
212
+ model.load_state_dict(model_state, strict=regression_data is not None)
213
+
214
+ return model, alphabet
215
+
216
+
217
+ def esm1_t34_670M_UR50S():
218
+ """34 layer transformer model with 670M params, trained on Uniref50 Sparse.
219
+
220
+ Returns a tuple of (Model, Alphabet).
221
+ """
222
+ return load_model_and_alphabet_hub("esm1_t34_670M_UR50S")
223
+
224
+
225
+ def esm1_t34_670M_UR50D():
226
+ """34 layer transformer model with 670M params, trained on Uniref50 Dense.
227
+
228
+ Returns a tuple of (Model, Alphabet).
229
+ """
230
+ return load_model_and_alphabet_hub("esm1_t34_670M_UR50D")
231
+
232
+
233
+ def esm1_t34_670M_UR100():
234
+ """34 layer transformer model with 670M params, trained on Uniref100.
235
+
236
+ Returns a tuple of (Model, Alphabet).
237
+ """
238
+ return load_model_and_alphabet_hub("esm1_t34_670M_UR100")
239
+
240
+
241
+ def esm1_t12_85M_UR50S():
242
+ """12 layer transformer model with 85M params, trained on Uniref50 Sparse.
243
+
244
+ Returns a tuple of (Model, Alphabet).
245
+ """
246
+ return load_model_and_alphabet_hub("esm1_t12_85M_UR50S")
247
+
248
+
249
+ def esm1_t6_43M_UR50S():
250
+ """6 layer transformer model with 43M params, trained on Uniref50 Sparse.
251
+
252
+ Returns a tuple of (Model, Alphabet).
253
+ """
254
+ return load_model_and_alphabet_hub("esm1_t6_43M_UR50S")
255
+
256
+
257
+ def esm1b_t33_650M_UR50S():
258
+ """33 layer transformer model with 650M params, trained on Uniref50 Sparse.
259
+ This is our best performing model, which will be described in a future publication.
260
+
261
+ Returns a tuple of (Model, Alphabet).
262
+ """
263
+ return load_model_and_alphabet_hub("esm1b_t33_650M_UR50S")
264
+
265
+
266
+ def esm_msa1_t12_100M_UR50S():
267
+ warnings.warn(
268
+ "This model had a minor bug in the positional embeddings, "
269
+ "please use ESM-MSA-1b: esm.pretrained.esm_msa1b_t12_100M_UR50S()",
270
+ )
271
+ return load_model_and_alphabet_hub("esm_msa1_t12_100M_UR50S")
272
+
273
+
274
+ def esm_msa1b_t12_100M_UR50S():
275
+ return load_model_and_alphabet_hub("esm_msa1b_t12_100M_UR50S")
276
+
277
+
278
+ def esm1v_t33_650M_UR90S():
279
+ """33 layer transformer model with 650M params, trained on Uniref90.
280
+ This is model 1 of a 5 model ensemble.
281
+
282
+ Returns a tuple of (Model, Alphabet).
283
+ """
284
+ return load_model_and_alphabet_hub("esm1v_t33_650M_UR90S_1")
285
+
286
+
287
+ def esm1v_t33_650M_UR90S_1():
288
+ """33 layer transformer model with 650M params, trained on Uniref90.
289
+ This is model 1 of a 5 model ensemble.
290
+
291
+ Returns a tuple of (Model, Alphabet).
292
+ """
293
+ return load_model_and_alphabet_hub("esm1v_t33_650M_UR90S_1")
294
+
295
+
296
+ def esm1v_t33_650M_UR90S_2():
297
+ """33 layer transformer model with 650M params, trained on Uniref90.
298
+ This is model 2 of a 5 model ensemble.
299
+
300
+ Returns a tuple of (Model, Alphabet).
301
+ """
302
+ return load_model_and_alphabet_hub("esm1v_t33_650M_UR90S_2")
303
+
304
+
305
+ def esm1v_t33_650M_UR90S_3():
306
+ """33 layer transformer model with 650M params, trained on Uniref90.
307
+ This is model 3 of a 5 model ensemble.
308
+
309
+ Returns a tuple of (Model, Alphabet).
310
+ """
311
+ return load_model_and_alphabet_hub("esm1v_t33_650M_UR90S_3")
312
+
313
+
314
+ def esm1v_t33_650M_UR90S_4():
315
+ """33 layer transformer model with 650M params, trained on Uniref90.
316
+ This is model 4 of a 5 model ensemble.
317
+
318
+ Returns a tuple of (Model, Alphabet).
319
+ """
320
+ return load_model_and_alphabet_hub("esm1v_t33_650M_UR90S_4")
321
+
322
+
323
+ def esm1v_t33_650M_UR90S_5():
324
+ """33 layer transformer model with 650M params, trained on Uniref90.
325
+ This is model 5 of a 5 model ensemble.
326
+
327
+ Returns a tuple of (Model, Alphabet).
328
+ """
329
+ return load_model_and_alphabet_hub("esm1v_t33_650M_UR90S_5")
330
+
331
+
332
+ def esm_if1_gvp4_t16_142M_UR50():
333
+ """Inverse folding model with 142M params, with 4 GVP-GNN layers, 8
334
+ Transformer encoder layers, and 8 Transformer decoder layers, trained on
335
+ CATH structures and 12 million alphafold2 predicted structures from UniRef50
336
+ sequences.
337
+
338
+ Returns a tuple of (Model, Alphabet).
339
+ """
340
+ return load_model_and_alphabet_hub("esm_if1_gvp4_t16_142M_UR50")
341
+
342
+
343
+ def esm2_t6_8M_UR50D():
344
+ """6 layer ESM-2 model with 8M params, trained on UniRef50.
345
+
346
+ Returns a tuple of (Model, Alphabet).
347
+ """
348
+ return load_model_and_alphabet_hub("esm2_t6_8M_UR50D")
349
+
350
+
351
+ def esm2_t12_35M_UR50D():
352
+ """12 layer ESM-2 model with 35M params, trained on UniRef50.
353
+
354
+ Returns a tuple of (Model, Alphabet).
355
+ """
356
+ return load_model_and_alphabet_hub("esm2_t12_35M_UR50D")
357
+
358
+
359
+ def esm2_t30_150M_UR50D():
360
+ """30 layer ESM-2 model with 150M params, trained on UniRef50.
361
+
362
+ Returns a tuple of (Model, Alphabet).
363
+ """
364
+ return load_model_and_alphabet_hub("esm2_t30_150M_UR50D")
365
+
366
+
367
+ def esm2_t33_650M_UR50D():
368
+ """33 layer ESM-2 model with 650M params, trained on UniRef50.
369
+
370
+ Returns a tuple of (Model, Alphabet).
371
+ """
372
+ return load_model_and_alphabet_hub("esm2_t33_650M_UR50D")
373
+
374
+
375
+ def esm2_t36_3B_UR50D():
376
+ """36 layer ESM-2 model with 3B params, trained on UniRef50.
377
+
378
+ Returns a tuple of (Model, Alphabet).
379
+ """
380
+ return load_model_and_alphabet_hub("esm2_t36_3B_UR50D")
381
+
382
+
383
+ def esm2_t48_15B_UR50D():
384
+ """48 layer ESM-2 model with 15B params, trained on UniRef50.
385
+ If you have OOM while loading this model, please refer to README
386
+ on how to employ FSDP and ZeRO CPU offloading
387
+
388
+ Returns a tuple of (Model, Alphabet).
389
+ """
390
+ return load_model_and_alphabet_hub("esm2_t48_15B_UR50D")
391
+
392
+
393
+ def esmfold_v0():
394
+ """
395
+ ESMFold v0 model with 3B ESM-2, 48 folding blocks.
396
+ This version was used for the paper (Lin et al, 2022). It was trained
397
+ on all PDB chains until 2020-05, to ensure temporal holdout with CASP14
398
+ and the CAMEO validation and test set reported there.
399
+ """
400
+ import models.esm.esmfold.v1.pretrained
401
+ return esm.esmfold.v1.pretrained.esmfold_v0()
402
+
403
+
404
+ def esmfold_v1():
405
+ """
406
+ ESMFold v1 model using 3B ESM-2, 48 folding blocks.
407
+ ESMFold provides fast high accuracy atomic level structure prediction
408
+ directly from the individual sequence of a protein. ESMFold uses the ESM2
409
+ protein language model to extract meaningful representations from the
410
+ protein sequence.
411
+ """
412
+ import models.esm.esmfold.v1.pretrained
413
+ return esm.esmfold.v1.pretrained.esmfold_v1()
414
+
415
+ def esmfold_structure_module_only_8M():
416
+ """
417
+ ESMFold baseline model using 8M ESM-2, 0 folding blocks.
418
+ ESM-2 here is trained out to 500K updates.
419
+ This is a model designed to test the capabilities of the language model
420
+ when ablated for number of parameters in the language model.
421
+ See table S1 in (Lin et al, 2022).
422
+ """
423
+ import models.esm.esmfold.v1.pretrained
424
+ return esm.esmfold.v1.pretrained.esmfold_structure_module_only_8M()
425
+
426
+
427
+ def esmfold_structure_module_only_8M_270K():
428
+ """
429
+ ESMFold baseline model using 8M ESM-2, 0 folding blocks.
430
+ ESM-2 here is trained out to 270K updates.
431
+ This is a model designed to test the capabilities of the language model
432
+ when ablated for number of parameters in the language model.
433
+ See table S1 in (Lin et al, 2022).
434
+ """
435
+ import models.esm.esmfold.v1.pretrained
436
+ return esm.esmfold.v1.pretrained.esmfold_structure_module_only_8M_270K()
437
+
438
+
439
+ def esmfold_structure_module_only_35M():
440
+ """
441
+ ESMFold baseline model using 35M ESM-2, 0 folding blocks.
442
+ ESM-2 here is trained out to 500K updates.
443
+ This is a model designed to test the capabilities of the language model
444
+ when ablated for number of parameters in the language model.
445
+ See table S1 in (Lin et al, 2022).
446
+ """
447
+ import models.esm.esmfold.v1.pretrained
448
+ return esm.esmfold.v1.pretrained.esmfold_structure_module_only_35M()
449
+
450
+
451
+ def esmfold_structure_module_only_35M_270K():
452
+ """
453
+ ESMFold baseline model using 35M ESM-2, 0 folding blocks.
454
+ ESM-2 here is trained out to 270K updates.
455
+ This is a model designed to test the capabilities of the language model
456
+ when ablated for number of parameters in the language model.
457
+ See table S1 in (Lin et al, 2022).
458
+ """
459
+ import models.esm.esmfold.v1.pretrained
460
+ return esm.esmfold.v1.pretrained.esmfold_structure_module_only_35M_270K()
461
+
462
+
463
+ def esmfold_structure_module_only_150M():
464
+ """
465
+ ESMFold baseline model using 150M ESM-2, 0 folding blocks.
466
+ ESM-2 here is trained out to 500K updates.
467
+ This is a model designed to test the capabilities of the language model
468
+ when ablated for number of parameters in the language model.
469
+ See table S1 in (Lin et al, 2022).
470
+ """
471
+ import models.esm.esmfold.v1.pretrained
472
+ return esm.esmfold.v1.pretrained.esmfold_structure_module_only_150M()
473
+
474
+
475
+ def esmfold_structure_module_only_150M_270K():
476
+ """
477
+ ESMFold baseline model using 150M ESM-2, 0 folding blocks.
478
+ ESM-2 here is trained out to 270K updates.
479
+ This is a model designed to test the capabilities of the language model
480
+ when ablated for number of parameters in the language model.
481
+ See table S1 in (Lin et al, 2022).
482
+ """
483
+ import models.esm.esmfold.v1.pretrained
484
+ return esm.esmfold.v1.pretrained.esmfold_structure_module_only_150M_270K()
485
+
486
+
487
+ def esmfold_structure_module_only_650M():
488
+ """
489
+ ESMFold baseline model using 650M ESM-2, 0 folding blocks.
490
+ ESM-2 here is trained out to 500K updates.
491
+ This is a model designed to test the capabilities of the language model
492
+ when ablated for number of parameters in the language model.
493
+ See table S1 in (Lin et al, 2022).
494
+ """
495
+ import models.esm.esmfold.v1.pretrained
496
+ return esm.esmfold.v1.pretrained.esmfold_structure_module_only_650M()
497
+
498
+
499
+ def esmfold_structure_module_only_650M_270K():
500
+ """
501
+ ESMFold baseline model using 650M ESM-2, 0 folding blocks.
502
+ ESM-2 here is trained out to 270K updates.
503
+ This is a model designed to test the capabilities of the language model
504
+ when ablated for number of parameters in the language model.
505
+ See table S1 in (Lin et al, 2022).
506
+ """
507
+ import models.esm.esmfold.v1.pretrained
508
+ return esm.esmfold.v1.pretrained.esmfold_structure_module_only_650M_270K()
509
+
510
+
511
+ def esmfold_structure_module_only_3B():
512
+ """
513
+ ESMFold baseline model using 3B ESM-2, 0 folding blocks.
514
+ ESM-2 here is trained out to 500K updates.
515
+ This is a model designed to test the capabilities of the language model
516
+ when ablated for number of parameters in the language model.
517
+ See table S1 in (Lin et al, 2022).
518
+ """
519
+ import models.esm.esmfold.v1.pretrained
520
+ return esm.esmfold.v1.pretrained.esmfold_structure_module_only_3B()
521
+
522
+
523
+ def esmfold_structure_module_only_3B_270K():
524
+ """
525
+ ESMFold baseline model using 3B ESM-2, 0 folding blocks.
526
+ ESM-2 here is trained out to 270K updates.
527
+ This is a model designed to test the capabilities of the language model
528
+ when ablated for number of parameters in the language model.
529
+ See table S1 in (Lin et al, 2022).
530
+ """
531
+ import models.esm.esmfold.v1.pretrained
532
+ return esm.esmfold.v1.pretrained.esmfold_structure_module_only_3B_270K()
533
+
534
+
535
+ def esmfold_structure_module_only_15B():
536
+ """
537
+ ESMFold baseline model using 15B ESM-2, 0 folding blocks.
538
+ ESM-2 here is trained out to 270K updates.
539
+ The 15B parameter ESM-2 was not trained out to 500K updates
540
+ This is a model designed to test the capabilities of the language model
541
+ when ablated for number of parameters in the language model.
542
+ See table S1 in (Lin et al, 2022).
543
+ """
544
+ import models.esm.esmfold.v1.pretrained
545
+ return esm.esmfold.v1.pretrained.esmfold_structure_module_only_15B()
models/esm/version.py ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ #
3
+ # This source code is licensed under the MIT license found in the
4
+ # LICENSE file in the root directory of this source tree.
5
+
6
+ version = "2.0.1"
models/simplefold/mlx/__pycache__/esm_network.cpython-310.pyc ADDED
Binary file (3.68 kB). View file
 
models/simplefold/mlx/__pycache__/esm_rotary_embedding.cpython-310.pyc ADDED
Binary file (2.61 kB). View file
 
models/simplefold/mlx/__pycache__/sampler.cpython-310.pyc ADDED
Binary file (2.61 kB). View file
 
models/simplefold/torch/__pycache__/__init__.cpython-310.pyc ADDED
Binary file (171 Bytes). View file
 
models/simplefold/torch/__pycache__/architecture.cpython-310.pyc ADDED
Binary file (6.23 kB). View file
 
models/simplefold/torch/__pycache__/architecture.cpython-311.pyc ADDED
Binary file (12.9 kB). View file
 
models/simplefold/torch/__pycache__/blocks.cpython-310.pyc ADDED
Binary file (3.99 kB). View file
 
models/simplefold/torch/__pycache__/blocks.cpython-311.pyc ADDED
Binary file (8.74 kB). View file
 
models/simplefold/torch/__pycache__/confidence_module.cpython-310.pyc ADDED
Binary file (1.9 kB). View file
 
models/simplefold/torch/__pycache__/confidence_module.cpython-311.pyc ADDED
Binary file (3.5 kB). View file
 
models/simplefold/torch/__pycache__/layers.cpython-310.pyc ADDED
Binary file (9.92 kB). View file
 
models/simplefold/torch/__pycache__/layers.cpython-311.pyc ADDED
Binary file (19.1 kB). View file
 
models/simplefold/torch/__pycache__/pos_embed.cpython-310.pyc ADDED
Binary file (5.23 kB). View file
 
models/simplefold/torch/__pycache__/sampler.cpython-310.pyc ADDED
Binary file (2.39 kB). View file
 
models/simplefold/torch/__pycache__/sampler.cpython-311.pyc ADDED
Binary file (4.09 kB). View file
 
models/simplefold/torch/blocks.py ADDED
@@ -0,0 +1,146 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # For licensing see accompanying LICENSE file.
3
+ # Copyright (c) 2025 Apple Inc. Licensed under MIT License.
4
+ #
5
+
6
+ import torch
7
+ from torch import nn
8
+ from .layers import modulate, SwiGLUFeedForward
9
+
10
+ try:
11
+ from timm.models.vision_transformer import Mlp
12
+ except ModuleNotFoundError:
13
+ class Mlp(nn.Module):
14
+ def __init__(self, in_features, hidden_features=None, out_features=None, act_layer=nn.GELU, drop=0):
15
+ super().__init__()
16
+ out_features = out_features or in_features
17
+ hidden_features = hidden_features or in_features
18
+ self.fc1 = nn.Linear(in_features, hidden_features)
19
+ self.act = act_layer()
20
+ self.drop1 = nn.Dropout(drop)
21
+ self.fc2 = nn.Linear(hidden_features, out_features)
22
+ self.drop2 = nn.Dropout(drop)
23
+
24
+ def forward(self, x):
25
+ x = self.fc1(x)
26
+ x = self.act(x)
27
+ x = self.drop1(x)
28
+ x = self.fc2(x)
29
+ x = self.drop2(x)
30
+ return x
31
+
32
+
33
+ class DiTBlock(nn.Module):
34
+ """
35
+ A DiT block with adaptive layer norm zero (adaLN-Zero) conditioning.
36
+ """
37
+
38
+ def __init__(
39
+ self,
40
+ self_attention_layer,
41
+ hidden_size,
42
+ mlp_ratio=4.0,
43
+ use_swiglu=True,
44
+ ):
45
+ super().__init__()
46
+ self.norm1 = nn.LayerNorm(hidden_size, elementwise_affine=False, eps=1e-6)
47
+ self.attn = self_attention_layer()
48
+ self.norm2 = nn.LayerNorm(hidden_size, elementwise_affine=False, eps=1e-6)
49
+ mlp_hidden_dim = int(hidden_size * mlp_ratio)
50
+ if use_swiglu:
51
+ self.mlp = SwiGLUFeedForward(hidden_size, mlp_hidden_dim)
52
+ else:
53
+ approx_gelu = lambda: nn.GELU(approximate="tanh")
54
+ self.mlp = Mlp(
55
+ in_features=hidden_size,
56
+ hidden_features=mlp_hidden_dim,
57
+ act_layer=approx_gelu,
58
+ drop=0,
59
+ )
60
+ self.adaLN_modulation = nn.Sequential(
61
+ nn.SiLU(), nn.Linear(hidden_size, 6 * hidden_size, bias=True)
62
+ )
63
+ self.initialize_weights()
64
+
65
+ def initialize_weights(self):
66
+ # Initialize transformer layers:
67
+ def _basic_init(module):
68
+ if isinstance(module, nn.Linear):
69
+ torch.nn.init.xavier_uniform_(module.weight)
70
+ if module.bias is not None:
71
+ nn.init.constant_(module.bias, 0)
72
+
73
+ self.apply(_basic_init)
74
+
75
+ # Zero-out adaLN modulation layers in DiT encoder blocks:
76
+ nn.init.constant_(self.adaLN_modulation[-1].weight, 0)
77
+ nn.init.constant_(self.adaLN_modulation[-1].bias, 0)
78
+
79
+ def forward(
80
+ self,
81
+ latents,
82
+ c,
83
+ **kwargs,
84
+ ):
85
+ shift_msa, scale_msa, gate_msa, shift_mlp, scale_mlp, gate_mlp = (
86
+ self.adaLN_modulation(c).chunk(6, dim=1)
87
+ )
88
+ _latents = self.attn(
89
+ modulate(self.norm1(latents), shift_msa, scale_msa), **kwargs
90
+ )
91
+ latents = latents + gate_msa.unsqueeze(1) * _latents
92
+ latents = latents + gate_mlp.unsqueeze(1) * self.mlp(
93
+ modulate(self.norm2(latents), shift_mlp, scale_mlp)
94
+ )
95
+ return latents
96
+
97
+
98
+ class TransformerBlock(nn.Module):
99
+ """
100
+ A DiT block with adaptive layer norm zero (adaLN-Zero) conditioning.
101
+ """
102
+
103
+ def __init__(
104
+ self,
105
+ self_attention_layer,
106
+ hidden_size,
107
+ mlp_ratio=4.0,
108
+ use_swiglu=False,
109
+ ):
110
+ super().__init__()
111
+ self.norm1 = nn.LayerNorm(hidden_size, elementwise_affine=False, eps=1e-6)
112
+ self.attn = self_attention_layer()
113
+ self.norm2 = nn.LayerNorm(hidden_size, elementwise_affine=False, eps=1e-6)
114
+ mlp_hidden_dim = int(hidden_size * mlp_ratio)
115
+ approx_gelu = lambda: nn.GELU(approximate="tanh")
116
+ if use_swiglu:
117
+ self.mlp = SwiGLUFeedForward(hidden_size, mlp_hidden_dim)
118
+ else:
119
+ self.mlp = Mlp(
120
+ in_features=hidden_size,
121
+ hidden_features=mlp_hidden_dim,
122
+ act_layer=approx_gelu,
123
+ drop=0,
124
+ )
125
+
126
+ def forward(
127
+ self,
128
+ latents,
129
+ **kwargs,
130
+ ):
131
+ _latents = self.attn(self.norm1(latents), **kwargs)
132
+ latents = latents + _latents
133
+ latents = latents + self.mlp(self.norm2(latents))
134
+ return latents
135
+
136
+
137
+ class HomogenTrunk(nn.Module):
138
+ def __init__(self, block, depth):
139
+ super().__init__()
140
+ self.blocks = nn.ModuleList([block() for _ in range(depth)])
141
+
142
+ def forward(self, latents, c, **kwargs):
143
+ for i, block in enumerate(self.blocks):
144
+ kwargs["layer_idx"] = i
145
+ latents = block(latents=latents, c=c, **kwargs)
146
+ return latents
models/simplefold/torch/confidence_module.py ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # For licensing see accompanying LICENSE file.
3
+ # Copyright (c) 2025 Apple Inc. Licensed under MIT License.
4
+ #
5
+
6
+ import torch
7
+ from torch import nn
8
+
9
+
10
+ def compute_aggregated_metric(logits, end=1.0):
11
+ """Compute the metric from the logits.
12
+
13
+ Parameters
14
+ ----------
15
+ logits : torch.Tensor
16
+ The logits of the metric
17
+ end : float
18
+ Max value of the metric, by default 1.0
19
+
20
+ Returns
21
+ -------
22
+ Tensor
23
+ The metric value
24
+
25
+ """
26
+ num_bins = logits.shape[-1]
27
+ bin_width = end / num_bins
28
+ bounds = torch.arange(
29
+ start=0.5 * bin_width, end=end, step=bin_width, device=logits.device
30
+ )
31
+ probs = nn.functional.softmax(logits, dim=-1)
32
+ plddt = torch.sum(
33
+ probs * bounds.view(*((1,) * len(probs.shape[:-1])), *bounds.shape),
34
+ dim=-1,
35
+ )
36
+ return plddt
37
+
38
+
39
+ class ConfidenceModule(nn.Module):
40
+ def __init__(
41
+ self,
42
+ hidden_size,
43
+ transformer_blocks,
44
+ num_plddt_bins=50,
45
+ ):
46
+ super().__init__()
47
+ self.transformer_blocks = transformer_blocks
48
+ self.to_plddt_logits = nn.Sequential(
49
+ nn.Linear(hidden_size, hidden_size),
50
+ nn.LayerNorm(hidden_size),
51
+ nn.SiLU(),
52
+ nn.Linear(hidden_size, num_plddt_bins),
53
+ )
54
+
55
+ def forward(
56
+ self,
57
+ latent,
58
+ feats,
59
+ ):
60
+ token_pe_pos = torch.cat(
61
+ [
62
+ feats["residue_index"].unsqueeze(-1).float(), # (B, M, 1)
63
+ feats["entity_id"].unsqueeze(-1).float(), # (B, M, 1)
64
+ feats["asym_id"].unsqueeze(-1).float(), # (B, M, 1)
65
+ feats["sym_id"].unsqueeze(-1).float(), # (B, M, 1)
66
+ ],
67
+ dim=-1,
68
+ )
69
+
70
+ latent = self.transformer_blocks(
71
+ latents=latent,
72
+ c=None,
73
+ pos=token_pe_pos,
74
+ )
75
+
76
+ # Compute the pLDDT
77
+ plddt_logits = self.to_plddt_logits(latent)
78
+
79
+ # Compute the aggregated pLDDT
80
+ plddt = compute_aggregated_metric(plddt_logits)
81
+
82
+ return dict(
83
+ plddt=plddt,
84
+ plddt_logits=plddt_logits,
85
+ )
models/simplefold/torch/sampler.py ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # For licensing see accompanying LICENSE file.
3
+ # Copyright (c) 2025 Apple Inc. Licensed under MIT License.
4
+ #
5
+
6
+ import torch
7
+ from tqdm import tqdm
8
+ from einops import repeat
9
+ from onescience.utils.simplefold.boltz_utils import center_random_augmentation
10
+
11
+
12
+ class EMSampler():
13
+ """
14
+ A Euler-Maruyama solver for SDEs.
15
+ """
16
+ def __init__(
17
+ self,
18
+ num_timesteps=500,
19
+ t_start=1e-4,
20
+ tau=0.3,
21
+ log_timesteps=False,
22
+ w_cutoff=0.99,
23
+ ):
24
+ self.num_timesteps = num_timesteps
25
+ self.log_timesteps = log_timesteps
26
+ self.t_start = t_start
27
+ self.tau = tau
28
+ self.w_cutoff = w_cutoff
29
+
30
+ if self.log_timesteps:
31
+ t = 1.0 - torch.logspace(-2, 0, self.num_timesteps + 1).flip(0)
32
+ t = t - torch.min(t)
33
+ t = t / torch.max(t)
34
+ self.steps = t.clamp(min=self.t_start, max=1.0)
35
+ else:
36
+ self.steps = torch.linspace(
37
+ self.t_start, 1.0, steps=self.num_timesteps + 1
38
+ )
39
+
40
+ def diffusion_coefficient(self, t, eps=0.01):
41
+ # determine diffusion coefficient
42
+ w = (1.0 - t) / (t + eps)
43
+ if t >= self.w_cutoff:
44
+ w = 0.0
45
+ return w
46
+
47
+ @torch.no_grad()
48
+ def euler_maruyama_step(
49
+ self,
50
+ model_fn,
51
+ flow,
52
+ y,
53
+ t,
54
+ t_next,
55
+ batch,
56
+ ):
57
+ dt = t_next - t
58
+ eps = torch.randn_like(y).to(y)
59
+
60
+ y = center_random_augmentation(
61
+ y,
62
+ batch["atom_pad_mask"],
63
+ augmentation=False,
64
+ centering=True,
65
+ )
66
+
67
+ batched_t = repeat(t, " -> b", b=y.shape[0])
68
+ velocity = model_fn(
69
+ noised_pos=y,
70
+ t=batched_t,
71
+ feats=batch,
72
+ )['predict_velocity']
73
+ score = flow.compute_score_from_velocity(velocity, y, t)
74
+
75
+ diff_coeff = self.diffusion_coefficient(t)
76
+ drift = velocity + diff_coeff * score
77
+ mean_y = y + drift * dt
78
+ y_sample = mean_y + torch.sqrt(2.0 * dt * diff_coeff * self.tau) * eps
79
+
80
+ return y_sample
81
+
82
+ @torch.no_grad()
83
+ def sample(self, model_fn, flow, noise, batch):
84
+ sampling_timesteps = self.num_timesteps
85
+ steps = self.steps.to(noise.device)
86
+ y_sampled = noise
87
+ feats = batch
88
+
89
+ for i in tqdm(
90
+ range(sampling_timesteps),
91
+ desc="Sampling",
92
+ total=sampling_timesteps,
93
+ ):
94
+ t = steps[i]
95
+ t_next = steps[i + 1]
96
+
97
+ y_sampled = self.euler_maruyama_step(
98
+ model_fn,
99
+ flow,
100
+ y_sampled,
101
+ t,
102
+ t_next,
103
+ feats,
104
+ )
105
+
106
+ return {
107
+ "denoised_coords": y_sampled
108
+ }
weight/ccd.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:2d3b2f03a3c5665944adba51e33263511e51b21c9cd05d902f9c4b7c1e58d2f4
3
+ size 345859128