Repository: Zuricho/ParallelFold Branch: main Commit: b1cefc00331c Files: 108 Total size: 1.3 MB Directory structure: gitextract_x11711o3/ ├── .gitignore ├── README.md ├── alphafold/ │ ├── __init__.py │ ├── common/ │ │ ├── __init__.py │ │ ├── confidence.py │ │ ├── protein.py │ │ ├── protein_test.py │ │ ├── residue_constants.py │ │ ├── residue_constants_test.py │ │ ├── stereo_chemical_props.txt │ │ └── testdata/ │ │ └── 2rbg.pdb │ ├── data/ │ │ ├── __init__.py │ │ ├── feature_processing.py │ │ ├── mmcif_parsing.py │ │ ├── msa_identifiers.py │ │ ├── msa_pairing.py │ │ ├── parsers.py │ │ ├── pipeline.py │ │ ├── pipeline_multimer.py │ │ ├── templates.py │ │ └── tools/ │ │ ├── __init__.py │ │ ├── hhblits.py │ │ ├── hhsearch.py │ │ ├── hmmbuild.py │ │ ├── hmmsearch.py │ │ ├── jackhmmer.py │ │ ├── kalign.py │ │ └── utils.py │ ├── model/ │ │ ├── __init__.py │ │ ├── all_atom.py │ │ ├── all_atom_multimer.py │ │ ├── all_atom_test.py │ │ ├── common_modules.py │ │ ├── config.py │ │ ├── data.py │ │ ├── features.py │ │ ├── folding.py │ │ ├── folding_multimer.py │ │ ├── geometry/ │ │ │ ├── __init__.py │ │ │ ├── rigid_matrix_vector.py │ │ │ ├── rotation_matrix.py │ │ │ ├── struct_of_array.py │ │ │ ├── test_utils.py │ │ │ ├── utils.py │ │ │ └── vector.py │ │ ├── layer_stack.py │ │ ├── layer_stack_test.py │ │ ├── lddt.py │ │ ├── lddt_test.py │ │ ├── mapping.py │ │ ├── model.py │ │ ├── modules.py │ │ ├── modules_multimer.py │ │ ├── prng.py │ │ ├── prng_test.py │ │ ├── quat_affine.py │ │ ├── quat_affine_test.py │ │ ├── r3.py │ │ ├── tf/ │ │ │ ├── __init__.py │ │ │ ├── data_transforms.py │ │ │ ├── input_pipeline.py │ │ │ ├── protein_features.py │ │ │ ├── protein_features_test.py │ │ │ ├── proteins_dataset.py │ │ │ ├── shape_helpers.py │ │ │ ├── shape_helpers_test.py │ │ │ ├── shape_placeholders.py │ │ │ └── utils.py │ │ └── utils.py │ ├── notebooks/ │ │ ├── __init__.py │ │ ├── notebook_utils.py │ │ └── notebook_utils_test.py │ └── relax/ │ ├── __init__.py │ ├── amber_minimize.py │ ├── amber_minimize_test.py │ ├── cleanup.py │ ├── cleanup_test.py │ ├── relax.py │ ├── relax_test.py │ ├── testdata/ │ │ ├── model_output.pdb │ │ ├── multiple_disulfides_target.pdb │ │ ├── with_violations.pdb │ │ └── with_violations_casp14.pdb │ ├── utils.py │ └── utils_test.py ├── docs/ │ ├── python_inputs.md │ └── usage.md ├── environment/ │ └── environment_gpu.yml ├── input/ │ └── mono_set1/ │ ├── GA98.fasta │ └── GB98.fasta ├── requirements.txt ├── run_alphafold.py ├── run_alphafold.sh ├── scripts/ │ ├── download_all_data.sh │ ├── download_alphafold_params.sh │ ├── download_bfd.sh │ ├── download_mgnify.sh │ ├── download_pdb70.sh │ ├── download_pdb_mmcif.sh │ ├── download_pdb_seqres.sh │ ├── download_small_bfd.sh │ ├── download_uniprot.sh │ ├── download_uniref30.sh │ └── download_uniref90.sh └── tools/ ├── batch_scripts/ │ ├── batch_alphafold.sh │ ├── batch_feature.sh │ └── move_batch.sh └── plddt.py ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ *.slurm ================================================ FILE: README.md ================================================
] = 9 / 2 point_variance = max(num_point_qk, 1) * 9. / 2 # Allocate equal variance to scalar, point and attention 2d parts so that # the sum is 1. num_logit_terms = 3 scalar_weights = np.sqrt(1.0 / (num_logit_terms * scalar_variance)) point_weights = np.sqrt(1.0 / (num_logit_terms * point_variance)) attention_2d_weights = np.sqrt(1.0 / (num_logit_terms)) # Trainable per-head weights for points. trainable_point_weights = jax.nn.softplus(hk.get_parameter( 'trainable_point_weights', shape=[num_head], # softplus^{-1} (1) init=hk.initializers.Constant(np.log(np.exp(1.) - 1.)))) point_weights *= jnp.expand_dims(trainable_point_weights, axis=1) v_point = [jnp.swapaxes(x, -2, -3) for x in v_point] q_point = [jnp.swapaxes(x, -2, -3) for x in q_point] k_point = [jnp.swapaxes(x, -2, -3) for x in k_point] dist2 = [ squared_difference(qx[:, :, None, :], kx[:, None, :, :]) for qx, kx in zip(q_point, k_point) ] dist2 = sum(dist2) attn_qk_point = -0.5 * jnp.sum( point_weights[:, None, None, :] * dist2, axis=-1) v = jnp.swapaxes(v_scalar, -2, -3) q = jnp.swapaxes(scalar_weights * q_scalar, -2, -3) k = jnp.swapaxes(k_scalar, -2, -3) attn_qk_scalar = jnp.matmul(q, jnp.swapaxes(k, -2, -1)) attn_logits = attn_qk_scalar + attn_qk_point attention_2d = common_modules.Linear( num_head, name='attention_2d')( inputs_2d) attention_2d = jnp.transpose(attention_2d, [2, 0, 1]) attention_2d = attention_2d_weights * attention_2d attn_logits += attention_2d mask_2d = mask * jnp.swapaxes(mask, -1, -2) attn_logits -= 1e5 * (1. - mask_2d) # [num_head, num_query_residues, num_target_residues] attn = jax.nn.softmax(attn_logits) # [num_head, num_query_residues, num_head * num_scalar_v] result_scalar = jnp.matmul(attn, v) # For point result, implement matmul manually so that it will be a float32 # on TPU. This is equivalent to # result_point_global = [jnp.einsum('bhqk,bhkc->bhqc', attn, vx) # for vx in v_point] # but on the TPU, doing the multiply and reduce_sum ensures the # computation happens in float32 instead of bfloat16. result_point_global = [jnp.sum( attn[:, :, :, None] * vx[:, None, :, :], axis=-2) for vx in v_point] # [num_query_residues, num_head, num_head * num_(scalar|point)_v] result_scalar = jnp.swapaxes(result_scalar, -2, -3) result_point_global = [ jnp.swapaxes(x, -2, -3) for x in result_point_global] # Features used in the linear output projection. Should have the size # [num_query_residues, ?] output_features = [] result_scalar = jnp.reshape( result_scalar, [num_residues, num_head * num_scalar_v]) output_features.append(result_scalar) result_point_global = [ jnp.reshape(r, [num_residues, num_head * num_point_v]) for r in result_point_global] result_point_local = affine.invert_point(result_point_global, extra_dims=1) output_features.extend(result_point_local) output_features.append(jnp.sqrt(self._dist_epsilon + jnp.square(result_point_local[0]) + jnp.square(result_point_local[1]) + jnp.square(result_point_local[2]))) # Dimensions: h = heads, i and j = residues, # c = inputs_2d channels # Contraction happens over the second residue dimension, similarly to how # the usual attention is performed. result_attention_over_2d = jnp.einsum('hij, ijc->ihc', attn, inputs_2d) num_out = num_head * result_attention_over_2d.shape[-1] output_features.append( jnp.reshape(result_attention_over_2d, [num_residues, num_out])) final_init = 'zeros' if self._zero_initialize_last else 'linear' final_act = jnp.concatenate(output_features, axis=-1) return common_modules.Linear( num_output, initializer=final_init, name='output_projection')(final_act) class FoldIteration(hk.Module): """A single iteration of the main structure module loop. Jumper et al. (2021) Suppl. Alg. 20 "StructureModule" lines 6-21 First, each residue attends to all residues using InvariantPointAttention. Then, we apply transition layers to update the hidden representations. Finally, we use the hidden representations to produce an update to the affine of each residue. """ def __init__(self, config, global_config, name='fold_iteration'): super().__init__(name=name) self.config = config self.global_config = global_config def __call__(self, activations, sequence_mask, update_affine, is_training, initial_act, safe_key=None, static_feat_2d=None, aatype=None): c = self.config if safe_key is None: safe_key = prng.SafeKey(hk.next_rng_key()) def safe_dropout_fn(tensor, safe_key): return prng.safe_dropout( tensor=tensor, safe_key=safe_key, rate=c.dropout, is_deterministic=self.global_config.deterministic, is_training=is_training) affine = quat_affine.QuatAffine.from_tensor(activations['affine']) act = activations['act'] attention_module = InvariantPointAttention(self.config, self.global_config) # Attention attn = attention_module( inputs_1d=act, inputs_2d=static_feat_2d, mask=sequence_mask, affine=affine) act += attn safe_key, *sub_keys = safe_key.split(3) sub_keys = iter(sub_keys) act = safe_dropout_fn(act, next(sub_keys)) act = common_modules.LayerNorm( axis=[-1], create_scale=True, create_offset=True, name='attention_layer_norm')( act) final_init = 'zeros' if self.global_config.zero_init else 'linear' # Transition input_act = act for i in range(c.num_layer_in_transition): init = 'relu' if i < c.num_layer_in_transition - 1 else final_init act = common_modules.Linear( c.num_channel, initializer=init, name='transition')( act) if i < c.num_layer_in_transition - 1: act = jax.nn.relu(act) act += input_act act = safe_dropout_fn(act, next(sub_keys)) act = common_modules.LayerNorm( axis=[-1], create_scale=True, create_offset=True, name='transition_layer_norm')(act) if update_affine: # This block corresponds to # Jumper et al. (2021) Alg. 23 "Backbone update" affine_update_size = 6 # Affine update affine_update = common_modules.Linear( affine_update_size, initializer=final_init, name='affine_update')( act) affine = affine.pre_compose(affine_update) sc = MultiRigidSidechain(c.sidechain, self.global_config)( affine.scale_translation(c.position_scale), [act, initial_act], aatype) outputs = {'affine': affine.to_tensor(), 'sc': sc} affine = affine.apply_rotation_tensor_fn(jax.lax.stop_gradient) new_activations = { 'act': act, 'affine': affine.to_tensor() } return new_activations, outputs def generate_affines(representations, batch, config, global_config, is_training, safe_key): """Generate predicted affines for a single chain. Jumper et al. (2021) Suppl. Alg. 20 "StructureModule" This is the main part of the structure module - it iteratively applies folding to produce a set of predicted residue positions. Args: representations: Representations dictionary. batch: Batch dictionary. config: Config for the structure module. global_config: Global config. is_training: Whether the model is being trained. safe_key: A prng.SafeKey object that wraps a PRNG key. Returns: A dictionary containing residue affines and sidechain positions. """ c = config sequence_mask = batch['seq_mask'][:, None] act = common_modules.LayerNorm( axis=[-1], create_scale=True, create_offset=True, name='single_layer_norm')( representations['single']) initial_act = act act = common_modules.Linear( c.num_channel, name='initial_projection')( act) affine = generate_new_affine(sequence_mask) fold_iteration = FoldIteration( c, global_config, name='fold_iteration') assert len(batch['seq_mask'].shape) == 1 activations = {'act': act, 'affine': affine.to_tensor(), } act_2d = common_modules.LayerNorm( axis=[-1], create_scale=True, create_offset=True, name='pair_layer_norm')( representations['pair']) outputs = [] safe_keys = safe_key.split(c.num_layer) for sub_key in safe_keys: activations, output = fold_iteration( activations, initial_act=initial_act, static_feat_2d=act_2d, safe_key=sub_key, sequence_mask=sequence_mask, update_affine=True, is_training=is_training, aatype=batch['aatype']) outputs.append(output) output = jax.tree_map(lambda *x: jnp.stack(x), *outputs) # Include the activations in the output dict for use by the LDDT-Head. output['act'] = activations['act'] return output class StructureModule(hk.Module): """StructureModule as a network head. Jumper et al. (2021) Suppl. Alg. 20 "StructureModule" """ def __init__(self, config, global_config, compute_loss=True, name='structure_module'): super().__init__(name=name) self.config = config self.global_config = global_config self.compute_loss = compute_loss def __call__(self, representations, batch, is_training, safe_key=None): c = self.config ret = {} if safe_key is None: safe_key = prng.SafeKey(hk.next_rng_key()) output = generate_affines( representations=representations, batch=batch, config=self.config, global_config=self.global_config, is_training=is_training, safe_key=safe_key) ret['representations'] = {'structure_module': output['act']} ret['traj'] = output['affine'] * jnp.array([1.] * 4 + [c.position_scale] * 3) ret['sidechains'] = output['sc'] atom14_pred_positions = r3.vecs_to_tensor(output['sc']['atom_pos'])[-1] ret['final_atom14_positions'] = atom14_pred_positions # (N, 14, 3) ret['final_atom14_mask'] = batch['atom14_atom_exists'] # (N, 14) atom37_pred_positions = all_atom.atom14_to_atom37(atom14_pred_positions, batch) atom37_pred_positions *= batch['atom37_atom_exists'][:, :, None] ret['final_atom_positions'] = atom37_pred_positions # (N, 37, 3) ret['final_atom_mask'] = batch['atom37_atom_exists'] # (N, 37) ret['final_affines'] = ret['traj'][-1] if self.compute_loss: return ret else: no_loss_features = ['final_atom_positions', 'final_atom_mask', 'representations'] no_loss_ret = {k: ret[k] for k in no_loss_features} return no_loss_ret def loss(self, value, batch): ret = {'loss': 0.} ret['metrics'] = {} # If requested, compute in-graph metrics. if self.config.compute_in_graph_metrics: atom14_pred_positions = value['final_atom14_positions'] # Compute renaming and violations. value.update(compute_renamed_ground_truth(batch, atom14_pred_positions)) value['violations'] = find_structural_violations( batch, atom14_pred_positions, self.config) # Several violation metrics: violation_metrics = compute_violation_metrics( batch=batch, atom14_pred_positions=atom14_pred_positions, violations=value['violations']) ret['metrics'].update(violation_metrics) backbone_loss(ret, batch, value, self.config) if 'renamed_atom14_gt_positions' not in value: value.update(compute_renamed_ground_truth( batch, value['final_atom14_positions'])) sc_loss = sidechain_loss(batch, value, self.config) ret['loss'] = ((1 - self.config.sidechain.weight_frac) * ret['loss'] + self.config.sidechain.weight_frac * sc_loss['loss']) ret['sidechain_fape'] = sc_loss['fape'] supervised_chi_loss(ret, batch, value, self.config) if self.config.structural_violation_loss_weight: if 'violations' not in value: value['violations'] = find_structural_violations( batch, value['final_atom14_positions'], self.config) structural_violation_loss(ret, batch, value, self.config) return ret def compute_renamed_ground_truth( batch: Dict[str, jnp.ndarray], atom14_pred_positions: jnp.ndarray, ) -> Dict[str, jnp.ndarray]: """Find optimal renaming of ground truth based on the predicted positions. Jumper et al. (2021) Suppl. Alg. 26 "renameSymmetricGroundTruthAtoms" This renamed ground truth is then used for all losses, such that each loss moves the atoms in the same direction. Shape (N). Args: batch: Dictionary containing: * atom14_gt_positions: Ground truth positions. * atom14_alt_gt_positions: Ground truth positions with renaming swaps. * atom14_atom_is_ambiguous: 1.0 for atoms that are affected by renaming swaps. * atom14_gt_exists: Mask for which atoms exist in ground truth. * atom14_alt_gt_exists: Mask for which atoms exist in ground truth after renaming. * atom14_atom_exists: Mask for whether each atom is part of the given amino acid type. atom14_pred_positions: Array of atom positions in global frame with shape (N, 14, 3). Returns: Dictionary containing: alt_naming_is_better: Array with 1.0 where alternative swap is better. renamed_atom14_gt_positions: Array of optimal ground truth positions after renaming swaps are performed. renamed_atom14_gt_exists: Mask after renaming swap is performed. """ alt_naming_is_better = all_atom.find_optimal_renaming( atom14_gt_positions=batch['atom14_gt_positions'], atom14_alt_gt_positions=batch['atom14_alt_gt_positions'], atom14_atom_is_ambiguous=batch['atom14_atom_is_ambiguous'], atom14_gt_exists=batch['atom14_gt_exists'], atom14_pred_positions=atom14_pred_positions, atom14_atom_exists=batch['atom14_atom_exists']) renamed_atom14_gt_positions = ( (1. - alt_naming_is_better[:, None, None]) * batch['atom14_gt_positions'] + alt_naming_is_better[:, None, None] * batch['atom14_alt_gt_positions']) renamed_atom14_gt_mask = ( (1. - alt_naming_is_better[:, None]) * batch['atom14_gt_exists'] + alt_naming_is_better[:, None] * batch['atom14_alt_gt_exists']) return { 'alt_naming_is_better': alt_naming_is_better, # (N) 'renamed_atom14_gt_positions': renamed_atom14_gt_positions, # (N, 14, 3) 'renamed_atom14_gt_exists': renamed_atom14_gt_mask, # (N, 14) } def backbone_loss(ret, batch, value, config): """Backbone FAPE Loss. Jumper et al. (2021) Suppl. Alg. 20 "StructureModule" line 17 Args: ret: Dictionary to write outputs into, needs to contain 'loss'. batch: Batch, needs to contain 'backbone_affine_tensor', 'backbone_affine_mask'. value: Dictionary containing structure module output, needs to contain 'traj', a trajectory of rigids. config: Configuration of loss, should contain 'fape.clamp_distance' and 'fape.loss_unit_distance'. """ affine_trajectory = quat_affine.QuatAffine.from_tensor(value['traj']) rigid_trajectory = r3.rigids_from_quataffine(affine_trajectory) gt_affine = quat_affine.QuatAffine.from_tensor( batch['backbone_affine_tensor']) gt_rigid = r3.rigids_from_quataffine(gt_affine) backbone_mask = batch['backbone_affine_mask'] fape_loss_fn = functools.partial( all_atom.frame_aligned_point_error, l1_clamp_distance=config.fape.clamp_distance, length_scale=config.fape.loss_unit_distance) fape_loss_fn = jax.vmap(fape_loss_fn, (0, None, None, 0, None, None)) fape_loss = fape_loss_fn(rigid_trajectory, gt_rigid, backbone_mask, rigid_trajectory.trans, gt_rigid.trans, backbone_mask) if 'use_clamped_fape' in batch: # Jumper et al. (2021) Suppl. Sec. 1.11.5 "Loss clamping details" use_clamped_fape = jnp.asarray(batch['use_clamped_fape'], jnp.float32) unclamped_fape_loss_fn = functools.partial( all_atom.frame_aligned_point_error, l1_clamp_distance=None, length_scale=config.fape.loss_unit_distance) unclamped_fape_loss_fn = jax.vmap(unclamped_fape_loss_fn, (0, None, None, 0, None, None)) fape_loss_unclamped = unclamped_fape_loss_fn(rigid_trajectory, gt_rigid, backbone_mask, rigid_trajectory.trans, gt_rigid.trans, backbone_mask) fape_loss = (fape_loss * use_clamped_fape + fape_loss_unclamped * (1 - use_clamped_fape)) ret['fape'] = fape_loss[-1] ret['loss'] += jnp.mean(fape_loss) def sidechain_loss(batch, value, config): """All Atom FAPE Loss using renamed rigids.""" # Rename Frames # Jumper et al. (2021) Suppl. Alg. 26 "renameSymmetricGroundTruthAtoms" line 7 alt_naming_is_better = value['alt_naming_is_better'] renamed_gt_frames = ( (1. - alt_naming_is_better[:, None, None]) * batch['rigidgroups_gt_frames'] + alt_naming_is_better[:, None, None] * batch['rigidgroups_alt_gt_frames']) flat_gt_frames = r3.rigids_from_tensor_flat12( jnp.reshape(renamed_gt_frames, [-1, 12])) flat_frames_mask = jnp.reshape(batch['rigidgroups_gt_exists'], [-1]) flat_gt_positions = r3.vecs_from_tensor( jnp.reshape(value['renamed_atom14_gt_positions'], [-1, 3])) flat_positions_mask = jnp.reshape(value['renamed_atom14_gt_exists'], [-1]) # Compute frame_aligned_point_error score for the final layer. pred_frames = value['sidechains']['frames'] pred_positions = value['sidechains']['atom_pos'] def _slice_last_layer_and_flatten(x): return jnp.reshape(x[-1], [-1]) flat_pred_frames = jax.tree_map( _slice_last_layer_and_flatten, pred_frames) flat_pred_positions = jax.tree_map( _slice_last_layer_and_flatten, pred_positions) # FAPE Loss on sidechains fape = all_atom.frame_aligned_point_error( pred_frames=flat_pred_frames, target_frames=flat_gt_frames, frames_mask=flat_frames_mask, pred_positions=flat_pred_positions, target_positions=flat_gt_positions, positions_mask=flat_positions_mask, l1_clamp_distance=config.sidechain.atom_clamp_distance, length_scale=config.sidechain.length_scale) return { 'fape': fape, 'loss': fape} def structural_violation_loss(ret, batch, value, config): """Computes loss for structural violations.""" assert config.sidechain.weight_frac # Put all violation losses together to one large loss. violations = value['violations'] num_atoms = jnp.sum(batch['atom14_atom_exists']).astype(jnp.float32) ret['loss'] += (config.structural_violation_loss_weight * ( violations['between_residues']['bonds_c_n_loss_mean'] + violations['between_residues']['angles_ca_c_n_loss_mean'] + violations['between_residues']['angles_c_n_ca_loss_mean'] + jnp.sum( violations['between_residues']['clashes_per_atom_loss_sum'] + violations['within_residues']['per_atom_loss_sum']) / (1e-6 + num_atoms))) def find_structural_violations( batch: Dict[str, jnp.ndarray], atom14_pred_positions: jnp.ndarray, # (N, 14, 3) config: ml_collections.ConfigDict ): """Computes several checks for structural violations.""" # Compute between residue backbone violations of bonds and angles. connection_violations = all_atom.between_residue_bond_loss( pred_atom_positions=atom14_pred_positions, pred_atom_mask=batch['atom14_atom_exists'].astype(jnp.float32), residue_index=batch['residue_index'].astype(jnp.float32), aatype=batch['aatype'], tolerance_factor_soft=config.violation_tolerance_factor, tolerance_factor_hard=config.violation_tolerance_factor) # Compute the Van der Waals radius for every atom # (the first letter of the atom name is the element type). # Shape: (N, 14). atomtype_radius = jnp.array([ residue_constants.van_der_waals_radius[name[0]] for name in residue_constants.atom_types ]) atom14_atom_radius = batch['atom14_atom_exists'] * utils.batched_gather( atomtype_radius, batch['residx_atom14_to_atom37']) # Compute the between residue clash loss. between_residue_clashes = all_atom.between_residue_clash_loss( atom14_pred_positions=atom14_pred_positions, atom14_atom_exists=batch['atom14_atom_exists'], atom14_atom_radius=atom14_atom_radius, residue_index=batch['residue_index'], overlap_tolerance_soft=config.clash_overlap_tolerance, overlap_tolerance_hard=config.clash_overlap_tolerance) # Compute all within-residue violations (clashes, # bond length and angle violations). restype_atom14_bounds = residue_constants.make_atom14_dists_bounds( overlap_tolerance=config.clash_overlap_tolerance, bond_length_tolerance_factor=config.violation_tolerance_factor) atom14_dists_lower_bound = utils.batched_gather( restype_atom14_bounds['lower_bound'], batch['aatype']) atom14_dists_upper_bound = utils.batched_gather( restype_atom14_bounds['upper_bound'], batch['aatype']) within_residue_violations = all_atom.within_residue_violations( atom14_pred_positions=atom14_pred_positions, atom14_atom_exists=batch['atom14_atom_exists'], atom14_dists_lower_bound=atom14_dists_lower_bound, atom14_dists_upper_bound=atom14_dists_upper_bound, tighten_bounds_for_loss=0.0) # Combine them to a single per-residue violation mask (used later for LDDT). per_residue_violations_mask = jnp.max(jnp.stack([ connection_violations['per_residue_violation_mask'], jnp.max(between_residue_clashes['per_atom_clash_mask'], axis=-1), jnp.max(within_residue_violations['per_atom_violations'], axis=-1)]), axis=0) return { 'between_residues': { 'bonds_c_n_loss_mean': connection_violations['c_n_loss_mean'], # () 'angles_ca_c_n_loss_mean': connection_violations['ca_c_n_loss_mean'], # () 'angles_c_n_ca_loss_mean': connection_violations['c_n_ca_loss_mean'], # () 'connections_per_residue_loss_sum': connection_violations['per_residue_loss_sum'], # (N) 'connections_per_residue_violation_mask': connection_violations['per_residue_violation_mask'], # (N) 'clashes_mean_loss': between_residue_clashes['mean_loss'], # () 'clashes_per_atom_loss_sum': between_residue_clashes['per_atom_loss_sum'], # (N, 14) 'clashes_per_atom_clash_mask': between_residue_clashes['per_atom_clash_mask'], # (N, 14) }, 'within_residues': { 'per_atom_loss_sum': within_residue_violations['per_atom_loss_sum'], # (N, 14) 'per_atom_violations': within_residue_violations['per_atom_violations'], # (N, 14), }, 'total_per_residue_violations_mask': per_residue_violations_mask, # (N) } def compute_violation_metrics( batch: Dict[str, jnp.ndarray], atom14_pred_positions: jnp.ndarray, # (N, 14, 3) violations: Dict[str, jnp.ndarray], ) -> Dict[str, jnp.ndarray]: """Compute several metrics to assess the structural violations.""" ret = {} extreme_ca_ca_violations = all_atom.extreme_ca_ca_distance_violations( pred_atom_positions=atom14_pred_positions, pred_atom_mask=batch['atom14_atom_exists'].astype(jnp.float32), residue_index=batch['residue_index'].astype(jnp.float32)) ret['violations_extreme_ca_ca_distance'] = extreme_ca_ca_violations ret['violations_between_residue_bond'] = utils.mask_mean( mask=batch['seq_mask'], value=violations['between_residues'][ 'connections_per_residue_violation_mask']) ret['violations_between_residue_clash'] = utils.mask_mean( mask=batch['seq_mask'], value=jnp.max( violations['between_residues']['clashes_per_atom_clash_mask'], axis=-1)) ret['violations_within_residue'] = utils.mask_mean( mask=batch['seq_mask'], value=jnp.max( violations['within_residues']['per_atom_violations'], axis=-1)) ret['violations_per_residue'] = utils.mask_mean( mask=batch['seq_mask'], value=violations['total_per_residue_violations_mask']) return ret def supervised_chi_loss(ret, batch, value, config): """Computes loss for direct chi angle supervision. Jumper et al. (2021) Suppl. Alg. 27 "torsionAngleLoss" Args: ret: Dictionary to write outputs into, needs to contain 'loss'. batch: Batch, needs to contain 'seq_mask', 'chi_mask', 'chi_angles'. value: Dictionary containing structure module output, needs to contain value['sidechains']['angles_sin_cos'] for angles and value['sidechains']['unnormalized_angles_sin_cos'] for unnormalized angles. config: Configuration of loss, should contain 'chi_weight' and 'angle_norm_weight', 'angle_norm_weight' scales angle norm term, 'chi_weight' scales torsion term. """ eps = 1e-6 sequence_mask = batch['seq_mask'] num_res = sequence_mask.shape[0] chi_mask = batch['chi_mask'].astype(jnp.float32) pred_angles = jnp.reshape( value['sidechains']['angles_sin_cos'], [-1, num_res, 7, 2]) pred_angles = pred_angles[:, :, 3:] residue_type_one_hot = jax.nn.one_hot( batch['aatype'], residue_constants.restype_num + 1, dtype=jnp.float32)[None] chi_pi_periodic = jnp.einsum('ijk, kl->ijl', residue_type_one_hot, jnp.asarray(residue_constants.chi_pi_periodic)) true_chi = batch['chi_angles'][None] sin_true_chi = jnp.sin(true_chi) cos_true_chi = jnp.cos(true_chi) sin_cos_true_chi = jnp.stack([sin_true_chi, cos_true_chi], axis=-1) # This is -1 if chi is pi-periodic and +1 if it's 2pi-periodic shifted_mask = (1 - 2 * chi_pi_periodic)[..., None] sin_cos_true_chi_shifted = shifted_mask * sin_cos_true_chi sq_chi_error = jnp.sum( squared_difference(sin_cos_true_chi, pred_angles), -1) sq_chi_error_shifted = jnp.sum( squared_difference(sin_cos_true_chi_shifted, pred_angles), -1) sq_chi_error = jnp.minimum(sq_chi_error, sq_chi_error_shifted) sq_chi_loss = utils.mask_mean(mask=chi_mask[None], value=sq_chi_error) ret['chi_loss'] = sq_chi_loss ret['loss'] += config.chi_weight * sq_chi_loss unnormed_angles = jnp.reshape( value['sidechains']['unnormalized_angles_sin_cos'], [-1, num_res, 7, 2]) angle_norm = jnp.sqrt(jnp.sum(jnp.square(unnormed_angles), axis=-1) + eps) norm_error = jnp.abs(angle_norm - 1.) angle_norm_loss = utils.mask_mean(mask=sequence_mask[None, :, None], value=norm_error) ret['angle_norm_loss'] = angle_norm_loss ret['loss'] += config.angle_norm_weight * angle_norm_loss def generate_new_affine(sequence_mask): num_residues, _ = sequence_mask.shape quaternion = jnp.tile( jnp.reshape(jnp.asarray([1., 0., 0., 0.]), [1, 4]), [num_residues, 1]) translation = jnp.zeros([num_residues, 3]) return quat_affine.QuatAffine(quaternion, translation, unstack_inputs=True) def l2_normalize(x, axis=-1, epsilon=1e-12): return x / jnp.sqrt( jnp.maximum(jnp.sum(x**2, axis=axis, keepdims=True), epsilon)) class MultiRigidSidechain(hk.Module): """Class to make side chain atoms.""" def __init__(self, config, global_config, name='rigid_sidechain'): super().__init__(name=name) self.config = config self.global_config = global_config def __call__(self, affine, representations_list, aatype): """Predict side chains using multi-rigid representations. Args: affine: The affines for each residue (translations in angstroms). representations_list: A list of activations to predict side chains from. aatype: Amino acid types. Returns: Dict containing atom positions and frames (in angstroms). """ act = [ common_modules.Linear( # pylint: disable=g-complex-comprehension self.config.num_channel, name='input_projection')(jax.nn.relu(x)) for x in representations_list ] # Sum the activation list (equivalent to concat then Linear). act = sum(act) final_init = 'zeros' if self.global_config.zero_init else 'linear' # Mapping with some residual blocks. for _ in range(self.config.num_residual_block): old_act = act act = common_modules.Linear( self.config.num_channel, initializer='relu', name='resblock1')( jax.nn.relu(act)) act = common_modules.Linear( self.config.num_channel, initializer=final_init, name='resblock2')( jax.nn.relu(act)) act += old_act # Map activations to torsion angles. Shape: (num_res, 14). num_res = act.shape[0] unnormalized_angles = common_modules.Linear( 14, name='unnormalized_angles')( jax.nn.relu(act)) unnormalized_angles = jnp.reshape( unnormalized_angles, [num_res, 7, 2]) angles = l2_normalize(unnormalized_angles, axis=-1) outputs = { 'angles_sin_cos': angles, # jnp.ndarray (N, 7, 2) 'unnormalized_angles_sin_cos': unnormalized_angles, # jnp.ndarray (N, 7, 2) } # Map torsion angles to frames. backb_to_global = r3.rigids_from_quataffine(affine) # Jumper et al. (2021) Suppl. Alg. 24 "computeAllAtomCoordinates" # r3.Rigids with shape (N, 8). all_frames_to_global = all_atom.torsion_angles_to_frames( aatype, backb_to_global, angles) # Use frames and literature positions to create the final atom coordinates. # r3.Vecs with shape (N, 14). pred_positions = all_atom.frames_and_literature_positions_to_atom14_pos( aatype, all_frames_to_global) outputs.update({ 'atom_pos': pred_positions, # r3.Vecs (N, 14) 'frames': all_frames_to_global, # r3.Rigids (N, 8) }) return outputs ================================================ FILE: alphafold/model/folding_multimer.py ================================================ # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Modules and utilities for the structure module in the multimer system.""" import functools import numbers from typing import Any, Dict, Iterable, Mapping, Optional, Tuple, Union from alphafold.common import residue_constants from alphafold.model import all_atom_multimer from alphafold.model import common_modules from alphafold.model import geometry from alphafold.model import modules from alphafold.model import prng from alphafold.model import utils from alphafold.model.geometry import utils as geometry_utils import haiku as hk import jax import jax.numpy as jnp import ml_collections import numpy as np EPSILON = 1e-8 Float = Union[float, jnp.ndarray] def squared_difference(x: jnp.ndarray, y: jnp.ndarray) -> jnp.ndarray: """Computes Squared difference between two arrays.""" return jnp.square(x - y) def make_backbone_affine( positions: geometry.Vec3Array, mask: jnp.ndarray, aatype: jnp.ndarray, ) -> Tuple[geometry.Rigid3Array, jnp.ndarray]: """Make backbone Rigid3Array and mask.""" del aatype a = residue_constants.atom_order['N'] b = residue_constants.atom_order['CA'] c = residue_constants.atom_order['C'] rigid_mask = (mask[:, a] * mask[:, b] * mask[:, c]).astype( jnp.float32) rigid = all_atom_multimer.make_transform_from_reference( a_xyz=positions[:, a], b_xyz=positions[:, b], c_xyz=positions[:, c]) return rigid, rigid_mask class QuatRigid(hk.Module): """Module for projecting Rigids via a quaternion.""" def __init__(self, global_config: ml_collections.ConfigDict, rigid_shape: Union[int, Iterable[int]] = tuple(), full_quat: bool = False, init: str = 'zeros', name: str = 'quat_rigid'): """Module projecting a Rigid Object. For this Module the Rotation is parametrized as a quaternion, If 'full_quat' is True a 4 vector is produced for the rotation which is normalized and treated as a quaternion. When 'full_quat' is False a 3 vector is produced and the 1st component of the quaternion is set to 1. Args: global_config: Global Config, used to set certain properties of underlying Linear module, see common_modules.Linear for details. rigid_shape: Shape of Rigids relative to shape of activations, e.g. when activations have shape (n,) and this is (m,) output will be (n, m) full_quat: Whether to parametrize rotation using full quaternion. init: initializer to use, see common_modules.Linear for details name: Name to use for module. """ self.init = init self.global_config = global_config if isinstance(rigid_shape, int): self.rigid_shape = (rigid_shape,) else: self.rigid_shape = tuple(rigid_shape) self.full_quat = full_quat super(QuatRigid, self).__init__(name=name) def __call__(self, activations: jnp.ndarray) -> geometry.Rigid3Array: """Executes Module. This returns a set of rigid with the same shape as activations, projecting the channel dimension, rigid_shape controls the trailing dimensions. For example when activations is shape (12, 5) and rigid_shape is (3, 2) then the shape of the output rigids will be (12, 3, 2). This also supports passing in an empty tuple for rigid shape, in that case the example would produce a rigid of shape (12,). Args: activations: Activations to use for projection, shape [..., num_channel] Returns: Rigid transformations with shape [...] + rigid_shape """ if self.full_quat: rigid_dim = 7 else: rigid_dim = 6 linear_dims = self.rigid_shape + (rigid_dim,) rigid_flat = common_modules.Linear( linear_dims, initializer=self.init, precision=jax.lax.Precision.HIGHEST, name='rigid')( activations) rigid_flat = geometry_utils.unstack(rigid_flat) if self.full_quat: qw, qx, qy, qz = rigid_flat[:4] translation = rigid_flat[4:] else: qx, qy, qz = rigid_flat[:3] qw = jnp.ones_like(qx) translation = rigid_flat[3:] rotation = geometry.Rot3Array.from_quaternion( qw, qx, qy, qz, normalize=True) translation = geometry.Vec3Array(*translation) return geometry.Rigid3Array(rotation, translation) class PointProjection(hk.Module): """Given input reprensentation and frame produces points in global frame.""" def __init__(self, num_points: Union[Iterable[int], int], global_config: ml_collections.ConfigDict, return_local_points: bool = False, name: str = 'point_projection'): """Constructs Linear Module. Args: num_points: number of points to project. Can be tuple when outputting multiple dimensions global_config: Global Config, passed through to underlying Linear return_local_points: Whether to return points in local frame as well. name: name of module, used for name scopes. """ if isinstance(num_points, numbers.Integral): self.num_points = (num_points,) else: self.num_points = tuple(num_points) self.return_local_points = return_local_points self.global_config = global_config super().__init__(name=name) def __call__( self, activations: jnp.ndarray, rigids: geometry.Rigid3Array ) -> Union[geometry.Vec3Array, Tuple[geometry.Vec3Array, geometry.Vec3Array]]: output_shape = self.num_points output_shape = output_shape[:-1] + (3 * output_shape[-1],) points_local = common_modules.Linear( output_shape, precision=jax.lax.Precision.HIGHEST, name='point_projection')( activations) points_local = jnp.split(points_local, 3, axis=-1) points_local = geometry.Vec3Array(*points_local) rigids = rigids[(...,) + (None,) * len(output_shape)] points_global = rigids.apply_to_point(points_local) if self.return_local_points: return points_global, points_local else: return points_global class InvariantPointAttention(hk.Module): """Invariant point attention module. The high-level idea is that this attention module works over a set of points and associated orientations in 3D space (e.g. protein residues). Each residue outputs a set of queries and keys as points in their local reference frame. The attention is then defined as the euclidean distance between the queries and keys in the global frame. """ def __init__(self, config: ml_collections.ConfigDict, global_config: ml_collections.ConfigDict, dist_epsilon: float = 1e-8, name: str = 'invariant_point_attention'): """Initialize. Args: config: iterative Fold Head Config global_config: Global Config of Model. dist_epsilon: Small value to avoid NaN in distance calculation. name: Sonnet name. """ super().__init__(name=name) self._dist_epsilon = dist_epsilon self._zero_initialize_last = global_config.zero_init self.config = config self.global_config = global_config def __call__( self, inputs_1d: jnp.ndarray, inputs_2d: jnp.ndarray, mask: jnp.ndarray, rigid: geometry.Rigid3Array, ) -> jnp.ndarray: """Compute geometric aware attention. Given a set of query residues (defined by affines and associated scalar features), this function computes geometric aware attention between the query residues and target residues. The residues produce points in their local reference frame, which are converted into the global frame to get attention via euclidean distance. Equivalently the target residues produce points in their local frame to be used as attention values, which are converted into the query residues local frames. Args: inputs_1d: (N, C) 1D input embedding that is the basis for the scalar queries. inputs_2d: (N, M, C') 2D input embedding, used for biases values in the attention between query_inputs_1d and target_inputs_1d. mask: (N, 1) mask to indicate query_inputs_1d that participate in the attention. rigid: Rigid object describing the position and orientation of every element in query_inputs_1d. Returns: Transformation of the input embedding. """ num_head = self.config.num_head attn_logits = 0. num_point_qk = self.config.num_point_qk # Each point pair (q, k) contributes Var [0.5 ||q||^2 -] = 9 / 2 point_variance = max(num_point_qk, 1) * 9. / 2 point_weights = np.sqrt(1.0 / point_variance) # This is equivalent to jax.nn.softplus, but avoids a bug in the test... softplus = lambda x: jnp.logaddexp(x, jnp.zeros_like(x)) raw_point_weights = hk.get_parameter( 'trainable_point_weights', shape=[num_head], # softplus^{-1} (1) init=hk.initializers.Constant(np.log(np.exp(1.) - 1.))) # Trainable per-head weights for points. trainable_point_weights = softplus(raw_point_weights) point_weights *= trainable_point_weights q_point = PointProjection([num_head, num_point_qk], self.global_config, name='q_point_projection')(inputs_1d, rigid) k_point = PointProjection([num_head, num_point_qk], self.global_config, name='k_point_projection')(inputs_1d, rigid) dist2 = geometry.square_euclidean_distance( q_point[:, None, :, :], k_point[None, :, :, :], epsilon=0.) attn_qk_point = -0.5 * jnp.sum(point_weights[:, None] * dist2, axis=-1) attn_logits += attn_qk_point num_scalar_qk = self.config.num_scalar_qk # We assume that all queries and keys come iid from N(0, 1) distribution # and compute the variances of the attention logits. # Each scalar pair (q, k) contributes Var q*k = 1 scalar_variance = max(num_scalar_qk, 1) * 1. scalar_weights = np.sqrt(1.0 / scalar_variance) q_scalar = common_modules.Linear([num_head, num_scalar_qk], use_bias=False, name='q_scalar_projection')( inputs_1d) k_scalar = common_modules.Linear([num_head, num_scalar_qk], use_bias=False, name='k_scalar_projection')( inputs_1d) q_scalar *= scalar_weights attn_logits += jnp.einsum('qhc,khc->qkh', q_scalar, k_scalar) attention_2d = common_modules.Linear( num_head, name='attention_2d')(inputs_2d) attn_logits += attention_2d mask_2d = mask * jnp.swapaxes(mask, -1, -2) attn_logits -= 1e5 * (1. - mask_2d[..., None]) attn_logits *= np.sqrt(1. / 3) # Normalize by number of logit terms (3) attn = jax.nn.softmax(attn_logits, axis=-2) num_scalar_v = self.config.num_scalar_v v_scalar = common_modules.Linear([num_head, num_scalar_v], use_bias=False, name='v_scalar_projection')( inputs_1d) # [num_query_residues, num_head, num_scalar_v] result_scalar = jnp.einsum('qkh, khc->qhc', attn, v_scalar) num_point_v = self.config.num_point_v v_point = PointProjection([num_head, num_point_v], self.global_config, name='v_point_projection')(inputs_1d, rigid) result_point_global = jax.tree_map( lambda x: jnp.sum(attn[..., None] * x, axis=-3), v_point[None]) # Features used in the linear output projection. Should have the size # [num_query_residues, ?] output_features = [] num_query_residues, _ = inputs_1d.shape flat_shape = [num_query_residues, -1] result_scalar = jnp.reshape(result_scalar, flat_shape) output_features.append(result_scalar) result_point_global = jax.tree_map(lambda r: jnp.reshape(r, flat_shape), result_point_global) result_point_local = rigid[..., None].apply_inverse_to_point( result_point_global) output_features.extend( [result_point_local.x, result_point_local.y, result_point_local.z]) point_norms = result_point_local.norm(self._dist_epsilon) output_features.append(point_norms) # Dimensions: h = heads, i and j = residues, # c = inputs_2d channels # Contraction happens over the second residue dimension, similarly to how # the usual attention is performed. result_attention_over_2d = jnp.einsum('ijh, ijc->ihc', attn, inputs_2d) output_features.append(jnp.reshape(result_attention_over_2d, flat_shape)) final_init = 'zeros' if self._zero_initialize_last else 'linear' final_act = jnp.concatenate(output_features, axis=-1) return common_modules.Linear( self.config.num_channel, initializer=final_init, name='output_projection')(final_act) class FoldIteration(hk.Module): """A single iteration of iterative folding. First, each residue attends to all residues using InvariantPointAttention. Then, we apply transition layers to update the hidden representations. Finally, we use the hidden representations to produce an update to the affine of each residue. """ def __init__(self, config: ml_collections.ConfigDict, global_config: ml_collections.ConfigDict, name: str = 'fold_iteration'): super().__init__(name=name) self.config = config self.global_config = global_config def __call__( self, activations: Mapping[str, Any], aatype: jnp.ndarray, sequence_mask: jnp.ndarray, update_rigid: bool, is_training: bool, initial_act: jnp.ndarray, safe_key: Optional[prng.SafeKey] = None, static_feat_2d: Optional[jnp.ndarray] = None, ) -> Tuple[Dict[str, Any], Dict[str, Any]]: c = self.config if safe_key is None: safe_key = prng.SafeKey(hk.next_rng_key()) def safe_dropout_fn(tensor, safe_key): return modules.apply_dropout( tensor=tensor, safe_key=safe_key, rate=0.0 if self.global_config.deterministic else c.dropout, is_training=is_training) rigid = activations['rigid'] act = activations['act'] attention_module = InvariantPointAttention( self.config, self.global_config) # Attention act += attention_module( inputs_1d=act, inputs_2d=static_feat_2d, mask=sequence_mask, rigid=rigid) safe_key, *sub_keys = safe_key.split(3) sub_keys = iter(sub_keys) act = safe_dropout_fn(act, next(sub_keys)) act = common_modules.LayerNorm( axis=-1, create_scale=True, create_offset=True, name='attention_layer_norm')( act) final_init = 'zeros' if self.global_config.zero_init else 'linear' # Transition input_act = act for i in range(c.num_layer_in_transition): init = 'relu' if i < c.num_layer_in_transition - 1 else final_init act = common_modules.Linear( c.num_channel, initializer=init, name='transition')( act) if i < c.num_layer_in_transition - 1: act = jax.nn.relu(act) act += input_act act = safe_dropout_fn(act, next(sub_keys)) act = common_modules.LayerNorm( axis=-1, create_scale=True, create_offset=True, name='transition_layer_norm')(act) if update_rigid: # Rigid update rigid_update = QuatRigid( self.global_config, init=final_init)( act) rigid = rigid @ rigid_update sc = MultiRigidSidechain(c.sidechain, self.global_config)( rigid.scale_translation(c.position_scale), [act, initial_act], aatype) outputs = {'rigid': rigid, 'sc': sc} rotation = jax.tree_map(jax.lax.stop_gradient, rigid.rotation) rigid = geometry.Rigid3Array(rotation, rigid.translation) new_activations = { 'act': act, 'rigid': rigid } return new_activations, outputs def generate_monomer_rigids(representations: Mapping[str, jnp.ndarray], batch: Mapping[str, jnp.ndarray], config: ml_collections.ConfigDict, global_config: ml_collections.ConfigDict, is_training: bool, safe_key: prng.SafeKey ) -> Dict[str, Any]: """Generate predicted Rigid's for a single chain. This is the main part of the iterative fold head - it iteratively applies folding to produce a set of predicted residue positions. Args: representations: Embeddings dictionary. batch: Batch dictionary. config: config for the iterative fold head. global_config: global config. is_training: is training. safe_key: A prng.SafeKey object that wraps a PRNG key. Returns: A dictionary containing residue Rigid's and sidechain positions. """ c = config sequence_mask = batch['seq_mask'][:, None] act = common_modules.LayerNorm( axis=-1, create_scale=True, create_offset=True, name='single_layer_norm')( representations['single']) initial_act = act act = common_modules.Linear( c.num_channel, name='initial_projection')(act) # Sequence Mask has extra 1 at the end. rigid = geometry.Rigid3Array.identity(sequence_mask.shape[:-1]) fold_iteration = FoldIteration( c, global_config, name='fold_iteration') assert len(batch['seq_mask'].shape) == 1 activations = { 'act': act, 'rigid': rigid } act_2d = common_modules.LayerNorm( axis=-1, create_scale=True, create_offset=True, name='pair_layer_norm')( representations['pair']) safe_keys = safe_key.split(c.num_layer) outputs = [] for key in safe_keys: activations, output = fold_iteration( activations, initial_act=initial_act, static_feat_2d=act_2d, aatype=batch['aatype'], safe_key=key, sequence_mask=sequence_mask, update_rigid=True, is_training=is_training, ) outputs.append(output) output = jax.tree_map(lambda *x: jnp.stack(x), *outputs) # Pass along for LDDT-Head. output['act'] = activations['act'] return output class StructureModule(hk.Module): """StructureModule as a network head. Jumper et al. (2021) Suppl. Alg. 20 "StructureModule" """ def __init__(self, config: ml_collections.ConfigDict, global_config: ml_collections.ConfigDict, name: str = 'structure_module'): super().__init__(name=name) self.config = config self.global_config = global_config def __call__(self, representations: Mapping[str, jnp.ndarray], batch: Mapping[str, Any], is_training: bool, safe_key: Optional[prng.SafeKey] = None, compute_loss: bool = False ) -> Dict[str, Any]: c = self.config ret = {} if safe_key is None: safe_key = prng.SafeKey(hk.next_rng_key()) output = generate_monomer_rigids( representations=representations, batch=batch, config=self.config, global_config=self.global_config, is_training=is_training, safe_key=safe_key) ret['traj'] = output['rigid'].scale_translation(c.position_scale).to_array() ret['sidechains'] = output['sc'] ret['sidechains']['atom_pos'] = ret['sidechains']['atom_pos'].to_array() ret['sidechains']['frames'] = ret['sidechains']['frames'].to_array() if 'local_atom_pos' in ret['sidechains']: ret['sidechains']['local_atom_pos'] = ret['sidechains'][ 'local_atom_pos'].to_array() ret['sidechains']['local_frames'] = ret['sidechains'][ 'local_frames'].to_array() aatype = batch['aatype'] seq_mask = batch['seq_mask'] atom14_pred_mask = all_atom_multimer.get_atom14_mask( aatype) * seq_mask[:, None] atom14_pred_positions = output['sc']['atom_pos'][-1] ret['final_atom14_positions'] = atom14_pred_positions # (N, 14, 3) ret['final_atom14_mask'] = atom14_pred_mask # (N, 14) atom37_mask = all_atom_multimer.get_atom37_mask(aatype) * seq_mask[:, None] atom37_pred_positions = all_atom_multimer.atom14_to_atom37( atom14_pred_positions, aatype) atom37_pred_positions *= atom37_mask[:, :, None] ret['final_atom_positions'] = atom37_pred_positions # (N, 37, 3) ret['final_atom_mask'] = atom37_mask # (N, 37) ret['final_rigids'] = ret['traj'][-1] ret['act'] = output['act'] if compute_loss: return ret else: no_loss_features = ['final_atom_positions', 'final_atom_mask', 'act'] no_loss_ret = {k: ret[k] for k in no_loss_features} return no_loss_ret def loss(self, value: Mapping[str, Any], batch: Mapping[str, Any] ) -> Dict[str, Any]: raise NotImplementedError( 'This function should be called on a batch with reordered chains (see ' 'Evans et al (2021) Section 7.3. Multi-Chain Permutation Alignment.') ret = {'loss': 0.} ret['metrics'] = {} aatype = batch['aatype'] all_atom_positions = batch['all_atom_positions'] all_atom_positions = geometry.Vec3Array.from_array(all_atom_positions) all_atom_mask = batch['all_atom_mask'] seq_mask = batch['seq_mask'] residue_index = batch['residue_index'] gt_rigid, gt_affine_mask = make_backbone_affine(all_atom_positions, all_atom_mask, aatype) chi_angles, chi_mask = all_atom_multimer.compute_chi_angles( all_atom_positions, all_atom_mask, aatype) pred_mask = all_atom_multimer.get_atom14_mask(aatype) pred_mask *= seq_mask[:, None] pred_positions = value['final_atom14_positions'] pred_positions = geometry.Vec3Array.from_array(pred_positions) gt_positions, gt_mask, alt_naming_is_better = compute_atom14_gt( aatype, all_atom_positions, all_atom_mask, pred_positions) violations = find_structural_violations( aatype=aatype, residue_index=residue_index, mask=pred_mask, pred_positions=pred_positions, config=self.config, asym_id=batch['asym_id']) sidechains = value['sidechains'] gt_chi_angles = get_renamed_chi_angles(aatype, chi_angles, alt_naming_is_better) # Several violation metrics: violation_metrics = compute_violation_metrics( residue_index=residue_index, mask=pred_mask, seq_mask=seq_mask, pred_positions=pred_positions, violations=violations) ret['metrics'].update(violation_metrics) target_rigid = geometry.Rigid3Array.from_array(value['traj']) gt_frames_mask = gt_affine_mask # Split the loss into within-chain and between-chain components. intra_chain_mask = batch['asym_id'][:, None] == batch['asym_id'][None, :] intra_chain_bb_loss, intra_chain_fape = backbone_loss( gt_rigid=gt_rigid, gt_frames_mask=gt_frames_mask, gt_positions_mask=gt_affine_mask, target_rigid=target_rigid, config=self.config.intra_chain_fape, pair_mask=intra_chain_mask) interface_bb_loss, interface_fape = backbone_loss( gt_rigid=gt_rigid, gt_frames_mask=gt_frames_mask, gt_positions_mask=gt_affine_mask, target_rigid=target_rigid, config=self.config.interface_fape, pair_mask=1. - intra_chain_mask) bb_loss = intra_chain_bb_loss + interface_bb_loss ret['fape'] = intra_chain_fape + interface_fape ret['bb_loss'] = bb_loss ret['loss'] += bb_loss pred_frames = geometry.Rigid3Array.from_array(sidechains['frames']) pred_positions = geometry.Vec3Array.from_array(sidechains['atom_pos']) gt_sc_frames, gt_sc_frames_mask = compute_frames( aatype=aatype, all_atom_positions=all_atom_positions, all_atom_mask=all_atom_mask, use_alt=alt_naming_is_better) sc_loss = sidechain_loss( gt_frames=gt_sc_frames, gt_frames_mask=gt_sc_frames_mask, gt_positions=gt_positions, gt_mask=gt_mask, pred_frames=pred_frames, pred_positions=pred_positions, config=self.config) ret['loss'] = ((1 - self.config.sidechain.weight_frac) * ret['loss'] + self.config.sidechain.weight_frac * sc_loss['loss']) ret['sidechain_fape'] = sc_loss['fape'] unnormed_angles = sidechains['unnormalized_angles_sin_cos'] pred_angles = sidechains['angles_sin_cos'] sup_chi_loss, ret['chi_loss'], ret[ 'angle_norm_loss'] = supervised_chi_loss( sequence_mask=seq_mask, target_chi_mask=chi_mask, target_chi_angles=gt_chi_angles, aatype=aatype, pred_angles=pred_angles, unnormed_angles=unnormed_angles, config=self.config) ret['loss'] += sup_chi_loss if self.config.structural_violation_loss_weight: ret['loss'] += structural_violation_loss( mask=pred_mask, violations=violations, config=self.config) return ret def compute_atom14_gt( aatype: jnp.ndarray, all_atom_positions: geometry.Vec3Array, all_atom_mask: jnp.ndarray, pred_pos: geometry.Vec3Array ) -> Tuple[geometry.Vec3Array, jnp.ndarray, jnp.ndarray]: """Find atom14 positions, this includes finding the correct renaming.""" gt_positions, gt_mask = all_atom_multimer.atom37_to_atom14( aatype, all_atom_positions, all_atom_mask) alt_gt_positions, alt_gt_mask = all_atom_multimer.get_alt_atom14( aatype, gt_positions, gt_mask) atom_is_ambiguous = all_atom_multimer.get_atom14_is_ambiguous(aatype) alt_naming_is_better = all_atom_multimer.find_optimal_renaming( gt_positions=gt_positions, alt_gt_positions=alt_gt_positions, atom_is_ambiguous=atom_is_ambiguous, gt_exists=gt_mask, pred_positions=pred_pos) use_alt = alt_naming_is_better[:, None] gt_mask = (1. - use_alt) * gt_mask + use_alt * alt_gt_mask gt_positions = (1. - use_alt) * gt_positions + use_alt * alt_gt_positions return gt_positions, alt_gt_mask, alt_naming_is_better def backbone_loss(gt_rigid: geometry.Rigid3Array, gt_frames_mask: jnp.ndarray, gt_positions_mask: jnp.ndarray, target_rigid: geometry.Rigid3Array, config: ml_collections.ConfigDict, pair_mask: jnp.ndarray ) -> Tuple[Float, jnp.ndarray]: """Backbone FAPE Loss.""" loss_fn = functools.partial( all_atom_multimer.frame_aligned_point_error, l1_clamp_distance=config.atom_clamp_distance, length_scale=config.loss_unit_distance) loss_fn = jax.vmap(loss_fn, (0, None, None, 0, None, None, None)) fape = loss_fn(target_rigid, gt_rigid, gt_frames_mask, target_rigid.translation, gt_rigid.translation, gt_positions_mask, pair_mask) return jnp.mean(fape), fape[-1] def compute_frames( aatype: jnp.ndarray, all_atom_positions: geometry.Vec3Array, all_atom_mask: jnp.ndarray, use_alt: jnp.ndarray ) -> Tuple[geometry.Rigid3Array, jnp.ndarray]: """Compute Frames from all atom positions. Args: aatype: array of aatypes, int of [N] all_atom_positions: Vector of all atom positions, shape [N, 37] all_atom_mask: mask, shape [N] use_alt: whether to use alternative orientation for ambiguous aatypes shape [N] Returns: Rigid corresponding to Frames w shape [N, 8], mask which Rigids are present w shape [N, 8] """ frames_batch = all_atom_multimer.atom37_to_frames(aatype, all_atom_positions, all_atom_mask) gt_frames = frames_batch['rigidgroups_gt_frames'] alt_gt_frames = frames_batch['rigidgroups_alt_gt_frames'] use_alt = use_alt[:, None] renamed_gt_frames = jax.tree_map( lambda x, y: (1. - use_alt) * x + use_alt * y, gt_frames, alt_gt_frames) return renamed_gt_frames, frames_batch['rigidgroups_gt_exists'] def sidechain_loss(gt_frames: geometry.Rigid3Array, gt_frames_mask: jnp.ndarray, gt_positions: geometry.Vec3Array, gt_mask: jnp.ndarray, pred_frames: geometry.Rigid3Array, pred_positions: geometry.Vec3Array, config: ml_collections.ConfigDict ) -> Dict[str, jnp.ndarray]: """Sidechain Loss using cleaned up rigids.""" flat_gt_frames = jax.tree_map(jnp.ravel, gt_frames) flat_frames_mask = jnp.ravel(gt_frames_mask) flat_gt_positions = jax.tree_map(jnp.ravel, gt_positions) flat_positions_mask = jnp.ravel(gt_mask) # Compute frame_aligned_point_error score for the final layer. def _slice_last_layer_and_flatten(x): return jnp.ravel(x[-1]) flat_pred_frames = jax.tree_map(_slice_last_layer_and_flatten, pred_frames) flat_pred_positions = jax.tree_map(_slice_last_layer_and_flatten, pred_positions) fape = all_atom_multimer.frame_aligned_point_error( pred_frames=flat_pred_frames, target_frames=flat_gt_frames, frames_mask=flat_frames_mask, pred_positions=flat_pred_positions, target_positions=flat_gt_positions, positions_mask=flat_positions_mask, pair_mask=None, length_scale=config.sidechain.loss_unit_distance, l1_clamp_distance=config.sidechain.atom_clamp_distance) return { 'fape': fape, 'loss': fape} def structural_violation_loss(mask: jnp.ndarray, violations: Mapping[str, Float], config: ml_collections.ConfigDict ) -> Float: """Computes Loss for structural Violations.""" # Put all violation losses together to one large loss. num_atoms = jnp.sum(mask).astype(jnp.float32) + 1e-6 between_residues = violations['between_residues'] within_residues = violations['within_residues'] return (config.structural_violation_loss_weight * (between_residues['bonds_c_n_loss_mean'] + between_residues['angles_ca_c_n_loss_mean'] + between_residues['angles_c_n_ca_loss_mean'] + jnp.sum(between_residues['clashes_per_atom_loss_sum'] + within_residues['per_atom_loss_sum']) / num_atoms )) def find_structural_violations( aatype: jnp.ndarray, residue_index: jnp.ndarray, mask: jnp.ndarray, pred_positions: geometry.Vec3Array, # (N, 14) config: ml_collections.ConfigDict, asym_id: jnp.ndarray, ) -> Dict[str, Any]: """Computes several checks for structural Violations.""" # Compute between residue backbone violations of bonds and angles. connection_violations = all_atom_multimer.between_residue_bond_loss( pred_atom_positions=pred_positions, pred_atom_mask=mask.astype(jnp.float32), residue_index=residue_index.astype(jnp.float32), aatype=aatype, tolerance_factor_soft=config.violation_tolerance_factor, tolerance_factor_hard=config.violation_tolerance_factor) # Compute the van der Waals radius for every atom # (the first letter of the atom name is the element type). # shape (N, 14) atomtype_radius = jnp.array([ residue_constants.van_der_waals_radius[name[0]] for name in residue_constants.atom_types ]) residx_atom14_to_atom37 = all_atom_multimer.get_atom14_to_atom37_map(aatype) atom_radius = mask * utils.batched_gather(atomtype_radius, residx_atom14_to_atom37) # Compute the between residue clash loss. between_residue_clashes = all_atom_multimer.between_residue_clash_loss( pred_positions=pred_positions, atom_exists=mask, atom_radius=atom_radius, residue_index=residue_index, overlap_tolerance_soft=config.clash_overlap_tolerance, overlap_tolerance_hard=config.clash_overlap_tolerance, asym_id=asym_id) # Compute all within-residue violations (clashes, # bond length and angle violations). restype_atom14_bounds = residue_constants.make_atom14_dists_bounds( overlap_tolerance=config.clash_overlap_tolerance, bond_length_tolerance_factor=config.violation_tolerance_factor) dists_lower_bound = utils.batched_gather(restype_atom14_bounds['lower_bound'], aatype) dists_upper_bound = utils.batched_gather(restype_atom14_bounds['upper_bound'], aatype) within_residue_violations = all_atom_multimer.within_residue_violations( pred_positions=pred_positions, atom_exists=mask, dists_lower_bound=dists_lower_bound, dists_upper_bound=dists_upper_bound, tighten_bounds_for_loss=0.0) # Combine them to a single per-residue violation mask (used later for LDDT). per_residue_violations_mask = jnp.max(jnp.stack([ connection_violations['per_residue_violation_mask'], jnp.max(between_residue_clashes['per_atom_clash_mask'], axis=-1), jnp.max(within_residue_violations['per_atom_violations'], axis=-1)]), axis=0) return { 'between_residues': { 'bonds_c_n_loss_mean': connection_violations['c_n_loss_mean'], # () 'angles_ca_c_n_loss_mean': connection_violations['ca_c_n_loss_mean'], # () 'angles_c_n_ca_loss_mean': connection_violations['c_n_ca_loss_mean'], # () 'connections_per_residue_loss_sum': connection_violations['per_residue_loss_sum'], # (N) 'connections_per_residue_violation_mask': connection_violations['per_residue_violation_mask'], # (N) 'clashes_mean_loss': between_residue_clashes['mean_loss'], # () 'clashes_per_atom_loss_sum': between_residue_clashes['per_atom_loss_sum'], # (N, 14) 'clashes_per_atom_clash_mask': between_residue_clashes['per_atom_clash_mask'], # (N, 14) }, 'within_residues': { 'per_atom_loss_sum': within_residue_violations['per_atom_loss_sum'], # (N, 14) 'per_atom_violations': within_residue_violations['per_atom_violations'], # (N, 14), }, 'total_per_residue_violations_mask': per_residue_violations_mask, # (N) } def compute_violation_metrics( residue_index: jnp.ndarray, mask: jnp.ndarray, seq_mask: jnp.ndarray, pred_positions: geometry.Vec3Array, # (N, 14) violations: Mapping[str, jnp.ndarray], ) -> Dict[str, jnp.ndarray]: """Compute several metrics to assess the structural violations.""" ret = {} between_residues = violations['between_residues'] within_residues = violations['within_residues'] extreme_ca_ca_violations = all_atom_multimer.extreme_ca_ca_distance_violations( positions=pred_positions, mask=mask.astype(jnp.float32), residue_index=residue_index.astype(jnp.float32)) ret['violations_extreme_ca_ca_distance'] = extreme_ca_ca_violations ret['violations_between_residue_bond'] = utils.mask_mean( mask=seq_mask, value=between_residues['connections_per_residue_violation_mask']) ret['violations_between_residue_clash'] = utils.mask_mean( mask=seq_mask, value=jnp.max(between_residues['clashes_per_atom_clash_mask'], axis=-1)) ret['violations_within_residue'] = utils.mask_mean( mask=seq_mask, value=jnp.max(within_residues['per_atom_violations'], axis=-1)) ret['violations_per_residue'] = utils.mask_mean( mask=seq_mask, value=violations['total_per_residue_violations_mask']) return ret def supervised_chi_loss( sequence_mask: jnp.ndarray, target_chi_mask: jnp.ndarray, aatype: jnp.ndarray, target_chi_angles: jnp.ndarray, pred_angles: jnp.ndarray, unnormed_angles: jnp.ndarray, config: ml_collections.ConfigDict) -> Tuple[Float, Float, Float]: """Computes loss for direct chi angle supervision.""" eps = 1e-6 chi_mask = target_chi_mask.astype(jnp.float32) pred_angles = pred_angles[:, :, 3:] residue_type_one_hot = jax.nn.one_hot( aatype, residue_constants.restype_num + 1, dtype=jnp.float32)[None] chi_pi_periodic = jnp.einsum('ijk, kl->ijl', residue_type_one_hot, jnp.asarray(residue_constants.chi_pi_periodic)) true_chi = target_chi_angles[None] sin_true_chi = jnp.sin(true_chi) cos_true_chi = jnp.cos(true_chi) sin_cos_true_chi = jnp.stack([sin_true_chi, cos_true_chi], axis=-1) # This is -1 if chi is pi periodic and +1 if it's 2 pi periodic shifted_mask = (1 - 2 * chi_pi_periodic)[..., None] sin_cos_true_chi_shifted = shifted_mask * sin_cos_true_chi sq_chi_error = jnp.sum( squared_difference(sin_cos_true_chi, pred_angles), -1) sq_chi_error_shifted = jnp.sum( squared_difference(sin_cos_true_chi_shifted, pred_angles), -1) sq_chi_error = jnp.minimum(sq_chi_error, sq_chi_error_shifted) sq_chi_loss = utils.mask_mean(mask=chi_mask[None], value=sq_chi_error) angle_norm = jnp.sqrt(jnp.sum(jnp.square(unnormed_angles), axis=-1) + eps) norm_error = jnp.abs(angle_norm - 1.) angle_norm_loss = utils.mask_mean(mask=sequence_mask[None, :, None], value=norm_error) loss = (config.chi_weight * sq_chi_loss + config.angle_norm_weight * angle_norm_loss) return loss, sq_chi_loss, angle_norm_loss def l2_normalize(x: jnp.ndarray, axis: int = -1, epsilon: float = 1e-12 ) -> jnp.ndarray: return x / jnp.sqrt( jnp.maximum(jnp.sum(x**2, axis=axis, keepdims=True), epsilon)) def get_renamed_chi_angles(aatype: jnp.ndarray, chi_angles: jnp.ndarray, alt_is_better: jnp.ndarray ) -> jnp.ndarray: """Return renamed chi angles.""" chi_angle_is_ambiguous = utils.batched_gather( jnp.array(residue_constants.chi_pi_periodic, dtype=jnp.float32), aatype) alt_chi_angles = chi_angles + np.pi * chi_angle_is_ambiguous # Map back to [-pi, pi]. alt_chi_angles = alt_chi_angles - 2 * np.pi * (alt_chi_angles > np.pi).astype( jnp.float32) alt_is_better = alt_is_better[:, None] return (1. - alt_is_better) * chi_angles + alt_is_better * alt_chi_angles class MultiRigidSidechain(hk.Module): """Class to make side chain atoms.""" def __init__(self, config: ml_collections.ConfigDict, global_config: ml_collections.ConfigDict, name: str = 'rigid_sidechain'): super().__init__(name=name) self.config = config self.global_config = global_config def __call__(self, rigid: geometry.Rigid3Array, representations_list: Iterable[jnp.ndarray], aatype: jnp.ndarray ) -> Dict[str, Any]: """Predict sidechains using multi-rigid representations. Args: rigid: The Rigid's for each residue (translations in angstoms) representations_list: A list of activations to predict sidechains from. aatype: amino acid types. Returns: dict containing atom positions and frames (in angstrom) """ act = [ common_modules.Linear( # pylint: disable=g-complex-comprehension self.config.num_channel, name='input_projection')(jax.nn.relu(x)) for x in representations_list] # Sum the activation list (equivalent to concat then Conv1D) act = sum(act) final_init = 'zeros' if self.global_config.zero_init else 'linear' # Mapping with some residual blocks. for _ in range(self.config.num_residual_block): old_act = act act = common_modules.Linear( self.config.num_channel, initializer='relu', name='resblock1')( jax.nn.relu(act)) act = common_modules.Linear( self.config.num_channel, initializer=final_init, name='resblock2')( jax.nn.relu(act)) act += old_act # Map activations to torsion angles. # [batch_size, num_res, 14] num_res = act.shape[0] unnormalized_angles = common_modules.Linear( 14, name='unnormalized_angles')( jax.nn.relu(act)) unnormalized_angles = jnp.reshape( unnormalized_angles, [num_res, 7, 2]) angles = l2_normalize(unnormalized_angles, axis=-1) outputs = { 'angles_sin_cos': angles, # jnp.ndarray (N, 7, 2) 'unnormalized_angles_sin_cos': unnormalized_angles, # jnp.ndarray (N, 7, 2) } # Map torsion angles to frames. # geometry.Rigid3Array with shape (N, 8) all_frames_to_global = all_atom_multimer.torsion_angles_to_frames( aatype, rigid, angles) # Use frames and literature positions to create the final atom coordinates. # geometry.Vec3Array with shape (N, 14) pred_positions = all_atom_multimer.frames_and_literature_positions_to_atom14_pos( aatype, all_frames_to_global) outputs.update({ 'atom_pos': pred_positions, # geometry.Vec3Array (N, 14) 'frames': all_frames_to_global, # geometry.Rigid3Array (N, 8) }) return outputs ================================================ FILE: alphafold/model/geometry/__init__.py ================================================ # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Geometry Module.""" from alphafold.model.geometry import rigid_matrix_vector from alphafold.model.geometry import rotation_matrix from alphafold.model.geometry import struct_of_array from alphafold.model.geometry import vector Rot3Array = rotation_matrix.Rot3Array Rigid3Array = rigid_matrix_vector.Rigid3Array StructOfArray = struct_of_array.StructOfArray Vec3Array = vector.Vec3Array square_euclidean_distance = vector.square_euclidean_distance euclidean_distance = vector.euclidean_distance dihedral_angle = vector.dihedral_angle dot = vector.dot cross = vector.cross ================================================ FILE: alphafold/model/geometry/rigid_matrix_vector.py ================================================ # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Rigid3Array Transformations represented by a Matrix and a Vector.""" from __future__ import annotations from typing import Union from alphafold.model.geometry import rotation_matrix from alphafold.model.geometry import struct_of_array from alphafold.model.geometry import vector import jax import jax.numpy as jnp Float = Union[float, jnp.ndarray] VERSION = '0.1' @struct_of_array.StructOfArray(same_dtype=True) class Rigid3Array: """Rigid Transformation, i.e. element of special euclidean group.""" rotation: rotation_matrix.Rot3Array translation: vector.Vec3Array def __matmul__(self, other: Rigid3Array) -> Rigid3Array: new_rotation = self.rotation @ other.rotation new_translation = self.apply_to_point(other.translation) return Rigid3Array(new_rotation, new_translation) def inverse(self) -> Rigid3Array: """Return Rigid3Array corresponding to inverse transform.""" inv_rotation = self.rotation.inverse() inv_translation = inv_rotation.apply_to_point(-self.translation) return Rigid3Array(inv_rotation, inv_translation) def apply_to_point(self, point: vector.Vec3Array) -> vector.Vec3Array: """Apply Rigid3Array transform to point.""" return self.rotation.apply_to_point(point) + self.translation def apply_inverse_to_point(self, point: vector.Vec3Array) -> vector.Vec3Array: """Apply inverse Rigid3Array transform to point.""" new_point = point - self.translation return self.rotation.apply_inverse_to_point(new_point) def compose_rotation(self, other_rotation): rot = self.rotation @ other_rotation trans = jax.tree_map(lambda x: jnp.broadcast_to(x, rot.shape), self.translation) return Rigid3Array(rot, trans) @classmethod def identity(cls, shape, dtype=jnp.float32) -> Rigid3Array: """Return identity Rigid3Array of given shape.""" return cls( rotation_matrix.Rot3Array.identity(shape, dtype=dtype), vector.Vec3Array.zeros(shape, dtype=dtype)) # pytype: disable=wrong-arg-count # trace-all-classes def scale_translation(self, factor: Float) -> Rigid3Array: """Scale translation in Rigid3Array by 'factor'.""" return Rigid3Array(self.rotation, self.translation * factor) def to_array(self): rot_array = self.rotation.to_array() vec_array = self.translation.to_array() return jnp.concatenate([rot_array, vec_array[..., None]], axis=-1) @classmethod def from_array(cls, array): rot = rotation_matrix.Rot3Array.from_array(array[..., :3]) vec = vector.Vec3Array.from_array(array[..., -1]) return cls(rot, vec) # pytype: disable=wrong-arg-count # trace-all-classes @classmethod def from_array4x4(cls, array: jnp.ndarray) -> Rigid3Array: """Construct Rigid3Array from homogeneous 4x4 array.""" assert array.shape[-1] == 4 assert array.shape[-2] == 4 rotation = rotation_matrix.Rot3Array( array[..., 0, 0], array[..., 0, 1], array[..., 0, 2], array[..., 1, 0], array[..., 1, 1], array[..., 1, 2], array[..., 2, 0], array[..., 2, 1], array[..., 2, 2] ) translation = vector.Vec3Array( array[..., 0, 3], array[..., 1, 3], array[..., 2, 3]) return cls(rotation, translation) # pytype: disable=wrong-arg-count # trace-all-classes def __getstate__(self): return (VERSION, (self.rotation, self.translation)) def __setstate__(self, state): version, (rot, trans) = state del version object.__setattr__(self, 'rotation', rot) object.__setattr__(self, 'translation', trans) ================================================ FILE: alphafold/model/geometry/rotation_matrix.py ================================================ # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Rot3Array Matrix Class.""" from __future__ import annotations import dataclasses from alphafold.model.geometry import struct_of_array from alphafold.model.geometry import utils from alphafold.model.geometry import vector import jax import jax.numpy as jnp import numpy as np COMPONENTS = ['xx', 'xy', 'xz', 'yx', 'yy', 'yz', 'zx', 'zy', 'zz'] VERSION = '0.1' @struct_of_array.StructOfArray(same_dtype=True) class Rot3Array: """Rot3Array Matrix in 3 dimensional Space implemented as struct of arrays.""" xx: jnp.ndarray = dataclasses.field(metadata={'dtype': jnp.float32}) xy: jnp.ndarray xz: jnp.ndarray yx: jnp.ndarray yy: jnp.ndarray yz: jnp.ndarray zx: jnp.ndarray zy: jnp.ndarray zz: jnp.ndarray __array_ufunc__ = None def inverse(self) -> Rot3Array: """Returns inverse of Rot3Array.""" return Rot3Array(self.xx, self.yx, self.zx, self.xy, self.yy, self.zy, self.xz, self.yz, self.zz) def apply_to_point(self, point: vector.Vec3Array) -> vector.Vec3Array: """Applies Rot3Array to point.""" return vector.Vec3Array( self.xx * point.x + self.xy * point.y + self.xz * point.z, self.yx * point.x + self.yy * point.y + self.yz * point.z, self.zx * point.x + self.zy * point.y + self.zz * point.z) def apply_inverse_to_point(self, point: vector.Vec3Array) -> vector.Vec3Array: """Applies inverse Rot3Array to point.""" return self.inverse().apply_to_point(point) def __matmul__(self, other: Rot3Array) -> Rot3Array: """Composes two Rot3Arrays.""" c0 = self.apply_to_point(vector.Vec3Array(other.xx, other.yx, other.zx)) c1 = self.apply_to_point(vector.Vec3Array(other.xy, other.yy, other.zy)) c2 = self.apply_to_point(vector.Vec3Array(other.xz, other.yz, other.zz)) return Rot3Array(c0.x, c1.x, c2.x, c0.y, c1.y, c2.y, c0.z, c1.z, c2.z) @classmethod def identity(cls, shape, dtype=jnp.float32) -> Rot3Array: """Returns identity of given shape.""" ones = jnp.ones(shape, dtype=dtype) zeros = jnp.zeros(shape, dtype=dtype) return cls(ones, zeros, zeros, zeros, ones, zeros, zeros, zeros, ones) # pytype: disable=wrong-arg-count # trace-all-classes @classmethod def from_two_vectors(cls, e0: vector.Vec3Array, e1: vector.Vec3Array) -> Rot3Array: """Construct Rot3Array from two Vectors. Rot3Array is constructed such that in the corresponding frame 'e0' lies on the positive x-Axis and 'e1' lies in the xy plane with positive sign of y. Args: e0: Vector e1: Vector Returns: Rot3Array """ # Normalize the unit vector for the x-axis, e0. e0 = e0.normalized() # make e1 perpendicular to e0. c = e1.dot(e0) e1 = (e1 - c * e0).normalized() # Compute e2 as cross product of e0 and e1. e2 = e0.cross(e1) return cls(e0.x, e1.x, e2.x, e0.y, e1.y, e2.y, e0.z, e1.z, e2.z) # pytype: disable=wrong-arg-count # trace-all-classes @classmethod def from_array(cls, array: jnp.ndarray) -> Rot3Array: """Construct Rot3Array Matrix from array of shape. [..., 3, 3].""" unstacked = utils.unstack(array, axis=-2) unstacked = sum([utils.unstack(x, axis=-1) for x in unstacked], []) return cls(*unstacked) def to_array(self) -> jnp.ndarray: """Convert Rot3Array to array of shape [..., 3, 3].""" return jnp.stack( [jnp.stack([self.xx, self.xy, self.xz], axis=-1), jnp.stack([self.yx, self.yy, self.yz], axis=-1), jnp.stack([self.zx, self.zy, self.zz], axis=-1)], axis=-2) @classmethod def from_quaternion(cls, w: jnp.ndarray, x: jnp.ndarray, y: jnp.ndarray, z: jnp.ndarray, normalize: bool = True, epsilon: float = 1e-6) -> Rot3Array: """Construct Rot3Array from components of quaternion.""" if normalize: inv_norm = jax.lax.rsqrt(jnp.maximum(epsilon, w**2 + x**2 + y**2 + z**2)) w *= inv_norm x *= inv_norm y *= inv_norm z *= inv_norm xx = 1 - 2 * (jnp.square(y) + jnp.square(z)) xy = 2 * (x * y - w * z) xz = 2 * (x * z + w * y) yx = 2 * (x * y + w * z) yy = 1 - 2 * (jnp.square(x) + jnp.square(z)) yz = 2 * (y * z - w * x) zx = 2 * (x * z - w * y) zy = 2 * (y * z + w * x) zz = 1 - 2 * (jnp.square(x) + jnp.square(y)) return cls(xx, xy, xz, yx, yy, yz, zx, zy, zz) # pytype: disable=wrong-arg-count # trace-all-classes @classmethod def random_uniform(cls, key, shape, dtype=jnp.float32) -> Rot3Array: """Samples uniform random Rot3Array according to Haar Measure.""" quat_array = jax.random.normal(key, tuple(shape) + (4,), dtype=dtype) quats = utils.unstack(quat_array) return cls.from_quaternion(*quats) def __getstate__(self): return (VERSION, [np.asarray(getattr(self, field)) for field in COMPONENTS]) def __setstate__(self, state): version, state = state del version for i, field in enumerate(COMPONENTS): object.__setattr__(self, field, state[i]) ================================================ FILE: alphafold/model/geometry/struct_of_array.py ================================================ # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Class decorator to represent (nested) struct of arrays.""" import dataclasses import jax def get_item(instance, key): sliced = {} for field in get_array_fields(instance): num_trailing_dims = field.metadata.get('num_trailing_dims', 0) this_key = key if isinstance(key, tuple) and Ellipsis in this_key: this_key += (slice(None),) * num_trailing_dims sliced[field.name] = getattr(instance, field.name)[this_key] return dataclasses.replace(instance, **sliced) @property def get_shape(instance): """Returns Shape for given instance of dataclass.""" first_field = dataclasses.fields(instance)[0] num_trailing_dims = first_field.metadata.get('num_trailing_dims', None) value = getattr(instance, first_field.name) if num_trailing_dims: return value.shape[:-num_trailing_dims] else: return value.shape def get_len(instance): """Returns length for given instance of dataclass.""" shape = instance.shape if shape: return shape[0] else: raise TypeError('len() of unsized object') # Match jax.numpy behavior. @property def get_dtype(instance): """Returns Dtype for given instance of dataclass.""" fields = dataclasses.fields(instance) sets_dtype = [ field.name for field in fields if field.metadata.get('sets_dtype', False) ] if sets_dtype: assert len(sets_dtype) == 1, 'at most field can set dtype' field_value = getattr(instance, sets_dtype[0]) elif instance.same_dtype: field_value = getattr(instance, fields[0].name) else: # Should this be Value Error? raise AttributeError('Trying to access Dtype on Struct of Array without' 'either "same_dtype" or field setting dtype') if hasattr(field_value, 'dtype'): return field_value.dtype else: # Should this be Value Error? raise AttributeError(f'field_value {field_value} does not have dtype') def replace(instance, **kwargs): return dataclasses.replace(instance, **kwargs) def post_init(instance): """Validate instance has same shapes & dtypes.""" array_fields = get_array_fields(instance) arrays = list(get_array_fields(instance, return_values=True).values()) first_field = array_fields[0] # These slightly weird constructions about checking whether the leaves are # actual arrays is since e.g. vmap internally relies on being able to # construct pytree's with object() as leaves, this would break the checking # as such we are only validating the object when the entries in the dataclass # Are arrays or other dataclasses of arrays. try: dtype = instance.dtype except AttributeError: dtype = None if dtype is not None: first_shape = instance.shape for array, field in zip(arrays, array_fields): field_shape = array.shape num_trailing_dims = field.metadata.get('num_trailing_dims', None) if num_trailing_dims: array_shape = array.shape field_shape = array_shape[:-num_trailing_dims] msg = (f'field {field} should have number of trailing dims' ' {num_trailing_dims}') assert len(array_shape) == len(first_shape) + num_trailing_dims, msg else: field_shape = array.shape shape_msg = (f"Stripped Shape {field_shape} of field {field} doesn't " f"match shape {first_shape} of field {first_field}") assert field_shape == first_shape, shape_msg field_dtype = array.dtype allowed_metadata_dtypes = field.metadata.get('allowed_dtypes', []) if allowed_metadata_dtypes: msg = f'Dtype is {field_dtype} but must be in {allowed_metadata_dtypes}' assert field_dtype in allowed_metadata_dtypes, msg if 'dtype' in field.metadata: target_dtype = field.metadata['dtype'] else: target_dtype = dtype msg = f'Dtype is {field_dtype} but must be {target_dtype}' assert field_dtype == target_dtype, msg def flatten(instance): """Flatten Struct of Array instance.""" array_likes = list(get_array_fields(instance, return_values=True).values()) flat_array_likes = [] inner_treedefs = [] num_arrays = [] for array_like in array_likes: flat_array_like, inner_treedef = jax.tree_util.tree_flatten(array_like) inner_treedefs.append(inner_treedef) flat_array_likes += flat_array_like num_arrays.append(len(flat_array_like)) metadata = get_metadata_fields(instance, return_values=True) metadata = type(instance).metadata_cls(**metadata) return flat_array_likes, (inner_treedefs, metadata, num_arrays) def make_metadata_class(cls): metadata_fields = get_fields(cls, lambda x: x.metadata.get('is_metadata', False)) metadata_cls = dataclasses.make_dataclass( cls_name='Meta' + cls.__name__, fields=[(field.name, field.type, field) for field in metadata_fields], frozen=True, eq=True) return metadata_cls def get_fields(cls_or_instance, filterfn, return_values=False): fields = dataclasses.fields(cls_or_instance) fields = [field for field in fields if filterfn(field)] if return_values: return { field.name: getattr(cls_or_instance, field.name) for field in fields } else: return fields def get_array_fields(cls, return_values=False): return get_fields( cls, lambda x: not x.metadata.get('is_metadata', False), return_values=return_values) def get_metadata_fields(cls, return_values=False): return get_fields( cls, lambda x: x.metadata.get('is_metadata', False), return_values=return_values) class StructOfArray: """Class Decorator for Struct Of Arrays.""" def __init__(self, same_dtype=True): self.same_dtype = same_dtype def __call__(self, cls): cls.__array_ufunc__ = None cls.replace = replace cls.same_dtype = self.same_dtype cls.dtype = get_dtype cls.shape = get_shape cls.__len__ = get_len cls.__getitem__ = get_item cls.__post_init__ = post_init new_cls = dataclasses.dataclass(cls, frozen=True, eq=False) # pytype: disable=wrong-keyword-args # pytree claims to require metadata to be hashable, not sure why, # But making derived dataclass that can just hold metadata new_cls.metadata_cls = make_metadata_class(new_cls) def unflatten(aux, data): inner_treedefs, metadata, num_arrays = aux array_fields = [field.name for field in get_array_fields(new_cls)] value_dict = {} array_start = 0 for num_array, inner_treedef, array_field in zip(num_arrays, inner_treedefs, array_fields): value_dict[array_field] = jax.tree_util.tree_unflatten( inner_treedef, data[array_start:array_start + num_array]) array_start += num_array metadata_fields = get_metadata_fields(new_cls) for field in metadata_fields: value_dict[field.name] = getattr(metadata, field.name) return new_cls(**value_dict) jax.tree_util.register_pytree_node( nodetype=new_cls, flatten_func=flatten, unflatten_func=unflatten) return new_cls ================================================ FILE: alphafold/model/geometry/test_utils.py ================================================ # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Shared utils for tests.""" import dataclasses from alphafold.model.geometry import rigid_matrix_vector from alphafold.model.geometry import rotation_matrix from alphafold.model.geometry import vector import jax.numpy as jnp import numpy as np def assert_rotation_matrix_equal(matrix1: rotation_matrix.Rot3Array, matrix2: rotation_matrix.Rot3Array): for field in dataclasses.fields(rotation_matrix.Rot3Array): field = field.name np.testing.assert_array_equal( getattr(matrix1, field), getattr(matrix2, field)) def assert_rotation_matrix_close(mat1: rotation_matrix.Rot3Array, mat2: rotation_matrix.Rot3Array): np.testing.assert_array_almost_equal(mat1.to_array(), mat2.to_array(), 6) def assert_array_equal_to_rotation_matrix(array: jnp.ndarray, matrix: rotation_matrix.Rot3Array): """Check that array and Matrix match.""" np.testing.assert_array_equal(matrix.xx, array[..., 0, 0]) np.testing.assert_array_equal(matrix.xy, array[..., 0, 1]) np.testing.assert_array_equal(matrix.xz, array[..., 0, 2]) np.testing.assert_array_equal(matrix.yx, array[..., 1, 0]) np.testing.assert_array_equal(matrix.yy, array[..., 1, 1]) np.testing.assert_array_equal(matrix.yz, array[..., 1, 2]) np.testing.assert_array_equal(matrix.zx, array[..., 2, 0]) np.testing.assert_array_equal(matrix.zy, array[..., 2, 1]) np.testing.assert_array_equal(matrix.zz, array[..., 2, 2]) def assert_array_close_to_rotation_matrix(array: jnp.ndarray, matrix: rotation_matrix.Rot3Array): np.testing.assert_array_almost_equal(matrix.to_array(), array, 6) def assert_vectors_equal(vec1: vector.Vec3Array, vec2: vector.Vec3Array): np.testing.assert_array_equal(vec1.x, vec2.x) np.testing.assert_array_equal(vec1.y, vec2.y) np.testing.assert_array_equal(vec1.z, vec2.z) def assert_vectors_close(vec1: vector.Vec3Array, vec2: vector.Vec3Array): np.testing.assert_allclose(vec1.x, vec2.x, atol=1e-6, rtol=0.) np.testing.assert_allclose(vec1.y, vec2.y, atol=1e-6, rtol=0.) np.testing.assert_allclose(vec1.z, vec2.z, atol=1e-6, rtol=0.) def assert_array_close_to_vector(array: jnp.ndarray, vec: vector.Vec3Array): np.testing.assert_allclose(vec.to_array(), array, atol=1e-6, rtol=0.) def assert_array_equal_to_vector(array: jnp.ndarray, vec: vector.Vec3Array): np.testing.assert_array_equal(vec.to_array(), array) def assert_rigid_equal_to_rigid(rigid1: rigid_matrix_vector.Rigid3Array, rigid2: rigid_matrix_vector.Rigid3Array): assert_rot_trans_equal_to_rigid(rigid1.rotation, rigid1.translation, rigid2) def assert_rigid_close_to_rigid(rigid1: rigid_matrix_vector.Rigid3Array, rigid2: rigid_matrix_vector.Rigid3Array): assert_rot_trans_close_to_rigid(rigid1.rotation, rigid1.translation, rigid2) def assert_rot_trans_equal_to_rigid(rot: rotation_matrix.Rot3Array, trans: vector.Vec3Array, rigid: rigid_matrix_vector.Rigid3Array): assert_rotation_matrix_equal(rot, rigid.rotation) assert_vectors_equal(trans, rigid.translation) def assert_rot_trans_close_to_rigid(rot: rotation_matrix.Rot3Array, trans: vector.Vec3Array, rigid: rigid_matrix_vector.Rigid3Array): assert_rotation_matrix_close(rot, rigid.rotation) assert_vectors_close(trans, rigid.translation) ================================================ FILE: alphafold/model/geometry/utils.py ================================================ # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Utils for geometry library.""" from typing import List import jax.numpy as jnp def unstack(value: jnp.ndarray, axis: int = -1) -> List[jnp.ndarray]: return [jnp.squeeze(v, axis=axis) for v in jnp.split(value, value.shape[axis], axis=axis)] ================================================ FILE: alphafold/model/geometry/vector.py ================================================ # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Vec3Array Class.""" from __future__ import annotations import dataclasses from typing import Union from alphafold.model.geometry import struct_of_array from alphafold.model.geometry import utils import jax import jax.numpy as jnp import numpy as np Float = Union[float, jnp.ndarray] VERSION = '0.1' @struct_of_array.StructOfArray(same_dtype=True) class Vec3Array: """Vec3Array in 3 dimensional Space implemented as struct of arrays. This is done in order to improve performance and precision. On TPU small matrix multiplications are very suboptimal and will waste large compute ressources, furthermore any matrix multiplication on tpu happen in mixed bfloat16/float32 precision, which is often undesirable when handling physical coordinates. In most cases this will also be faster on cpu's/gpu's since it allows for easier use of vector instructions. """ x: jnp.ndarray = dataclasses.field(metadata={'dtype': jnp.float32}) y: jnp.ndarray z: jnp.ndarray def __post_init__(self): if hasattr(self.x, 'dtype'): assert self.x.dtype == self.y.dtype assert self.x.dtype == self.z.dtype assert all([x == y for x, y in zip(self.x.shape, self.y.shape)]) assert all([x == z for x, z in zip(self.x.shape, self.z.shape)]) def __add__(self, other: Vec3Array) -> Vec3Array: return jax.tree_map(lambda x, y: x + y, self, other) def __sub__(self, other: Vec3Array) -> Vec3Array: return jax.tree_map(lambda x, y: x - y, self, other) def __mul__(self, other: Float) -> Vec3Array: return jax.tree_map(lambda x: x * other, self) def __rmul__(self, other: Float) -> Vec3Array: return self * other def __truediv__(self, other: Float) -> Vec3Array: return jax.tree_map(lambda x: x / other, self) def __neg__(self) -> Vec3Array: return jax.tree_map(lambda x: -x, self) def __pos__(self) -> Vec3Array: return jax.tree_map(lambda x: x, self) def cross(self, other: Vec3Array) -> Vec3Array: """Compute cross product between 'self' and 'other'.""" new_x = self.y * other.z - self.z * other.y new_y = self.z * other.x - self.x * other.z new_z = self.x * other.y - self.y * other.x return Vec3Array(new_x, new_y, new_z) def dot(self, other: Vec3Array) -> Float: """Compute dot product between 'self' and 'other'.""" return self.x * other.x + self.y * other.y + self.z * other.z def norm(self, epsilon: float = 1e-6) -> Float: """Compute Norm of Vec3Array, clipped to epsilon.""" # To avoid NaN on the backward pass, we must use maximum before the sqrt norm2 = self.dot(self) if epsilon: norm2 = jnp.maximum(norm2, epsilon**2) return jnp.sqrt(norm2) def norm2(self): return self.dot(self) def normalized(self, epsilon: float = 1e-6) -> Vec3Array: """Return unit vector with optional clipping.""" return self / self.norm(epsilon) @classmethod def zeros(cls, shape, dtype=jnp.float32): """Return Vec3Array corresponding to zeros of given shape.""" return cls( jnp.zeros(shape, dtype), jnp.zeros(shape, dtype), jnp.zeros(shape, dtype)) # pytype: disable=wrong-arg-count # trace-all-classes def to_array(self) -> jnp.ndarray: return jnp.stack([self.x, self.y, self.z], axis=-1) @classmethod def from_array(cls, array): return cls(*utils.unstack(array)) def __getstate__(self): return (VERSION, [np.asarray(self.x), np.asarray(self.y), np.asarray(self.z)]) def __setstate__(self, state): version, state = state del version for i, letter in enumerate('xyz'): object.__setattr__(self, letter, state[i]) def square_euclidean_distance(vec1: Vec3Array, vec2: Vec3Array, epsilon: float = 1e-6) -> Float: """Computes square of euclidean distance between 'vec1' and 'vec2'. Args: vec1: Vec3Array to compute distance to vec2: Vec3Array to compute distance from, should be broadcast compatible with 'vec1' epsilon: distance is clipped from below to be at least epsilon Returns: Array of square euclidean distances; shape will be result of broadcasting 'vec1' and 'vec2' """ difference = vec1 - vec2 distance = difference.dot(difference) if epsilon: distance = jnp.maximum(distance, epsilon) return distance def dot(vector1: Vec3Array, vector2: Vec3Array) -> Float: return vector1.dot(vector2) def cross(vector1: Vec3Array, vector2: Vec3Array) -> Float: return vector1.cross(vector2) def norm(vector: Vec3Array, epsilon: float = 1e-6) -> Float: return vector.norm(epsilon) def normalized(vector: Vec3Array, epsilon: float = 1e-6) -> Vec3Array: return vector.normalized(epsilon) def euclidean_distance(vec1: Vec3Array, vec2: Vec3Array, epsilon: float = 1e-6) -> Float: """Computes euclidean distance between 'vec1' and 'vec2'. Args: vec1: Vec3Array to compute euclidean distance to vec2: Vec3Array to compute euclidean distance from, should be broadcast compatible with 'vec1' epsilon: distance is clipped from below to be at least epsilon Returns: Array of euclidean distances; shape will be result of broadcasting 'vec1' and 'vec2' """ distance_sq = square_euclidean_distance(vec1, vec2, epsilon**2) distance = jnp.sqrt(distance_sq) return distance def dihedral_angle(a: Vec3Array, b: Vec3Array, c: Vec3Array, d: Vec3Array) -> Float: """Computes torsion angle for a quadruple of points. For points (a, b, c, d), this is the angle between the planes defined by points (a, b, c) and (b, c, d). It is also known as the dihedral angle. Arguments: a: A Vec3Array of coordinates. b: A Vec3Array of coordinates. c: A Vec3Array of coordinates. d: A Vec3Array of coordinates. Returns: A tensor of angles in radians: [-pi, pi]. """ v1 = a - b v2 = b - c v3 = d - c c1 = v1.cross(v2) c2 = v3.cross(v2) c3 = c2.cross(c1) v2_mag = v2.norm() return jnp.arctan2(c3.dot(v2), v2_mag * c1.dot(c2)) def random_gaussian_vector(shape, key, dtype=jnp.float32): vec_array = jax.random.normal(key, shape + (3,), dtype) return Vec3Array.from_array(vec_array) ================================================ FILE: alphafold/model/layer_stack.py ================================================ # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Function to stack repeats of a layer function without shared parameters.""" import collections import contextlib import functools import inspect from typing import Any, Callable, Optional, Tuple, Union import haiku as hk import jax import jax.numpy as jnp LayerStackCarry = collections.namedtuple('LayerStackCarry', ['x', 'rng']) LayerStackScanned = collections.namedtuple('LayerStackScanned', ['i', 'args_ys']) # WrappedFn should take in arbitrarily nested `jnp.ndarray`, and return the # exact same type. We cannot express this with `typing`. So we just use it # to inform the user. In reality, the typing below will accept anything. NestedArray = Any WrappedFn = Callable[..., Union[NestedArray, Tuple[NestedArray]]] def _check_no_varargs(f): if list(inspect.signature( f).parameters.values())[0].kind == inspect.Parameter.VAR_POSITIONAL: raise ValueError( 'The function `f` should not have any `varargs` (that is *args) ' 'argument. Instead, it should only use explicit positional' 'arguments.') @contextlib.contextmanager def nullcontext(): yield def maybe_with_rng(key): if key is not None: return hk.with_rng(key) else: return nullcontext() def maybe_fold_in(key, data): if key is not None: return jax.random.fold_in(key, data) else: return None class _LayerStack(hk.Module): """Module to compose parameterized functions, implemented as a scan.""" def __init__(self, count: int, unroll: int, name: Optional[str] = None): """Iterate a function `f` `count` times, with non-shared parameters.""" super().__init__(name=name) self._count = count self._unroll = unroll def __call__(self, x, *args_ys): count = self._count if hk.running_init(): # At initialization time, we run just one layer but add an extra first # dimension to every initialized tensor, making sure to use different # random keys for different slices. def creator(next_creator, shape, dtype, init, context): del context def multi_init(shape, dtype): assert shape[0] == count key = hk.maybe_next_rng_key() def rng_context_init(slice_idx): slice_key = maybe_fold_in(key, slice_idx) with maybe_with_rng(slice_key): return init(shape[1:], dtype) return jax.vmap(rng_context_init)(jnp.arange(count)) return next_creator((count,) + tuple(shape), dtype, multi_init) def getter(next_getter, value, context): trailing_dims = len(context.original_shape) + 1 sliced_value = jax.lax.index_in_dim( value, index=0, axis=value.ndim - trailing_dims, keepdims=False) return next_getter(sliced_value) with hk.experimental.custom_creator( creator), hk.experimental.custom_getter(getter): if len(args_ys) == 1 and args_ys[0] is None: args0 = (None,) else: args0 = [ jax.lax.dynamic_index_in_dim(ys, 0, keepdims=False) for ys in args_ys ] x, z = self._call_wrapped(x, *args0) if z is None: return x, z # Broadcast state to hold each layer state. def broadcast_state(layer_state): return jnp.broadcast_to( layer_state, [count,] + list(layer_state.shape)) zs = jax.tree_util.tree_map(broadcast_state, z) return x, zs else: # Use scan during apply, threading through random seed so that it's # unique for each layer. def layer(carry: LayerStackCarry, scanned: LayerStackScanned): rng = carry.rng def getter(next_getter, value, context): # Getter slices the full param at the current loop index. trailing_dims = len(context.original_shape) + 1 assert value.shape[value.ndim - trailing_dims] == count, ( f'Attempting to use a parameter stack of size ' f'{value.shape[value.ndim - trailing_dims]} for a LayerStack of ' f'size {count}.') sliced_value = jax.lax.dynamic_index_in_dim( value, scanned.i, axis=value.ndim - trailing_dims, keepdims=False) return next_getter(sliced_value) with hk.experimental.custom_getter(getter): if rng is None: out_x, z = self._call_wrapped(carry.x, *scanned.args_ys) else: rng, rng_ = jax.random.split(rng) with hk.with_rng(rng_): out_x, z = self._call_wrapped(carry.x, *scanned.args_ys) return LayerStackCarry(x=out_x, rng=rng), z carry = LayerStackCarry(x=x, rng=hk.maybe_next_rng_key()) scanned = LayerStackScanned(i=jnp.arange(count, dtype=jnp.int32), args_ys=args_ys) carry, zs = hk.scan( layer, carry, scanned, length=count, unroll=self._unroll) return carry.x, zs def _call_wrapped(self, x: jnp.ndarray, *args, ) -> Tuple[jnp.ndarray, Optional[jnp.ndarray]]: raise NotImplementedError() class _LayerStackNoState(_LayerStack): """_LayerStack impl with no per-layer state provided to the function.""" def __init__(self, f: WrappedFn, count: int, unroll: int, name: Optional[str] = None): super().__init__(count=count, unroll=unroll, name=name) _check_no_varargs(f) self._f = f @hk.transparent def _call_wrapped(self, args, y): del y ret = self._f(*args) if len(args) == 1: # If the function takes a single argument, the wrapped function receives # a tuple of length 1, and therefore it must return a tuple of length 1. ret = (ret,) return ret, None class _LayerStackWithState(_LayerStack): """_LayerStack impl with per-layer state provided to the function.""" def __init__(self, f: WrappedFn, count: int, unroll: int, name: Optional[str] = None): super().__init__(count=count, unroll=unroll, name=name) self._f = f @hk.transparent def _call_wrapped(self, x, *args): return self._f(x, *args) def layer_stack(num_layers: int, with_state=False, unroll: int = 1, name: Optional[str] = None): """Utility to wrap a Haiku function and recursively apply it to an input. A function is valid if it uses only explicit position parameters, and its return type matches its input type. The position parameters can be arbitrarily nested structures with `jnp.ndarray` at the leaf nodes. Note that kwargs are not supported, neither are functions with variable number of parameters (specified by `*args`). If `with_state=False` then the new, wrapped function can be understood as performing the following: ``` for i in range(num_layers): x = f(x) return x ``` And if `with_state=True`, assuming `f` takes two arguments on top of `x`: ``` for i in range(num_layers): x, zs[i] = f(x, ys_0[i], ys_1[i]) return x, zs ``` The code using `layer_stack` for the above function would be: ``` def f(x, y_0, y_1): ... return new_x, z x, zs = layer_stack.layer_stack(num_layers, with_state=True)(f)(x, ys_0, ys_1) ``` Crucially, any parameters created inside `f` will not be shared across iterations. Args: num_layers: The number of times to iterate the wrapped function. with_state: Whether or not to pass per-layer state to the wrapped function. unroll: the unroll used by `scan`. name: Name of the Haiku context. Returns: Callable that will produce a layer stack when called with a valid function. """ def iterate(f): if with_state: @functools.wraps(f) def wrapped(x, *args): for ys in args: assert ys.shape[0] == num_layers return _LayerStackWithState( f, num_layers, unroll=unroll, name=name)(x, *args) else: _check_no_varargs(f) @functools.wraps(f) def wrapped(*args): ret = _LayerStackNoState( f, num_layers, unroll=unroll, name=name)(args, None)[0] if len(args) == 1: # If the function takes a single argument, we must also return a # single value, and not a tuple of length 1. ret = ret[0] return ret return wrapped return iterate ================================================ FILE: alphafold/model/layer_stack_test.py ================================================ # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Tests for layer_stack.""" import functools from absl.testing import absltest from absl.testing import parameterized from alphafold.model import layer_stack import haiku as hk import jax import jax.numpy as jnp import numpy as np import scipy.stats # Suffixes applied by Haiku for repeated module names. suffixes = [''] + [f'_{i}' for i in range(1, 100)] def _slice_layers_params(layers_params): sliced_layers_params = {} for k, v in layers_params.items(): for inner_k in v: for var_slice, suffix in zip(v[inner_k], suffixes): k_new = k.split('/')[-1] + suffix if k_new not in sliced_layers_params: sliced_layers_params[k_new] = {} sliced_layers_params[k_new][inner_k] = var_slice return sliced_layers_params class LayerStackTest(parameterized.TestCase): @parameterized.parameters([1, 2, 4]) def test_layer_stack(self, unroll): """Compare layer_stack to the equivalent unrolled stack. Tests that the layer_stack application of a Haiku layer function is equivalent to repeatedly applying the layer function in an unrolled loop. Args: unroll: Number of unrolled layers. """ num_layers = 20 def inner_fn(x): x += hk.Linear(100, name='linear1')(x) x += hk.Linear(100, name='linear2')(x) return x def outer_fn_unrolled(x): for _ in range(num_layers): x = inner_fn(x) return x def outer_fn_layer_stack(x): stack = layer_stack.layer_stack(num_layers, unroll=unroll)(inner_fn) return stack(x) unrolled_fn = hk.transform(outer_fn_unrolled) layer_stack_fn = hk.transform(outer_fn_layer_stack) x = jax.random.uniform(jax.random.PRNGKey(0), [10, 256, 100]) rng_init = jax.random.PRNGKey(42) params = layer_stack_fn.init(rng_init, x) sliced_params = _slice_layers_params(params) unrolled_pred = unrolled_fn.apply(sliced_params, None, x) layer_stack_pred = layer_stack_fn.apply(params, None, x) np.testing.assert_allclose(unrolled_pred, layer_stack_pred) def test_layer_stack_multi_args(self): """Compare layer_stack to the equivalent unrolled stack. Similar to `test_layer_stack`, but use a function that takes more than one argument. """ num_layers = 20 def inner_fn(x, y): x_out = x + hk.Linear(100, name='linear1')(y) y_out = y + hk.Linear(100, name='linear2')(x) return x_out, y_out def outer_fn_unrolled(x, y): for _ in range(num_layers): x, y = inner_fn(x, y) return x, y def outer_fn_layer_stack(x, y): stack = layer_stack.layer_stack(num_layers)(inner_fn) return stack(x, y) unrolled_fn = hk.transform(outer_fn_unrolled) layer_stack_fn = hk.transform(outer_fn_layer_stack) x = jax.random.uniform(jax.random.PRNGKey(0), [10, 256, 100]) y = jax.random.uniform(jax.random.PRNGKey(1), [10, 256, 100]) rng_init = jax.random.PRNGKey(42) params = layer_stack_fn.init(rng_init, x, y) sliced_params = _slice_layers_params(params) unrolled_x, unrolled_y = unrolled_fn.apply(sliced_params, None, x, y) layer_stack_x, layer_stack_y = layer_stack_fn.apply(params, None, x, y) np.testing.assert_allclose(unrolled_x, layer_stack_x) np.testing.assert_allclose(unrolled_y, layer_stack_y) def test_layer_stack_no_varargs(self): """Test an error is raised when using a function with varargs.""" class VarArgsModule(hk.Module): """When used, this module should cause layer_stack to raise an Error.""" def __call__(self, *args): return args class NoVarArgsModule(hk.Module): """This module should be fine to use with layer_stack.""" def __call__(self, x): return x def build_and_init_stack(module_class): def stack_fn(x): module = module_class() return layer_stack.layer_stack(1)(module)(x) stack = hk.without_apply_rng(hk.transform(stack_fn)) stack.init(jax.random.PRNGKey(1729), jnp.ones([5])) build_and_init_stack(NoVarArgsModule) with self.assertRaisesRegex( ValueError, 'The function `f` should not have any `varargs`'): build_and_init_stack(VarArgsModule) @parameterized.parameters([1, 2, 4]) def test_layer_stack_grads(self, unroll): """Compare layer_stack gradients to the equivalent unrolled stack. Tests that the layer_stack application of a Haiku layer function is equivalent to repeatedly applying the layer function in an unrolled loop. Args: unroll: Number of unrolled layers. """ num_layers = 20 def inner_fn(x): x += hk.Linear(100, name='linear1')(x) x += hk.Linear(100, name='linear2')(x) return x def outer_fn_unrolled(x): for _ in range(num_layers): x = inner_fn(x) return x def outer_fn_layer_stack(x): stack = layer_stack.layer_stack(num_layers, unroll=unroll)(inner_fn) return stack(x) unrolled_fn = hk.transform(outer_fn_unrolled) layer_stack_fn = hk.transform(outer_fn_layer_stack) x = jax.random.uniform(jax.random.PRNGKey(0), [10, 256, 100]) rng_init = jax.random.PRNGKey(42) params = layer_stack_fn.init(rng_init, x) sliced_params = _slice_layers_params(params) unrolled_grad = jax.grad( lambda p, x: jnp.mean(unrolled_fn.apply(p, None, x)))(sliced_params, x) layer_stack_grad = jax.grad( lambda p, x: jnp.mean(layer_stack_fn.apply(p, None, x)))(params, x) assert_fn = functools.partial( np.testing.assert_allclose, atol=1e-4, rtol=1e-4) jax.tree_map(assert_fn, unrolled_grad, _slice_layers_params(layer_stack_grad)) def test_random(self): """Random numbers should be handled correctly.""" n = 100 @hk.transform @layer_stack.layer_stack(n) def add_random(x): x = x + jax.random.normal(hk.next_rng_key()) return x # Evaluate a bunch of times key, *keys = jax.random.split(jax.random.PRNGKey(7), 1024 + 1) params = add_random.init(key, 0.) apply_fn = jax.jit(add_random.apply) values = [apply_fn(params, key, 0.) for key in keys] # Should be roughly N(0, sqrt(n)) cdf = scipy.stats.norm(scale=np.sqrt(n)).cdf _, p = scipy.stats.kstest(values, cdf) self.assertLess(0.3, p) def test_threading(self): """Test @layer_stack when the function gets per-layer state.""" n = 5 @layer_stack.layer_stack(n, with_state=True) def f(x, y): x = x + y * jax.nn.one_hot(y, len(x)) / 10 return x, 2 * y @hk.without_apply_rng @hk.transform def g(x, ys): x, zs = f(x, ys) # Check here to catch issues at init time self.assertEqual(zs.shape, (n,)) return x, zs rng = jax.random.PRNGKey(7) x = np.zeros(n) ys = np.arange(n).astype(np.float32) params = g.init(rng, x, ys) x, zs = g.apply(params, x, ys) self.assertTrue(np.allclose(x, [0, .1, .2, .3, .4])) self.assertTrue(np.all(zs == 2 * ys)) def test_nested_stacks(self): def stack_fn(x): def layer_fn(x): return hk.Linear(100)(x) outer_fn = layer_stack.layer_stack(10)(layer_fn) layer_outer = layer_stack.layer_stack(20)(outer_fn) return layer_outer(x) hk_mod = hk.transform(stack_fn) apply_rng, init_rng = jax.random.split(jax.random.PRNGKey(0)) params = hk_mod.init(init_rng, jnp.zeros([10, 100])) hk_mod.apply(params, apply_rng, jnp.zeros([10, 100])) p, = params.values() assert p['w'].shape == (10, 20, 100, 100) assert p['b'].shape == (10, 20, 100) def test_with_state_multi_args(self): """Test layer_stack with state with multiple arguments.""" width = 4 batch_size = 5 stack_height = 3 def f_with_multi_args(x, a, b): return hk.Linear( width, w_init=hk.initializers.Constant( jnp.eye(width)))(x) * a + b, None @hk.without_apply_rng @hk.transform def hk_fn(x): return layer_stack.layer_stack( stack_height, with_state=True)(f_with_multi_args)(x, jnp.full([stack_height], 2.), jnp.ones([stack_height])) x = jnp.zeros([batch_size, width]) key_seq = hk.PRNGSequence(19) params = hk_fn.init(next(key_seq), x) output, z = hk_fn.apply(params, x) self.assertIsNone(z) self.assertEqual(output.shape, (batch_size, width)) np.testing.assert_equal(output, np.full([batch_size, width], 7.)) def test_with_container_state(self): width = 2 batch_size = 2 stack_height = 3 def f_with_container_state(x): hk_layer = hk.Linear( width, w_init=hk.initializers.Constant(jnp.eye(width))) layer_output = hk_layer(x) layer_state = { 'raw_output': layer_output, 'output_projection': jnp.sum(layer_output) } return layer_output + jnp.ones_like(layer_output), layer_state @hk.without_apply_rng @hk.transform def hk_fn(x): return layer_stack.layer_stack( stack_height, with_state=True)(f_with_container_state)(x) x = jnp.zeros([batch_size, width]) key_seq = hk.PRNGSequence(19) params = hk_fn.init(next(key_seq), x) output, z = hk_fn.apply(params, x) self.assertEqual(z['raw_output'].shape, (stack_height, batch_size, width)) self.assertEqual(output.shape, (batch_size, width)) self.assertEqual(z['output_projection'].shape, (stack_height,)) np.testing.assert_equal(np.sum(z['output_projection']), np.array(12.)) np.testing.assert_equal( np.all(z['raw_output'] == np.array([0., 1., 2.])[..., None, None]), np.array(True)) if __name__ == '__main__': absltest.main() ================================================ FILE: alphafold/model/lddt.py ================================================ # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """lDDT protein distance score.""" import jax.numpy as jnp def lddt(predicted_points, true_points, true_points_mask, cutoff=15., per_residue=False): """Measure (approximate) lDDT for a batch of coordinates. lDDT reference: Mariani, V., Biasini, M., Barbato, A. & Schwede, T. lDDT: A local superposition-free score for comparing protein structures and models using distance difference tests. Bioinformatics 29, 2722–2728 (2013). lDDT is a measure of the difference between the true distance matrix and the distance matrix of the predicted points. The difference is computed only on points closer than cutoff *in the true structure*. This function does not compute the exact lDDT value that the original paper describes because it does not include terms for physical feasibility (e.g. bond length violations). Therefore this is only an approximate lDDT score. Args: predicted_points: (batch, length, 3) array of predicted 3D points true_points: (batch, length, 3) array of true 3D points true_points_mask: (batch, length, 1) binary-valued float array. This mask should be 1 for points that exist in the true points. cutoff: Maximum distance for a pair of points to be included per_residue: If true, return score for each residue. Note that the overall lDDT is not exactly the mean of the per_residue lDDT's because some residues have more contacts than others. Returns: An (approximate, see above) lDDT score in the range 0-1. """ assert len(predicted_points.shape) == 3 assert predicted_points.shape[-1] == 3 assert true_points_mask.shape[-1] == 1 assert len(true_points_mask.shape) == 3 # Compute true and predicted distance matrices. dmat_true = jnp.sqrt(1e-10 + jnp.sum( (true_points[:, :, None] - true_points[:, None, :])**2, axis=-1)) dmat_predicted = jnp.sqrt(1e-10 + jnp.sum( (predicted_points[:, :, None] - predicted_points[:, None, :])**2, axis=-1)) dists_to_score = ( (dmat_true < cutoff).astype(jnp.float32) * true_points_mask * jnp.transpose(true_points_mask, [0, 2, 1]) * (1. - jnp.eye(dmat_true.shape[1])) # Exclude self-interaction. ) # Shift unscored distances to be far away. dist_l1 = jnp.abs(dmat_true - dmat_predicted) # True lDDT uses a number of fixed bins. # We ignore the physical plausibility correction to lDDT, though. score = 0.25 * ((dist_l1 < 0.5).astype(jnp.float32) + (dist_l1 < 1.0).astype(jnp.float32) + (dist_l1 < 2.0).astype(jnp.float32) + (dist_l1 < 4.0).astype(jnp.float32)) # Normalize over the appropriate axes. reduce_axes = (-1,) if per_residue else (-2, -1) norm = 1. / (1e-10 + jnp.sum(dists_to_score, axis=reduce_axes)) score = norm * (1e-10 + jnp.sum(dists_to_score * score, axis=reduce_axes)) return score ================================================ FILE: alphafold/model/lddt_test.py ================================================ # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Tests for lddt.""" from absl.testing import absltest from absl.testing import parameterized from alphafold.model import lddt import numpy as np class LddtTest(parameterized.TestCase, absltest.TestCase): @parameterized.named_parameters( ('same', [[0, 0, 0], [5, 0, 0], [10, 0, 0]], [[0, 0, 0], [5, 0, 0], [10, 0, 0]], [1, 1, 1]), ('all_shifted', [[0, 0, 0], [5, 0, 0], [10, 0, 0]], [[-1, 0, 0], [4, 0, 0], [9, 0, 0]], [1, 1, 1]), ('all_rotated', [[0, 0, 0], [5, 0, 0], [10, 0, 0]], [[0, 0, 0], [0, 5, 0], [0, 10, 0]], [1, 1, 1]), ('half_a_dist', [[0, 0, 0], [5, 0, 0]], [[0, 0, 0], [5.5-1e-5, 0, 0]], [1, 1]), ('one_a_dist', [[0, 0, 0], [5, 0, 0]], [[0, 0, 0], [6-1e-5, 0, 0]], [0.75, 0.75]), ('two_a_dist', [[0, 0, 0], [5, 0, 0]], [[0, 0, 0], [7-1e-5, 0, 0]], [0.5, 0.5]), ('four_a_dist', [[0, 0, 0], [5, 0, 0]], [[0, 0, 0], [9-1e-5, 0, 0]], [0.25, 0.25],), ('five_a_dist', [[0, 0, 0], [16-1e-5, 0, 0]], [[0, 0, 0], [11, 0, 0]], [0, 0]), ('no_pairs', [[0, 0, 0], [20, 0, 0]], [[0, 0, 0], [25-1e-5, 0, 0]], [1, 1]), ) def test_lddt( self, predicted_pos, true_pos, exp_lddt): predicted_pos = np.array([predicted_pos], dtype=np.float32) true_points_mask = np.array([[[1]] * len(true_pos)], dtype=np.float32) true_pos = np.array([true_pos], dtype=np.float32) cutoff = 15.0 per_residue = True result = lddt.lddt( predicted_pos, true_pos, true_points_mask, cutoff, per_residue) np.testing.assert_almost_equal(result, [exp_lddt], decimal=4) if __name__ == '__main__': absltest.main() ================================================ FILE: alphafold/model/mapping.py ================================================ # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Specialized mapping functions.""" import functools import inspect from typing import Any, Callable, Optional, Sequence, Union import haiku as hk import jax import jax.numpy as jnp PYTREE = Any PYTREE_JAX_ARRAY = Any partial = functools.partial PROXY = object() def _maybe_slice(array, i, slice_size, axis): if axis is PROXY: return array else: return jax.lax.dynamic_slice_in_dim( array, i, slice_size=slice_size, axis=axis) def _maybe_get_size(array, axis): if axis == PROXY: return -1 else: return array.shape[axis] def _expand_axes(axes, values, name='sharded_apply'): values_tree_def = jax.tree_util.tree_flatten(values)[1] flat_axes = jax.api_util.flatten_axes(name, values_tree_def, axes) # Replace None's with PROXY flat_axes = [PROXY if x is None else x for x in flat_axes] return jax.tree_util.tree_unflatten(values_tree_def, flat_axes) def sharded_map( fun: Callable[..., PYTREE_JAX_ARRAY], shard_size: Union[int, None] = 1, in_axes: Union[int, PYTREE] = 0, out_axes: Union[int, PYTREE] = 0) -> Callable[..., PYTREE_JAX_ARRAY]: """Sharded vmap. Maps `fun` over axes, in a way similar to vmap, but does so in shards of `shard_size`. This allows a smooth trade-off between memory usage (as in a plain map) vs higher throughput (as in a vmap). Args: fun: Function to apply smap transform to. shard_size: Integer denoting shard size. in_axes: Either integer or pytree describing which axis to map over for each input to `fun`, None denotes broadcasting. out_axes: integer or pytree denoting to what axis in the output the mapped over axis maps. Returns: function with smap applied. """ if 'split_rng' in inspect.signature(hk.vmap).parameters: vmapped_fun = hk.vmap(fun, in_axes, out_axes, split_rng=False) else: # TODO(tomhennigan): Remove this when older versions of Haiku aren't used. vmapped_fun = hk.vmap(fun, in_axes, out_axes) return sharded_apply(vmapped_fun, shard_size, in_axes, out_axes) def sharded_apply( fun: Callable[..., PYTREE_JAX_ARRAY], # pylint: disable=g-bare-generic shard_size: Union[int, None] = 1, in_axes: Union[int, PYTREE] = 0, out_axes: Union[int, PYTREE] = 0, new_out_axes: bool = False) -> Callable[..., PYTREE_JAX_ARRAY]: """Sharded apply. Applies `fun` over shards to axes, in a way similar to vmap, but does so in shards of `shard_size`. Shards are stacked after. This allows a smooth trade-off between memory usage (as in a plain map) vs higher throughput (as in a vmap). Args: fun: Function to apply smap transform to. shard_size: Integer denoting shard size. in_axes: Either integer or pytree describing which axis to map over for each input to `fun`, None denotes broadcasting. out_axes: integer or pytree denoting to what axis in the output the mapped over axis maps. new_out_axes: whether to stack outputs on new axes. This assumes that the output sizes for each shard (including the possible remainder shard) are the same. Returns: function with smap applied. """ docstr = ('Mapped version of {fun}. Takes similar arguments to {fun} ' 'but with additional array axes over which {fun} is mapped.') if new_out_axes: raise NotImplementedError('New output axes not yet implemented.') # shard size None denotes no sharding if shard_size is None: return fun @jax.util.wraps(fun, docstr=docstr) def mapped_fn(*args): # Expand in axes and Determine Loop range in_axes_ = _expand_axes(in_axes, args) in_sizes = jax.tree_map(_maybe_get_size, args, in_axes_) flat_sizes = jax.tree_util.tree_flatten(in_sizes)[0] in_size = max(flat_sizes) assert all(i in {in_size, -1} for i in flat_sizes) num_extra_shards = (in_size - 1) // shard_size # Fix Up if necessary last_shard_size = in_size % shard_size last_shard_size = shard_size if last_shard_size == 0 else last_shard_size def apply_fun_to_slice(slice_start, slice_size): input_slice = jax.tree_map( lambda array, axis: _maybe_slice(array, slice_start, slice_size, axis ), args, in_axes_) return fun(*input_slice) remainder_shape_dtype = hk.eval_shape( partial(apply_fun_to_slice, 0, last_shard_size)) out_dtypes = jax.tree_map(lambda x: x.dtype, remainder_shape_dtype) out_shapes = jax.tree_map(lambda x: x.shape, remainder_shape_dtype) out_axes_ = _expand_axes(out_axes, remainder_shape_dtype) if num_extra_shards > 0: regular_shard_shape_dtype = hk.eval_shape( partial(apply_fun_to_slice, 0, shard_size)) shard_shapes = jax.tree_map(lambda x: x.shape, regular_shard_shape_dtype) def make_output_shape(axis, shard_shape, remainder_shape): return shard_shape[:axis] + ( shard_shape[axis] * num_extra_shards + remainder_shape[axis],) + shard_shape[axis + 1:] out_shapes = jax.tree_map(make_output_shape, out_axes_, shard_shapes, out_shapes) # Calls dynamic Update slice with different argument order # This is here since tree_map only works with positional arguments def dynamic_update_slice_in_dim(full_array, update, axis, i): return jax.lax.dynamic_update_slice_in_dim(full_array, update, i, axis) def compute_shard(outputs, slice_start, slice_size): slice_out = apply_fun_to_slice(slice_start, slice_size) update_slice = partial( dynamic_update_slice_in_dim, i=slice_start) return jax.tree_map(update_slice, outputs, slice_out, out_axes_) def scan_iteration(outputs, i): new_outputs = compute_shard(outputs, i, shard_size) return new_outputs, () slice_starts = jnp.arange(0, in_size - shard_size + 1, shard_size) def allocate_buffer(dtype, shape): return jnp.zeros(shape, dtype=dtype) outputs = jax.tree_map(allocate_buffer, out_dtypes, out_shapes) if slice_starts.shape[0] > 0: outputs, _ = hk.scan(scan_iteration, outputs, slice_starts) if last_shard_size != shard_size: remainder_start = in_size - last_shard_size outputs = compute_shard(outputs, remainder_start, last_shard_size) return outputs return mapped_fn def inference_subbatch( module: Callable[..., PYTREE_JAX_ARRAY], subbatch_size: int, batched_args: Sequence[PYTREE_JAX_ARRAY], nonbatched_args: Sequence[PYTREE_JAX_ARRAY], low_memory: bool = True, input_subbatch_dim: int = 0, output_subbatch_dim: Optional[int] = None) -> PYTREE_JAX_ARRAY: """Run through subbatches (like batch apply but with split and concat).""" assert len(batched_args) > 0 # pylint: disable=g-explicit-length-test if not low_memory: args = list(batched_args) + list(nonbatched_args) return module(*args) if output_subbatch_dim is None: output_subbatch_dim = input_subbatch_dim def run_module(*batched_args): args = list(batched_args) + list(nonbatched_args) return module(*args) sharded_module = sharded_apply(run_module, shard_size=subbatch_size, in_axes=input_subbatch_dim, out_axes=output_subbatch_dim) return sharded_module(*batched_args) ================================================ FILE: alphafold/model/model.py ================================================ # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Code for constructing the model.""" from typing import Any, Mapping, Optional, Union from absl import logging from alphafold.common import confidence from alphafold.model import features from alphafold.model import modules from alphafold.model import modules_multimer import haiku as hk import jax import ml_collections import numpy as np import tensorflow.compat.v1 as tf import tree def get_confidence_metrics( prediction_result: Mapping[str, Any], multimer_mode: bool) -> Mapping[str, Any]: """Post processes prediction_result to get confidence metrics.""" confidence_metrics = {} confidence_metrics['plddt'] = confidence.compute_plddt( prediction_result['predicted_lddt']['logits']) if 'predicted_aligned_error' in prediction_result: confidence_metrics.update(confidence.compute_predicted_aligned_error( logits=prediction_result['predicted_aligned_error']['logits'], breaks=prediction_result['predicted_aligned_error']['breaks'])) confidence_metrics['ptm'] = confidence.predicted_tm_score( logits=prediction_result['predicted_aligned_error']['logits'], breaks=prediction_result['predicted_aligned_error']['breaks'], asym_id=None) if multimer_mode: # Compute the ipTM only for the multimer model. confidence_metrics['iptm'] = confidence.predicted_tm_score( logits=prediction_result['predicted_aligned_error']['logits'], breaks=prediction_result['predicted_aligned_error']['breaks'], asym_id=prediction_result['predicted_aligned_error']['asym_id'], interface=True) confidence_metrics['ranking_confidence'] = ( 0.8 * confidence_metrics['iptm'] + 0.2 * confidence_metrics['ptm']) if not multimer_mode: # Monomer models use mean pLDDT for model ranking. confidence_metrics['ranking_confidence'] = np.mean( confidence_metrics['plddt']) return confidence_metrics class RunModel: """Container for JAX model.""" def __init__(self, config: ml_collections.ConfigDict, params: Optional[Mapping[str, Mapping[str, np.ndarray]]] = None): self.config = config self.params = params self.multimer_mode = config.model.global_config.multimer_mode if self.multimer_mode: def _forward_fn(batch): model = modules_multimer.AlphaFold(self.config.model) return model( batch, is_training=False) else: def _forward_fn(batch): model = modules.AlphaFold(self.config.model) return model( batch, is_training=False, compute_loss=False, ensemble_representations=True) self.apply = jax.jit(hk.transform(_forward_fn).apply) self.init = jax.jit(hk.transform(_forward_fn).init) def init_params(self, feat: features.FeatureDict, random_seed: int = 0): """Initializes the model parameters. If none were provided when this class was instantiated then the parameters are randomly initialized. Args: feat: A dictionary of NumPy feature arrays as output by RunModel.process_features. random_seed: A random seed to use to initialize the parameters if none were set when this class was initialized. """ if not self.params: # Init params randomly. rng = jax.random.PRNGKey(random_seed) self.params = hk.data_structures.to_mutable_dict( self.init(rng, feat)) logging.warning('Initialized parameters randomly') def process_features( self, raw_features: Union[tf.train.Example, features.FeatureDict], random_seed: int) -> features.FeatureDict: """Processes features to prepare for feeding them into the model. Args: raw_features: The output of the data pipeline either as a dict of NumPy arrays or as a tf.train.Example. random_seed: The random seed to use when processing the features. Returns: A dict of NumPy feature arrays suitable for feeding into the model. """ if self.multimer_mode: return raw_features # Single-chain mode. if isinstance(raw_features, dict): return features.np_example_to_features( np_example=raw_features, config=self.config, random_seed=random_seed) else: return features.tf_example_to_features( tf_example=raw_features, config=self.config, random_seed=random_seed) def eval_shape(self, feat: features.FeatureDict) -> jax.ShapeDtypeStruct: self.init_params(feat) logging.info('Running eval_shape with shape(feat) = %s', tree.map_structure(lambda x: x.shape, feat)) shape = jax.eval_shape(self.apply, self.params, jax.random.PRNGKey(0), feat) logging.info('Output shape was %s', shape) return shape def predict(self, feat: features.FeatureDict, random_seed: int, ) -> Mapping[str, Any]: """Makes a prediction by inferencing the model on the provided features. Args: feat: A dictionary of NumPy feature arrays as output by RunModel.process_features. random_seed: The random seed to use when running the model. In the multimer model this controls the MSA sampling. Returns: A dictionary of model outputs. """ self.init_params(feat) logging.info('Running predict with shape(feat) = %s', tree.map_structure(lambda x: x.shape, feat)) result = self.apply(self.params, jax.random.PRNGKey(random_seed), feat) # This block is to ensure benchmark timings are accurate. Some blocking is # already happening when computing get_confidence_metrics, and this ensures # all outputs are blocked on. jax.tree_map(lambda x: x.block_until_ready(), result) result.update( get_confidence_metrics(result, multimer_mode=self.multimer_mode)) logging.info('Output shape was %s', tree.map_structure(lambda x: x.shape, result)) return result ================================================ FILE: alphafold/model/modules.py ================================================ # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Modules and code used in the core part of AlphaFold. The structure generation code is in 'folding.py'. """ import functools from alphafold.common import residue_constants from alphafold.model import all_atom from alphafold.model import common_modules from alphafold.model import folding from alphafold.model import layer_stack from alphafold.model import lddt from alphafold.model import mapping from alphafold.model import prng from alphafold.model import quat_affine from alphafold.model import utils import haiku as hk import jax import jax.numpy as jnp def softmax_cross_entropy(logits, labels): """Computes softmax cross entropy given logits and one-hot class labels.""" loss = -jnp.sum(labels * jax.nn.log_softmax(logits), axis=-1) return jnp.asarray(loss) def sigmoid_cross_entropy(logits, labels): """Computes sigmoid cross entropy given logits and multiple class labels.""" log_p = jax.nn.log_sigmoid(logits) # log(1 - sigmoid(x)) = log_sigmoid(-x), the latter is more numerically stable log_not_p = jax.nn.log_sigmoid(-logits) loss = -labels * log_p - (1. - labels) * log_not_p return jnp.asarray(loss) def apply_dropout(*, tensor, safe_key, rate, is_training, broadcast_dim=None): """Applies dropout to a tensor.""" if is_training and rate != 0.0: shape = list(tensor.shape) if broadcast_dim is not None: shape[broadcast_dim] = 1 keep_rate = 1.0 - rate keep = jax.random.bernoulli(safe_key.get(), keep_rate, shape=shape) return keep * tensor / keep_rate else: return tensor def dropout_wrapper(module, input_act, mask, safe_key, global_config, output_act=None, is_training=True, **kwargs): """Applies module + dropout + residual update.""" if output_act is None: output_act = input_act gc = global_config residual = module(input_act, mask, is_training=is_training, **kwargs) dropout_rate = 0.0 if gc.deterministic else module.config.dropout_rate # Will override `is_training` to True if want to use dropout. should_apply_dropout = True if gc.eval_dropout else is_training if module.config.shared_dropout: if module.config.orientation == 'per_row': broadcast_dim = 0 else: broadcast_dim = 1 else: broadcast_dim = None residual = apply_dropout(tensor=residual, safe_key=safe_key, rate=dropout_rate, is_training=should_apply_dropout, broadcast_dim=broadcast_dim) new_act = output_act + residual return new_act def create_extra_msa_feature(batch): """Expand extra_msa into 1hot and concat with other extra msa features. We do this as late as possible as the one_hot extra msa can be very large. Arguments: batch: a dictionary with the following keys: * 'extra_msa': [N_extra_seq, N_res] MSA that wasn't selected as a cluster centre. Note, that this is not one-hot encoded. * 'extra_has_deletion': [N_extra_seq, N_res] Whether there is a deletion to the left of each position in the extra MSA. * 'extra_deletion_value': [N_extra_seq, N_res] The number of deletions to the left of each position in the extra MSA. Returns: Concatenated tensor of extra MSA features. """ # 23 = 20 amino acids + 'X' for unknown + gap + bert mask msa_1hot = jax.nn.one_hot(batch['extra_msa'], 23) msa_feat = [msa_1hot, jnp.expand_dims(batch['extra_has_deletion'], axis=-1), jnp.expand_dims(batch['extra_deletion_value'], axis=-1)] return jnp.concatenate(msa_feat, axis=-1) class AlphaFoldIteration(hk.Module): """A single recycling iteration of AlphaFold architecture. Computes ensembled (averaged) representations from the provided features. These representations are then passed to the various heads that have been requested by the configuration file. Each head also returns a loss which is combined as a weighted sum to produce the total loss. Jumper et al. (2021) Suppl. Alg. 2 "Inference" lines 3-22 """ def __init__(self, config, global_config, name='alphafold_iteration'): super().__init__(name=name) self.config = config self.global_config = global_config def __call__(self, ensembled_batch, non_ensembled_batch, is_training, compute_loss=False, ensemble_representations=False, return_representations=False): num_ensemble = jnp.asarray(ensembled_batch['seq_length'].shape[0]) if not ensemble_representations: assert ensembled_batch['seq_length'].shape[0] == 1 def slice_batch(i): b = {k: v[i] for k, v in ensembled_batch.items()} b.update(non_ensembled_batch) return b # Compute representations for each batch element and average. evoformer_module = EmbeddingsAndEvoformer( self.config.embeddings_and_evoformer, self.global_config) batch0 = slice_batch(0) representations = evoformer_module(batch0, is_training) # MSA representations are not ensembled so # we don't pass tensor into the loop. msa_representation = representations['msa'] del representations['msa'] # Average the representations (except MSA) over the batch dimension. if ensemble_representations: def body(x): """Add one element to the representations ensemble.""" i, current_representations = x feats = slice_batch(i) representations_update = evoformer_module( feats, is_training) new_representations = {} for k in current_representations: new_representations[k] = ( current_representations[k] + representations_update[k]) return i+1, new_representations if hk.running_init(): # When initializing the Haiku module, run one iteration of the # while_loop to initialize the Haiku modules used in `body`. _, representations = body((1, representations)) else: _, representations = hk.while_loop( lambda x: x[0] < num_ensemble, body, (1, representations)) for k in representations: if k != 'msa': representations[k] /= num_ensemble.astype(representations[k].dtype) representations['msa'] = msa_representation batch = batch0 # We are not ensembled from here on. heads = {} for head_name, head_config in sorted(self.config.heads.items()): if not head_config.weight: continue # Do not instantiate zero-weight heads. head_factory = { 'masked_msa': MaskedMsaHead, 'distogram': DistogramHead, 'structure_module': functools.partial( folding.StructureModule, compute_loss=compute_loss), 'predicted_lddt': PredictedLDDTHead, 'predicted_aligned_error': PredictedAlignedErrorHead, 'experimentally_resolved': ExperimentallyResolvedHead, }[head_name] heads[head_name] = (head_config, head_factory(head_config, self.global_config)) total_loss = 0. ret = {} ret['representations'] = representations def loss(module, head_config, ret, name, filter_ret=True): if filter_ret: value = ret[name] else: value = ret loss_output = module.loss(value, batch) ret[name].update(loss_output) loss = head_config.weight * ret[name]['loss'] return loss for name, (head_config, module) in heads.items(): # Skip PredictedLDDTHead and PredictedAlignedErrorHead until # StructureModule is executed. if name in ('predicted_lddt', 'predicted_aligned_error'): continue else: ret[name] = module(representations, batch, is_training) if 'representations' in ret[name]: # Extra representations from the head. Used by the structure module # to provide activations for the PredictedLDDTHead. representations.update(ret[name].pop('representations')) if compute_loss: total_loss += loss(module, head_config, ret, name) if self.config.heads.get('predicted_lddt.weight', 0.0): # Add PredictedLDDTHead after StructureModule executes. name = 'predicted_lddt' # Feed all previous results to give access to structure_module result. head_config, module = heads[name] ret[name] = module(representations, batch, is_training) if compute_loss: total_loss += loss(module, head_config, ret, name, filter_ret=False) if ('predicted_aligned_error' in self.config.heads and self.config.heads.get('predicted_aligned_error.weight', 0.0)): # Add PredictedAlignedErrorHead after StructureModule executes. name = 'predicted_aligned_error' # Feed all previous results to give access to structure_module result. head_config, module = heads[name] ret[name] = module(representations, batch, is_training) if compute_loss: total_loss += loss(module, head_config, ret, name, filter_ret=False) if compute_loss: return ret, total_loss else: return ret class AlphaFold(hk.Module): """AlphaFold model with recycling. Jumper et al. (2021) Suppl. Alg. 2 "Inference" """ def __init__(self, config, name='alphafold'): super().__init__(name=name) self.config = config self.global_config = config.global_config def __call__( self, batch, is_training, compute_loss=False, ensemble_representations=False, return_representations=False): """Run the AlphaFold model. Arguments: batch: Dictionary with inputs to the AlphaFold model. is_training: Whether the system is in training or inference mode. compute_loss: Whether to compute losses (requires extra features to be present in the batch and knowing the true structure). ensemble_representations: Whether to use ensembling of representations. return_representations: Whether to also return the intermediate representations. Returns: When compute_loss is True: a tuple of loss and output of AlphaFoldIteration. When compute_loss is False: just output of AlphaFoldIteration. The output of AlphaFoldIteration is a nested dictionary containing predictions from the various heads. """ impl = AlphaFoldIteration(self.config, self.global_config) batch_size, num_residues = batch['aatype'].shape def get_prev(ret): new_prev = { 'prev_pos': ret['structure_module']['final_atom_positions'], 'prev_msa_first_row': ret['representations']['msa_first_row'], 'prev_pair': ret['representations']['pair'], } return jax.tree_map(jax.lax.stop_gradient, new_prev) def do_call(prev, recycle_idx, compute_loss=compute_loss): if self.config.resample_msa_in_recycling: num_ensemble = batch_size // (self.config.num_recycle + 1) def slice_recycle_idx(x): start = recycle_idx * num_ensemble size = num_ensemble return jax.lax.dynamic_slice_in_dim(x, start, size, axis=0) ensembled_batch = jax.tree_map(slice_recycle_idx, batch) else: num_ensemble = batch_size ensembled_batch = batch non_ensembled_batch = jax.tree_map(lambda x: x, prev) return impl( ensembled_batch=ensembled_batch, non_ensembled_batch=non_ensembled_batch, is_training=is_training, compute_loss=compute_loss, ensemble_representations=ensemble_representations) prev = {} emb_config = self.config.embeddings_and_evoformer if emb_config.recycle_pos: prev['prev_pos'] = jnp.zeros( [num_residues, residue_constants.atom_type_num, 3]) if emb_config.recycle_features: prev['prev_msa_first_row'] = jnp.zeros( [num_residues, emb_config.msa_channel]) prev['prev_pair'] = jnp.zeros( [num_residues, num_residues, emb_config.pair_channel]) if self.config.num_recycle: if 'num_iter_recycling' in batch: # Training time: num_iter_recycling is in batch. # The value for each ensemble batch is the same, so arbitrarily taking # 0-th. num_iter = batch['num_iter_recycling'][0] # Add insurance that we will not run more # recyclings than the model is configured to run. num_iter = jnp.minimum(num_iter, self.config.num_recycle) else: # Eval mode or tests: use the maximum number of iterations. num_iter = self.config.num_recycle body = lambda x: (x[0] + 1, # pylint: disable=g-long-lambda get_prev(do_call(x[1], recycle_idx=x[0], compute_loss=False))) if hk.running_init(): # When initializing the Haiku module, run one iteration of the # while_loop to initialize the Haiku modules used in `body`. _, prev = body((0, prev)) else: _, prev = hk.while_loop( lambda x: x[0] < num_iter, body, (0, prev)) else: num_iter = 0 ret = do_call(prev=prev, recycle_idx=num_iter) if compute_loss: ret = ret[0], [ret[1]] if not return_representations: del (ret[0] if compute_loss else ret)['representations'] # pytype: disable=unsupported-operands return ret class TemplatePairStack(hk.Module): """Pair stack for the templates. Jumper et al. (2021) Suppl. Alg. 16 "TemplatePairStack" """ def __init__(self, config, global_config, name='template_pair_stack'): super().__init__(name=name) self.config = config self.global_config = global_config def __call__(self, pair_act, pair_mask, is_training, safe_key=None): """Builds TemplatePairStack module. Arguments: pair_act: Pair activations for single template, shape [N_res, N_res, c_t]. pair_mask: Pair mask, shape [N_res, N_res]. is_training: Whether the module is in training mode. safe_key: Safe key object encapsulating the random number generation key. Returns: Updated pair_act, shape [N_res, N_res, c_t]. """ if safe_key is None: safe_key = prng.SafeKey(hk.next_rng_key()) gc = self.global_config c = self.config if not c.num_block: return pair_act def block(x): """One block of the template pair stack.""" pair_act, safe_key = x dropout_wrapper_fn = functools.partial( dropout_wrapper, is_training=is_training, global_config=gc) safe_key, *sub_keys = safe_key.split(6) sub_keys = iter(sub_keys) pair_act = dropout_wrapper_fn( TriangleAttention(c.triangle_attention_starting_node, gc, name='triangle_attention_starting_node'), pair_act, pair_mask, next(sub_keys)) pair_act = dropout_wrapper_fn( TriangleAttention(c.triangle_attention_ending_node, gc, name='triangle_attention_ending_node'), pair_act, pair_mask, next(sub_keys)) pair_act = dropout_wrapper_fn( TriangleMultiplication(c.triangle_multiplication_outgoing, gc, name='triangle_multiplication_outgoing'), pair_act, pair_mask, next(sub_keys)) pair_act = dropout_wrapper_fn( TriangleMultiplication(c.triangle_multiplication_incoming, gc, name='triangle_multiplication_incoming'), pair_act, pair_mask, next(sub_keys)) pair_act = dropout_wrapper_fn( Transition(c.pair_transition, gc, name='pair_transition'), pair_act, pair_mask, next(sub_keys)) return pair_act, safe_key if gc.use_remat: block = hk.remat(block) res_stack = layer_stack.layer_stack(c.num_block)(block) pair_act, safe_key = res_stack((pair_act, safe_key)) return pair_act class Transition(hk.Module): """Transition layer. Jumper et al. (2021) Suppl. Alg. 9 "MSATransition" Jumper et al. (2021) Suppl. Alg. 15 "PairTransition" """ def __init__(self, config, global_config, name='transition_block'): super().__init__(name=name) self.config = config self.global_config = global_config def __call__(self, act, mask, is_training=True): """Builds Transition module. Arguments: act: A tensor of queries of size [batch_size, N_res, N_channel]. mask: A tensor denoting the mask of size [batch_size, N_res]. is_training: Whether the module is in training mode. Returns: A float32 tensor of size [batch_size, N_res, N_channel]. """ _, _, nc = act.shape num_intermediate = int(nc * self.config.num_intermediate_factor) mask = jnp.expand_dims(mask, axis=-1) act = common_modules.LayerNorm( axis=[-1], create_scale=True, create_offset=True, name='input_layer_norm')( act) transition_module = hk.Sequential([ common_modules.Linear( num_intermediate, initializer='relu', name='transition1'), jax.nn.relu, common_modules.Linear( nc, initializer=utils.final_init(self.global_config), name='transition2') ]) act = mapping.inference_subbatch( transition_module, self.global_config.subbatch_size, batched_args=[act], nonbatched_args=[], low_memory=not is_training) return act def glorot_uniform(): return hk.initializers.VarianceScaling(scale=1.0, mode='fan_avg', distribution='uniform') class Attention(hk.Module): """Multihead attention.""" def __init__(self, config, global_config, output_dim, name='attention'): super().__init__(name=name) self.config = config self.global_config = global_config self.output_dim = output_dim def __call__(self, q_data, m_data, bias, nonbatched_bias=None): """Builds Attention module. Arguments: q_data: A tensor of queries, shape [batch_size, N_queries, q_channels]. m_data: A tensor of memories from which the keys and values are projected, shape [batch_size, N_keys, m_channels]. bias: A bias for the attention, shape [batch_size, N_queries, N_keys]. nonbatched_bias: Shared bias, shape [N_queries, N_keys]. Returns: A float32 tensor of shape [batch_size, N_queries, output_dim]. """ # Sensible default for when the config keys are missing key_dim = self.config.get('key_dim', int(q_data.shape[-1])) value_dim = self.config.get('value_dim', int(m_data.shape[-1])) num_head = self.config.num_head assert key_dim % num_head == 0 assert value_dim % num_head == 0 key_dim = key_dim // num_head value_dim = value_dim // num_head q_weights = hk.get_parameter( 'query_w', shape=(q_data.shape[-1], num_head, key_dim), dtype=q_data.dtype, init=glorot_uniform()) k_weights = hk.get_parameter( 'key_w', shape=(m_data.shape[-1], num_head, key_dim), dtype=q_data.dtype, init=glorot_uniform()) v_weights = hk.get_parameter( 'value_w', shape=(m_data.shape[-1], num_head, value_dim), dtype=q_data.dtype, init=glorot_uniform()) q = jnp.einsum('bqa,ahc->bqhc', q_data, q_weights) * key_dim**(-0.5) k = jnp.einsum('bka,ahc->bkhc', m_data, k_weights) v = jnp.einsum('bka,ahc->bkhc', m_data, v_weights) logits = jnp.einsum('bqhc,bkhc->bhqk', q, k) + bias if nonbatched_bias is not None: logits += jnp.expand_dims(nonbatched_bias, axis=0) weights = jax.nn.softmax(logits) weighted_avg = jnp.einsum('bhqk,bkhc->bqhc', weights, v) if self.global_config.zero_init: init = hk.initializers.Constant(0.0) else: init = glorot_uniform() if self.config.gating: gating_weights = hk.get_parameter( 'gating_w', shape=(q_data.shape[-1], num_head, value_dim), dtype=q_data.dtype, init=hk.initializers.Constant(0.0)) gating_bias = hk.get_parameter( 'gating_b', shape=(num_head, value_dim), dtype=q_data.dtype, init=hk.initializers.Constant(1.0)) gate_values = jnp.einsum('bqc, chv->bqhv', q_data, gating_weights) + gating_bias gate_values = jax.nn.sigmoid(gate_values) weighted_avg *= gate_values o_weights = hk.get_parameter( 'output_w', shape=(num_head, value_dim, self.output_dim), dtype=q_data.dtype, init=init) o_bias = hk.get_parameter( 'output_b', shape=(self.output_dim,), dtype=q_data.dtype, init=hk.initializers.Constant(0.0)) output = jnp.einsum('bqhc,hco->bqo', weighted_avg, o_weights) + o_bias return output class GlobalAttention(hk.Module): """Global attention. Jumper et al. (2021) Suppl. Alg. 19 "MSAColumnGlobalAttention" lines 2-7 """ def __init__(self, config, global_config, output_dim, name='attention'): super().__init__(name=name) self.config = config self.global_config = global_config self.output_dim = output_dim def __call__(self, q_data, m_data, q_mask): """Builds GlobalAttention module. Arguments: q_data: A tensor of queries with size [batch_size, N_queries, q_channels] m_data: A tensor of memories from which the keys and values projected. Size [batch_size, N_keys, m_channels] q_mask: A binary mask for q_data with zeros in the padded sequence elements and ones otherwise. Size [batch_size, N_queries, q_channels] (or broadcastable to this shape). Returns: A float32 tensor of size [batch_size, N_queries, output_dim]. """ # Sensible default for when the config keys are missing key_dim = self.config.get('key_dim', int(q_data.shape[-1])) value_dim = self.config.get('value_dim', int(m_data.shape[-1])) num_head = self.config.num_head assert key_dim % num_head == 0 assert value_dim % num_head == 0 key_dim = key_dim // num_head value_dim = value_dim // num_head q_weights = hk.get_parameter( 'query_w', shape=(q_data.shape[-1], num_head, key_dim), dtype=q_data.dtype, init=glorot_uniform()) k_weights = hk.get_parameter( 'key_w', shape=(m_data.shape[-1], key_dim), dtype=q_data.dtype, init=glorot_uniform()) v_weights = hk.get_parameter( 'value_w', shape=(m_data.shape[-1], value_dim), dtype=q_data.dtype, init=glorot_uniform()) v = jnp.einsum('bka,ac->bkc', m_data, v_weights) q_avg = utils.mask_mean(q_mask, q_data, axis=1) q = jnp.einsum('ba,ahc->bhc', q_avg, q_weights) * key_dim**(-0.5) k = jnp.einsum('bka,ac->bkc', m_data, k_weights) bias = (1e9 * (q_mask[:, None, :, 0] - 1.)) logits = jnp.einsum('bhc,bkc->bhk', q, k) + bias weights = jax.nn.softmax(logits) weighted_avg = jnp.einsum('bhk,bkc->bhc', weights, v) if self.global_config.zero_init: init = hk.initializers.Constant(0.0) else: init = glorot_uniform() o_weights = hk.get_parameter( 'output_w', shape=(num_head, value_dim, self.output_dim), dtype=q_data.dtype, init=init) o_bias = hk.get_parameter( 'output_b', shape=(self.output_dim,), dtype=q_data.dtype, init=hk.initializers.Constant(0.0)) if self.config.gating: gating_weights = hk.get_parameter( 'gating_w', shape=(q_data.shape[-1], num_head, value_dim), dtype=q_data.dtype, init=hk.initializers.Constant(0.0)) gating_bias = hk.get_parameter( 'gating_b', shape=(num_head, value_dim), dtype=q_data.dtype, init=hk.initializers.Constant(1.0)) gate_values = jnp.einsum('bqc, chv->bqhv', q_data, gating_weights) gate_values = jax.nn.sigmoid(gate_values + gating_bias) weighted_avg = weighted_avg[:, None] * gate_values output = jnp.einsum('bqhc,hco->bqo', weighted_avg, o_weights) + o_bias else: output = jnp.einsum('bhc,hco->bo', weighted_avg, o_weights) + o_bias output = output[:, None] return output class MSARowAttentionWithPairBias(hk.Module): """MSA per-row attention biased by the pair representation. Jumper et al. (2021) Suppl. Alg. 7 "MSARowAttentionWithPairBias" """ def __init__(self, config, global_config, name='msa_row_attention_with_pair_bias'): super().__init__(name=name) self.config = config self.global_config = global_config def __call__(self, msa_act, msa_mask, pair_act, is_training=False): """Builds MSARowAttentionWithPairBias module. Arguments: msa_act: [N_seq, N_res, c_m] MSA representation. msa_mask: [N_seq, N_res] mask of non-padded regions. pair_act: [N_res, N_res, c_z] pair representation. is_training: Whether the module is in training mode. Returns: Update to msa_act, shape [N_seq, N_res, c_m]. """ c = self.config assert len(msa_act.shape) == 3 assert len(msa_mask.shape) == 2 assert c.orientation == 'per_row' bias = (1e9 * (msa_mask - 1.))[:, None, None, :] assert len(bias.shape) == 4 msa_act = common_modules.LayerNorm( axis=[-1], create_scale=True, create_offset=True, name='query_norm')( msa_act) pair_act = common_modules.LayerNorm( axis=[-1], create_scale=True, create_offset=True, name='feat_2d_norm')( pair_act) init_factor = 1. / jnp.sqrt(int(pair_act.shape[-1])) weights = hk.get_parameter( 'feat_2d_weights', shape=(pair_act.shape[-1], c.num_head), dtype=msa_act.dtype, init=hk.initializers.RandomNormal(stddev=init_factor)) nonbatched_bias = jnp.einsum('qkc,ch->hqk', pair_act, weights) attn_mod = Attention( c, self.global_config, msa_act.shape[-1]) msa_act = mapping.inference_subbatch( attn_mod, self.global_config.subbatch_size, batched_args=[msa_act, msa_act, bias], nonbatched_args=[nonbatched_bias], low_memory=not is_training) return msa_act class MSAColumnAttention(hk.Module): """MSA per-column attention. Jumper et al. (2021) Suppl. Alg. 8 "MSAColumnAttention" """ def __init__(self, config, global_config, name='msa_column_attention'): super().__init__(name=name) self.config = config self.global_config = global_config def __call__(self, msa_act, msa_mask, is_training=False): """Builds MSAColumnAttention module. Arguments: msa_act: [N_seq, N_res, c_m] MSA representation. msa_mask: [N_seq, N_res] mask of non-padded regions. is_training: Whether the module is in training mode. Returns: Update to msa_act, shape [N_seq, N_res, c_m] """ c = self.config assert len(msa_act.shape) == 3 assert len(msa_mask.shape) == 2 assert c.orientation == 'per_column' msa_act = jnp.swapaxes(msa_act, -2, -3) msa_mask = jnp.swapaxes(msa_mask, -1, -2) bias = (1e9 * (msa_mask - 1.))[:, None, None, :] assert len(bias.shape) == 4 msa_act = common_modules.LayerNorm( axis=[-1], create_scale=True, create_offset=True, name='query_norm')( msa_act) attn_mod = Attention( c, self.global_config, msa_act.shape[-1]) msa_act = mapping.inference_subbatch( attn_mod, self.global_config.subbatch_size, batched_args=[msa_act, msa_act, bias], nonbatched_args=[], low_memory=not is_training) msa_act = jnp.swapaxes(msa_act, -2, -3) return msa_act class MSAColumnGlobalAttention(hk.Module): """MSA per-column global attention. Jumper et al. (2021) Suppl. Alg. 19 "MSAColumnGlobalAttention" """ def __init__(self, config, global_config, name='msa_column_global_attention'): super().__init__(name=name) self.config = config self.global_config = global_config def __call__(self, msa_act, msa_mask, is_training=False): """Builds MSAColumnGlobalAttention module. Arguments: msa_act: [N_seq, N_res, c_m] MSA representation. msa_mask: [N_seq, N_res] mask of non-padded regions. is_training: Whether the module is in training mode. Returns: Update to msa_act, shape [N_seq, N_res, c_m]. """ c = self.config assert len(msa_act.shape) == 3 assert len(msa_mask.shape) == 2 assert c.orientation == 'per_column' msa_act = jnp.swapaxes(msa_act, -2, -3) msa_mask = jnp.swapaxes(msa_mask, -1, -2) bias = (1e9 * (msa_mask - 1.))[:, None, None, :] assert len(bias.shape) == 4 msa_act = common_modules.LayerNorm( axis=[-1], create_scale=True, create_offset=True, name='query_norm')( msa_act) attn_mod = GlobalAttention( c, self.global_config, msa_act.shape[-1], name='attention') # [N_seq, N_res, 1] msa_mask = jnp.expand_dims(msa_mask, axis=-1) msa_act = mapping.inference_subbatch( attn_mod, self.global_config.subbatch_size, batched_args=[msa_act, msa_act, msa_mask], nonbatched_args=[], low_memory=not is_training) msa_act = jnp.swapaxes(msa_act, -2, -3) return msa_act class TriangleAttention(hk.Module): """Triangle Attention. Jumper et al. (2021) Suppl. Alg. 13 "TriangleAttentionStartingNode" Jumper et al. (2021) Suppl. Alg. 14 "TriangleAttentionEndingNode" """ def __init__(self, config, global_config, name='triangle_attention'): super().__init__(name=name) self.config = config self.global_config = global_config def __call__(self, pair_act, pair_mask, is_training=False): """Builds TriangleAttention module. Arguments: pair_act: [N_res, N_res, c_z] pair activations tensor pair_mask: [N_res, N_res] mask of non-padded regions in the tensor. is_training: Whether the module is in training mode. Returns: Update to pair_act, shape [N_res, N_res, c_z]. """ c = self.config assert len(pair_act.shape) == 3 assert len(pair_mask.shape) == 2 assert c.orientation in ['per_row', 'per_column'] if c.orientation == 'per_column': pair_act = jnp.swapaxes(pair_act, -2, -3) pair_mask = jnp.swapaxes(pair_mask, -1, -2) bias = (1e9 * (pair_mask - 1.))[:, None, None, :] assert len(bias.shape) == 4 pair_act = common_modules.LayerNorm( axis=[-1], create_scale=True, create_offset=True, name='query_norm')( pair_act) init_factor = 1. / jnp.sqrt(int(pair_act.shape[-1])) weights = hk.get_parameter( 'feat_2d_weights', shape=(pair_act.shape[-1], c.num_head), dtype=pair_act.dtype, init=hk.initializers.RandomNormal(stddev=init_factor)) nonbatched_bias = jnp.einsum('qkc,ch->hqk', pair_act, weights) attn_mod = Attention( c, self.global_config, pair_act.shape[-1]) pair_act = mapping.inference_subbatch( attn_mod, self.global_config.subbatch_size, batched_args=[pair_act, pair_act, bias], nonbatched_args=[nonbatched_bias], low_memory=not is_training) if c.orientation == 'per_column': pair_act = jnp.swapaxes(pair_act, -2, -3) return pair_act class MaskedMsaHead(hk.Module): """Head to predict MSA at the masked locations. The MaskedMsaHead employs a BERT-style objective to reconstruct a masked version of the full MSA, based on a linear projection of the MSA representation. Jumper et al. (2021) Suppl. Sec. 1.9.9 "Masked MSA prediction" """ def __init__(self, config, global_config, name='masked_msa_head'): super().__init__(name=name) self.config = config self.global_config = global_config if global_config.multimer_mode: self.num_output = len(residue_constants.restypes_with_x_and_gap) else: self.num_output = config.num_output def __call__(self, representations, batch, is_training): """Builds MaskedMsaHead module. Arguments: representations: Dictionary of representations, must contain: * 'msa': MSA representation, shape [N_seq, N_res, c_m]. batch: Batch, unused. is_training: Whether the module is in training mode. Returns: Dictionary containing: * 'logits': logits of shape [N_seq, N_res, N_aatype] with (unnormalized) log probabilies of predicted aatype at position. """ del batch logits = common_modules.Linear( self.num_output, initializer=utils.final_init(self.global_config), name='logits')( representations['msa']) return dict(logits=logits) def loss(self, value, batch): errors = softmax_cross_entropy( labels=jax.nn.one_hot(batch['true_msa'], num_classes=self.num_output), logits=value['logits']) loss = (jnp.sum(errors * batch['bert_mask'], axis=(-2, -1)) / (1e-8 + jnp.sum(batch['bert_mask'], axis=(-2, -1)))) return {'loss': loss} class PredictedLDDTHead(hk.Module): """Head to predict the per-residue LDDT to be used as a confidence measure. Jumper et al. (2021) Suppl. Sec. 1.9.6 "Model confidence prediction (pLDDT)" Jumper et al. (2021) Suppl. Alg. 29 "predictPerResidueLDDT_Ca" """ def __init__(self, config, global_config, name='predicted_lddt_head'): super().__init__(name=name) self.config = config self.global_config = global_config def __call__(self, representations, batch, is_training): """Builds PredictedLDDTHead module. Arguments: representations: Dictionary of representations, must contain: * 'structure_module': Single representation from the structure module, shape [N_res, c_s]. batch: Batch, unused. is_training: Whether the module is in training mode. Returns: Dictionary containing : * 'logits': logits of shape [N_res, N_bins] with (unnormalized) log probabilies of binned predicted lDDT. """ act = representations['structure_module'] act = common_modules.LayerNorm( axis=[-1], create_scale=True, create_offset=True, name='input_layer_norm')( act) act = common_modules.Linear( self.config.num_channels, initializer='relu', name='act_0')( act) act = jax.nn.relu(act) act = common_modules.Linear( self.config.num_channels, initializer='relu', name='act_1')( act) act = jax.nn.relu(act) logits = common_modules.Linear( self.config.num_bins, initializer=utils.final_init(self.global_config), name='logits')( act) # Shape (batch_size, num_res, num_bins) return dict(logits=logits) def loss(self, value, batch): # Shape (num_res, 37, 3) pred_all_atom_pos = value['structure_module']['final_atom_positions'] # Shape (num_res, 37, 3) true_all_atom_pos = batch['all_atom_positions'] # Shape (num_res, 37) all_atom_mask = batch['all_atom_mask'] # Shape (num_res,) lddt_ca = lddt.lddt( # Shape (batch_size, num_res, 3) predicted_points=pred_all_atom_pos[None, :, 1, :], # Shape (batch_size, num_res, 3) true_points=true_all_atom_pos[None, :, 1, :], # Shape (batch_size, num_res, 1) true_points_mask=all_atom_mask[None, :, 1:2].astype(jnp.float32), cutoff=15., per_residue=True) lddt_ca = jax.lax.stop_gradient(lddt_ca) num_bins = self.config.num_bins bin_index = jnp.floor(lddt_ca * num_bins).astype(jnp.int32) # protect against out of range for lddt_ca == 1 bin_index = jnp.minimum(bin_index, num_bins - 1) lddt_ca_one_hot = jax.nn.one_hot(bin_index, num_classes=num_bins) # Shape (num_res, num_channel) logits = value['predicted_lddt']['logits'] errors = softmax_cross_entropy(labels=lddt_ca_one_hot, logits=logits) # Shape (num_res,) mask_ca = all_atom_mask[:, residue_constants.atom_order['CA']] mask_ca = mask_ca.astype(jnp.float32) loss = jnp.sum(errors * mask_ca) / (jnp.sum(mask_ca) + 1e-8) if self.config.filter_by_resolution: # NMR & distillation have resolution = 0 loss *= ((batch['resolution'] >= self.config.min_resolution) & (batch['resolution'] <= self.config.max_resolution)).astype( jnp.float32) output = {'loss': loss} return output class PredictedAlignedErrorHead(hk.Module): """Head to predict the distance errors in the backbone alignment frames. Can be used to compute predicted TM-Score. Jumper et al. (2021) Suppl. Sec. 1.9.7 "TM-score prediction" """ def __init__(self, config, global_config, name='predicted_aligned_error_head'): super().__init__(name=name) self.config = config self.global_config = global_config def __call__(self, representations, batch, is_training): """Builds PredictedAlignedErrorHead module. Arguments: representations: Dictionary of representations, must contain: * 'pair': pair representation, shape [N_res, N_res, c_z]. batch: Batch, unused. is_training: Whether the module is in training mode. Returns: Dictionary containing: * logits: logits for aligned error, shape [N_res, N_res, N_bins]. * bin_breaks: array containing bin breaks, shape [N_bins - 1]. """ act = representations['pair'] # Shape (num_res, num_res, num_bins) logits = common_modules.Linear( self.config.num_bins, initializer=utils.final_init(self.global_config), name='logits')(act) # Shape (num_bins,) breaks = jnp.linspace( 0., self.config.max_error_bin, self.config.num_bins - 1) return dict(logits=logits, breaks=breaks) def loss(self, value, batch): # Shape (num_res, 7) predicted_affine = quat_affine.QuatAffine.from_tensor( value['structure_module']['final_affines']) # Shape (num_res, 7) true_affine = quat_affine.QuatAffine.from_tensor( batch['backbone_affine_tensor']) # Shape (num_res) mask = batch['backbone_affine_mask'] # Shape (num_res, num_res) square_mask = mask[:, None] * mask[None, :] num_bins = self.config.num_bins # (1, num_bins - 1) breaks = value['predicted_aligned_error']['breaks'] # (1, num_bins) logits = value['predicted_aligned_error']['logits'] # Compute the squared error for each alignment. def _local_frame_points(affine): points = [jnp.expand_dims(x, axis=-2) for x in affine.translation] return affine.invert_point(points, extra_dims=1) error_dist2_xyz = [ jnp.square(a - b) for a, b in zip(_local_frame_points(predicted_affine), _local_frame_points(true_affine))] error_dist2 = sum(error_dist2_xyz) # Shape (num_res, num_res) # First num_res are alignment frames, second num_res are the residues. error_dist2 = jax.lax.stop_gradient(error_dist2) sq_breaks = jnp.square(breaks) true_bins = jnp.sum(( error_dist2[..., None] > sq_breaks).astype(jnp.int32), axis=-1) errors = softmax_cross_entropy( labels=jax.nn.one_hot(true_bins, num_bins, axis=-1), logits=logits) loss = (jnp.sum(errors * square_mask, axis=(-2, -1)) / (1e-8 + jnp.sum(square_mask, axis=(-2, -1)))) if self.config.filter_by_resolution: # NMR & distillation have resolution = 0 loss *= ((batch['resolution'] >= self.config.min_resolution) & (batch['resolution'] <= self.config.max_resolution)).astype( jnp.float32) output = {'loss': loss} return output class ExperimentallyResolvedHead(hk.Module): """Predicts if an atom is experimentally resolved in a high-res structure. Only trained on high-resolution X-ray crystals & cryo-EM. Jumper et al. (2021) Suppl. Sec. 1.9.10 '"Experimentally resolved" prediction' """ def __init__(self, config, global_config, name='experimentally_resolved_head'): super().__init__(name=name) self.config = config self.global_config = global_config def __call__(self, representations, batch, is_training): """Builds ExperimentallyResolvedHead module. Arguments: representations: Dictionary of representations, must contain: * 'single': Single representation, shape [N_res, c_s]. batch: Batch, unused. is_training: Whether the module is in training mode. Returns: Dictionary containing: * 'logits': logits of shape [N_res, 37], log probability that an atom is resolved in atom37 representation, can be converted to probability by applying sigmoid. """ logits = common_modules.Linear( 37, # atom_exists.shape[-1] initializer=utils.final_init(self.global_config), name='logits')(representations['single']) return dict(logits=logits) def loss(self, value, batch): logits = value['logits'] assert len(logits.shape) == 2 # Does the atom appear in the amino acid? atom_exists = batch['atom37_atom_exists'] # Is the atom resolved in the experiment? Subset of atom_exists, # *except for OXT* all_atom_mask = batch['all_atom_mask'].astype(jnp.float32) xent = sigmoid_cross_entropy(labels=all_atom_mask, logits=logits) loss = jnp.sum(xent * atom_exists) / (1e-8 + jnp.sum(atom_exists)) if self.config.filter_by_resolution: # NMR & distillation examples have resolution = 0. loss *= ((batch['resolution'] >= self.config.min_resolution) & (batch['resolution'] <= self.config.max_resolution)).astype( jnp.float32) output = {'loss': loss} return output def _layer_norm(axis=-1, name='layer_norm'): return common_modules.LayerNorm( axis=axis, create_scale=True, create_offset=True, eps=1e-5, use_fast_variance=True, scale_init=hk.initializers.Constant(1.), offset_init=hk.initializers.Constant(0.), param_axis=axis, name=name) class TriangleMultiplication(hk.Module): """Triangle multiplication layer ("outgoing" or "incoming"). Jumper et al. (2021) Suppl. Alg. 11 "TriangleMultiplicationOutgoing" Jumper et al. (2021) Suppl. Alg. 12 "TriangleMultiplicationIncoming" """ def __init__(self, config, global_config, name='triangle_multiplication'): super().__init__(name=name) self.config = config self.global_config = global_config def __call__(self, left_act, left_mask, is_training=True): """Builds TriangleMultiplication module. Arguments: left_act: Pair activations, shape [N_res, N_res, c_z] left_mask: Pair mask, shape [N_res, N_res]. is_training: Whether the module is in training mode. Returns: Outputs, same shape/type as left_act. """ del is_training if self.config.fuse_projection_weights: return self._fused_triangle_multiplication(left_act, left_mask) else: return self._triangle_multiplication(left_act, left_mask) @hk.transparent def _triangle_multiplication(self, left_act, left_mask): """Implementation of TriangleMultiplication used in AF2 and AF-M<2.3.""" c = self.config gc = self.global_config mask = left_mask[..., None] act = common_modules.LayerNorm(axis=[-1], create_scale=True, create_offset=True, name='layer_norm_input')(left_act) input_act = act left_projection = common_modules.Linear( c.num_intermediate_channel, name='left_projection') left_proj_act = mask * left_projection(act) right_projection = common_modules.Linear( c.num_intermediate_channel, name='right_projection') right_proj_act = mask * right_projection(act) left_gate_values = jax.nn.sigmoid(common_modules.Linear( c.num_intermediate_channel, bias_init=1., initializer=utils.final_init(gc), name='left_gate')(act)) right_gate_values = jax.nn.sigmoid(common_modules.Linear( c.num_intermediate_channel, bias_init=1., initializer=utils.final_init(gc), name='right_gate')(act)) left_proj_act *= left_gate_values right_proj_act *= right_gate_values # "Outgoing" edges equation: 'ikc,jkc->ijc' # "Incoming" edges equation: 'kjc,kic->ijc' # Note on the Suppl. Alg. 11 & 12 notation: # For the "outgoing" edges, a = left_proj_act and b = right_proj_act # For the "incoming" edges, it's swapped: # b = left_proj_act and a = right_proj_act act = jnp.einsum(c.equation, left_proj_act, right_proj_act) act = common_modules.LayerNorm( axis=[-1], create_scale=True, create_offset=True, name='center_layer_norm')( act) output_channel = int(input_act.shape[-1]) act = common_modules.Linear( output_channel, initializer=utils.final_init(gc), name='output_projection')(act) gate_values = jax.nn.sigmoid(common_modules.Linear( output_channel, bias_init=1., initializer=utils.final_init(gc), name='gating_linear')(input_act)) act *= gate_values return act @hk.transparent def _fused_triangle_multiplication(self, left_act, left_mask): """TriangleMultiplication with fused projection weights.""" mask = left_mask[..., None] c = self.config gc = self.global_config left_act = _layer_norm(axis=-1, name='left_norm_input')(left_act) # Both left and right projections are fused into projection. projection = common_modules.Linear( 2*c.num_intermediate_channel, name='projection') proj_act = mask * projection(left_act) # Both left + right gate are fused into gate_values. gate_values = common_modules.Linear( 2 * c.num_intermediate_channel, name='gate', bias_init=1., initializer=utils.final_init(gc))(left_act) proj_act *= jax.nn.sigmoid(gate_values) left_proj_act = proj_act[:, :, :c.num_intermediate_channel] right_proj_act = proj_act[:, :, c.num_intermediate_channel:] act = jnp.einsum(c.equation, left_proj_act, right_proj_act) act = _layer_norm(axis=-1, name='center_norm')(act) output_channel = int(left_act.shape[-1]) act = common_modules.Linear( output_channel, initializer=utils.final_init(gc), name='output_projection')(act) gate_values = common_modules.Linear( output_channel, bias_init=1., initializer=utils.final_init(gc), name='gating_linear')(left_act) act *= jax.nn.sigmoid(gate_values) return act class DistogramHead(hk.Module): """Head to predict a distogram. Jumper et al. (2021) Suppl. Sec. 1.9.8 "Distogram prediction" """ def __init__(self, config, global_config, name='distogram_head'): super().__init__(name=name) self.config = config self.global_config = global_config def __call__(self, representations, batch, is_training): """Builds DistogramHead module. Arguments: representations: Dictionary of representations, must contain: * 'pair': pair representation, shape [N_res, N_res, c_z]. batch: Batch, unused. is_training: Whether the module is in training mode. Returns: Dictionary containing: * logits: logits for distogram, shape [N_res, N_res, N_bins]. * bin_breaks: array containing bin breaks, shape [N_bins - 1,]. """ half_logits = common_modules.Linear( self.config.num_bins, initializer=utils.final_init(self.global_config), name='half_logits')( representations['pair']) logits = half_logits + jnp.swapaxes(half_logits, -2, -3) breaks = jnp.linspace(self.config.first_break, self.config.last_break, self.config.num_bins - 1) return dict(logits=logits, bin_edges=breaks) def loss(self, value, batch): return _distogram_log_loss(value['logits'], value['bin_edges'], batch, self.config.num_bins) def _distogram_log_loss(logits, bin_edges, batch, num_bins): """Log loss of a distogram.""" assert len(logits.shape) == 3 positions = batch['pseudo_beta'] mask = batch['pseudo_beta_mask'] assert positions.shape[-1] == 3 sq_breaks = jnp.square(bin_edges) dist2 = jnp.sum( jnp.square( jnp.expand_dims(positions, axis=-2) - jnp.expand_dims(positions, axis=-3)), axis=-1, keepdims=True) true_bins = jnp.sum(dist2 > sq_breaks, axis=-1) errors = softmax_cross_entropy( labels=jax.nn.one_hot(true_bins, num_bins), logits=logits) square_mask = jnp.expand_dims(mask, axis=-2) * jnp.expand_dims(mask, axis=-1) avg_error = ( jnp.sum(errors * square_mask, axis=(-2, -1)) / (1e-6 + jnp.sum(square_mask, axis=(-2, -1)))) dist2 = dist2[..., 0] return dict(loss=avg_error, true_dist=jnp.sqrt(1e-6 + dist2)) class OuterProductMean(hk.Module): """Computes mean outer product. Jumper et al. (2021) Suppl. Alg. 10 "OuterProductMean" """ def __init__(self, config, global_config, num_output_channel, name='outer_product_mean'): super().__init__(name=name) self.global_config = global_config self.config = config self.num_output_channel = num_output_channel def __call__(self, act, mask, is_training=True): """Builds OuterProductMean module. Arguments: act: MSA representation, shape [N_seq, N_res, c_m]. mask: MSA mask, shape [N_seq, N_res]. is_training: Whether the module is in training mode. Returns: Update to pair representation, shape [N_res, N_res, c_z]. """ gc = self.global_config c = self.config mask = mask[..., None] act = common_modules.LayerNorm([-1], True, True, name='layer_norm_input')(act) left_act = mask * common_modules.Linear( c.num_outer_channel, initializer='linear', name='left_projection')( act) right_act = mask * common_modules.Linear( c.num_outer_channel, initializer='linear', name='right_projection')( act) if gc.zero_init: init_w = hk.initializers.Constant(0.0) else: init_w = hk.initializers.VarianceScaling(scale=2., mode='fan_in') output_w = hk.get_parameter( 'output_w', shape=(c.num_outer_channel, c.num_outer_channel, self.num_output_channel), dtype=act.dtype, init=init_w) output_b = hk.get_parameter( 'output_b', shape=(self.num_output_channel,), dtype=act.dtype, init=hk.initializers.Constant(0.0)) def compute_chunk(left_act): # This is equivalent to # # act = jnp.einsum('abc,ade->dceb', left_act, right_act) # act = jnp.einsum('dceb,cef->bdf', act, output_w) + output_b # # but faster. left_act = jnp.transpose(left_act, [0, 2, 1]) act = jnp.einsum('acb,ade->dceb', left_act, right_act) act = jnp.einsum('dceb,cef->dbf', act, output_w) + output_b return jnp.transpose(act, [1, 0, 2]) act = mapping.inference_subbatch( compute_chunk, c.chunk_size, batched_args=[left_act], nonbatched_args=[], low_memory=True, input_subbatch_dim=1, output_subbatch_dim=0) epsilon = 1e-3 norm = jnp.einsum('abc,adc->bdc', mask, mask) act /= epsilon + norm return act def dgram_from_positions(positions, num_bins, min_bin, max_bin): """Compute distogram from amino acid positions. Arguments: positions: [N_res, 3] Position coordinates. num_bins: The number of bins in the distogram. min_bin: The left edge of the first bin. max_bin: The left edge of the final bin. The final bin catches everything larger than `max_bin`. Returns: Distogram with the specified number of bins. """ def squared_difference(x, y): return jnp.square(x - y) lower_breaks = jnp.linspace(min_bin, max_bin, num_bins) lower_breaks = jnp.square(lower_breaks) upper_breaks = jnp.concatenate([lower_breaks[1:], jnp.array([1e8], dtype=jnp.float32)], axis=-1) dist2 = jnp.sum( squared_difference( jnp.expand_dims(positions, axis=-2), jnp.expand_dims(positions, axis=-3)), axis=-1, keepdims=True) dgram = ((dist2 > lower_breaks).astype(jnp.float32) * (dist2 < upper_breaks).astype(jnp.float32)) return dgram def pseudo_beta_fn(aatype, all_atom_positions, all_atom_masks): """Create pseudo beta features.""" is_gly = jnp.equal(aatype, residue_constants.restype_order['G']) ca_idx = residue_constants.atom_order['CA'] cb_idx = residue_constants.atom_order['CB'] pseudo_beta = jnp.where( jnp.tile(is_gly[..., None], [1] * len(is_gly.shape) + [3]), all_atom_positions[..., ca_idx, :], all_atom_positions[..., cb_idx, :]) if all_atom_masks is not None: pseudo_beta_mask = jnp.where( is_gly, all_atom_masks[..., ca_idx], all_atom_masks[..., cb_idx]) pseudo_beta_mask = pseudo_beta_mask.astype(jnp.float32) return pseudo_beta, pseudo_beta_mask else: return pseudo_beta class EvoformerIteration(hk.Module): """Single iteration (block) of Evoformer stack. Jumper et al. (2021) Suppl. Alg. 6 "EvoformerStack" lines 2-10 """ def __init__(self, config, global_config, is_extra_msa, name='evoformer_iteration'): super().__init__(name=name) self.config = config self.global_config = global_config self.is_extra_msa = is_extra_msa def __call__(self, activations, masks, is_training=True, safe_key=None): """Builds EvoformerIteration module. Arguments: activations: Dictionary containing activations: * 'msa': MSA activations, shape [N_seq, N_res, c_m]. * 'pair': pair activations, shape [N_res, N_res, c_z]. masks: Dictionary of masks: * 'msa': MSA mask, shape [N_seq, N_res]. * 'pair': pair mask, shape [N_res, N_res]. is_training: Whether the module is in training mode. safe_key: prng.SafeKey encapsulating rng key. Returns: Outputs, same shape/type as act. """ c = self.config gc = self.global_config msa_act, pair_act = activations['msa'], activations['pair'] if safe_key is None: safe_key = prng.SafeKey(hk.next_rng_key()) msa_mask, pair_mask = masks['msa'], masks['pair'] dropout_wrapper_fn = functools.partial( dropout_wrapper, is_training=is_training, global_config=gc) safe_key, *sub_keys = safe_key.split(10) sub_keys = iter(sub_keys) outer_module = OuterProductMean( config=c.outer_product_mean, global_config=self.global_config, num_output_channel=int(pair_act.shape[-1]), name='outer_product_mean') if c.outer_product_mean.first: pair_act = dropout_wrapper_fn( outer_module, msa_act, msa_mask, safe_key=next(sub_keys), output_act=pair_act) msa_act = dropout_wrapper_fn( MSARowAttentionWithPairBias( c.msa_row_attention_with_pair_bias, gc, name='msa_row_attention_with_pair_bias'), msa_act, msa_mask, safe_key=next(sub_keys), pair_act=pair_act) if not self.is_extra_msa: attn_mod = MSAColumnAttention( c.msa_column_attention, gc, name='msa_column_attention') else: attn_mod = MSAColumnGlobalAttention( c.msa_column_attention, gc, name='msa_column_global_attention') msa_act = dropout_wrapper_fn( attn_mod, msa_act, msa_mask, safe_key=next(sub_keys)) msa_act = dropout_wrapper_fn( Transition(c.msa_transition, gc, name='msa_transition'), msa_act, msa_mask, safe_key=next(sub_keys)) if not c.outer_product_mean.first: pair_act = dropout_wrapper_fn( outer_module, msa_act, msa_mask, safe_key=next(sub_keys), output_act=pair_act) pair_act = dropout_wrapper_fn( TriangleMultiplication(c.triangle_multiplication_outgoing, gc, name='triangle_multiplication_outgoing'), pair_act, pair_mask, safe_key=next(sub_keys)) pair_act = dropout_wrapper_fn( TriangleMultiplication(c.triangle_multiplication_incoming, gc, name='triangle_multiplication_incoming'), pair_act, pair_mask, safe_key=next(sub_keys)) pair_act = dropout_wrapper_fn( TriangleAttention(c.triangle_attention_starting_node, gc, name='triangle_attention_starting_node'), pair_act, pair_mask, safe_key=next(sub_keys)) pair_act = dropout_wrapper_fn( TriangleAttention(c.triangle_attention_ending_node, gc, name='triangle_attention_ending_node'), pair_act, pair_mask, safe_key=next(sub_keys)) pair_act = dropout_wrapper_fn( Transition(c.pair_transition, gc, name='pair_transition'), pair_act, pair_mask, safe_key=next(sub_keys)) return {'msa': msa_act, 'pair': pair_act} class EmbeddingsAndEvoformer(hk.Module): """Embeds the input data and runs Evoformer. Produces the MSA, single and pair representations. Jumper et al. (2021) Suppl. Alg. 2 "Inference" line 5-18 """ def __init__(self, config, global_config, name='evoformer'): super().__init__(name=name) self.config = config self.global_config = global_config def __call__(self, batch, is_training, safe_key=None): c = self.config gc = self.global_config if safe_key is None: safe_key = prng.SafeKey(hk.next_rng_key()) # Embed clustered MSA. # Jumper et al. (2021) Suppl. Alg. 2 "Inference" line 5 # Jumper et al. (2021) Suppl. Alg. 3 "InputEmbedder" preprocess_1d = common_modules.Linear( c.msa_channel, name='preprocess_1d')( batch['target_feat']) preprocess_msa = common_modules.Linear( c.msa_channel, name='preprocess_msa')( batch['msa_feat']) msa_activations = jnp.expand_dims(preprocess_1d, axis=0) + preprocess_msa left_single = common_modules.Linear( c.pair_channel, name='left_single')( batch['target_feat']) right_single = common_modules.Linear( c.pair_channel, name='right_single')( batch['target_feat']) pair_activations = left_single[:, None] + right_single[None] mask_2d = batch['seq_mask'][:, None] * batch['seq_mask'][None, :] # Inject previous outputs for recycling. # Jumper et al. (2021) Suppl. Alg. 2 "Inference" line 6 # Jumper et al. (2021) Suppl. Alg. 32 "RecyclingEmbedder" if c.recycle_pos: prev_pseudo_beta = pseudo_beta_fn( batch['aatype'], batch['prev_pos'], None) dgram = dgram_from_positions(prev_pseudo_beta, **self.config.prev_pos) pair_activations += common_modules.Linear( c.pair_channel, name='prev_pos_linear')( dgram) if c.recycle_features: prev_msa_first_row = common_modules.LayerNorm( axis=[-1], create_scale=True, create_offset=True, name='prev_msa_first_row_norm')( batch['prev_msa_first_row']) msa_activations = msa_activations.at[0].add(prev_msa_first_row) pair_activations += common_modules.LayerNorm( axis=[-1], create_scale=True, create_offset=True, name='prev_pair_norm')( batch['prev_pair']) # Relative position encoding. # Jumper et al. (2021) Suppl. Alg. 4 "relpos" # Jumper et al. (2021) Suppl. Alg. 5 "one_hot" if c.max_relative_feature: # Add one-hot-encoded clipped residue distances to the pair activations. pos = batch['residue_index'] offset = pos[:, None] - pos[None, :] rel_pos = jax.nn.one_hot( jnp.clip( offset + c.max_relative_feature, a_min=0, a_max=2 * c.max_relative_feature), 2 * c.max_relative_feature + 1) pair_activations += common_modules.Linear( c.pair_channel, name='pair_activiations')( rel_pos) # Embed templates into the pair activations. # Jumper et al. (2021) Suppl. Alg. 2 "Inference" lines 9-13 if c.template.enabled: template_batch = {k: batch[k] for k in batch if k.startswith('template_')} template_pair_representation = TemplateEmbedding(c.template, gc)( pair_activations, template_batch, mask_2d, is_training=is_training) pair_activations += template_pair_representation # Embed extra MSA features. # Jumper et al. (2021) Suppl. Alg. 2 "Inference" lines 14-16 extra_msa_feat = create_extra_msa_feature(batch) extra_msa_activations = common_modules.Linear( c.extra_msa_channel, name='extra_msa_activations')( extra_msa_feat) # Extra MSA Stack. # Jumper et al. (2021) Suppl. Alg. 18 "ExtraMsaStack" extra_msa_stack_input = { 'msa': extra_msa_activations, 'pair': pair_activations, } extra_msa_stack_iteration = EvoformerIteration( c.evoformer, gc, is_extra_msa=True, name='extra_msa_stack') def extra_msa_stack_fn(x): act, safe_key = x safe_key, safe_subkey = safe_key.split() extra_evoformer_output = extra_msa_stack_iteration( activations=act, masks={ 'msa': batch['extra_msa_mask'], 'pair': mask_2d }, is_training=is_training, safe_key=safe_subkey) return (extra_evoformer_output, safe_key) if gc.use_remat: extra_msa_stack_fn = hk.remat(extra_msa_stack_fn) extra_msa_stack = layer_stack.layer_stack( c.extra_msa_stack_num_block)( extra_msa_stack_fn) extra_msa_output, safe_key = extra_msa_stack( (extra_msa_stack_input, safe_key)) pair_activations = extra_msa_output['pair'] evoformer_input = { 'msa': msa_activations, 'pair': pair_activations, } evoformer_masks = {'msa': batch['msa_mask'], 'pair': mask_2d} # Append num_templ rows to msa_activations with template embeddings. # Jumper et al. (2021) Suppl. Alg. 2 "Inference" lines 7-8 if c.template.enabled and c.template.embed_torsion_angles: num_templ, num_res = batch['template_aatype'].shape # Embed the templates aatypes. aatype_one_hot = jax.nn.one_hot(batch['template_aatype'], 22, axis=-1) # Embed the templates aatype, torsion angles and masks. # Shape (templates, residues, msa_channels) ret = all_atom.atom37_to_torsion_angles( aatype=batch['template_aatype'], all_atom_pos=batch['template_all_atom_positions'], all_atom_mask=batch['template_all_atom_masks'], # Ensure consistent behaviour during testing: placeholder_for_undefined=not gc.zero_init) template_features = jnp.concatenate([ aatype_one_hot, jnp.reshape( ret['torsion_angles_sin_cos'], [num_templ, num_res, 14]), jnp.reshape( ret['alt_torsion_angles_sin_cos'], [num_templ, num_res, 14]), ret['torsion_angles_mask']], axis=-1) template_activations = common_modules.Linear( c.msa_channel, initializer='relu', name='template_single_embedding')( template_features) template_activations = jax.nn.relu(template_activations) template_activations = common_modules.Linear( c.msa_channel, initializer='relu', name='template_projection')( template_activations) # Concatenate the templates to the msa. evoformer_input['msa'] = jnp.concatenate( [evoformer_input['msa'], template_activations], axis=0) # Concatenate templates masks to the msa masks. # Use mask from the psi angle, as it only depends on the backbone atoms # from a single residue. torsion_angle_mask = ret['torsion_angles_mask'][:, :, 2] torsion_angle_mask = torsion_angle_mask.astype( evoformer_masks['msa'].dtype) evoformer_masks['msa'] = jnp.concatenate( [evoformer_masks['msa'], torsion_angle_mask], axis=0) # Main trunk of the network # Jumper et al. (2021) Suppl. Alg. 2 "Inference" lines 17-18 evoformer_iteration = EvoformerIteration( c.evoformer, gc, is_extra_msa=False, name='evoformer_iteration') def evoformer_fn(x): act, safe_key = x safe_key, safe_subkey = safe_key.split() evoformer_output = evoformer_iteration( activations=act, masks=evoformer_masks, is_training=is_training, safe_key=safe_subkey) return (evoformer_output, safe_key) if gc.use_remat: evoformer_fn = hk.remat(evoformer_fn) evoformer_stack = layer_stack.layer_stack(c.evoformer_num_block)( evoformer_fn) evoformer_output, safe_key = evoformer_stack( (evoformer_input, safe_key)) msa_activations = evoformer_output['msa'] pair_activations = evoformer_output['pair'] single_activations = common_modules.Linear( c.seq_channel, name='single_activations')( msa_activations[0]) num_sequences = batch['msa_feat'].shape[0] output = { 'single': single_activations, 'pair': pair_activations, # Crop away template rows such that they are not used in MaskedMsaHead. 'msa': msa_activations[:num_sequences, :, :], 'msa_first_row': msa_activations[0], } return output class SingleTemplateEmbedding(hk.Module): """Embeds a single template. Jumper et al. (2021) Suppl. Alg. 2 "Inference" lines 9+11 """ def __init__(self, config, global_config, name='single_template_embedding'): super().__init__(name=name) self.config = config self.global_config = global_config def __call__(self, query_embedding, batch, mask_2d, is_training): """Build the single template embedding. Arguments: query_embedding: Query pair representation, shape [N_res, N_res, c_z]. batch: A batch of template features (note the template dimension has been stripped out as this module only runs over a single template). mask_2d: Padding mask (Note: this doesn't care if a template exists, unlike the template_pseudo_beta_mask). is_training: Whether the module is in training mode. Returns: A template embedding [N_res, N_res, c_z]. """ assert mask_2d.dtype == query_embedding.dtype dtype = query_embedding.dtype num_res = batch['template_aatype'].shape[0] num_channels = (self.config.template_pair_stack .triangle_attention_ending_node.value_dim) template_mask = batch['template_pseudo_beta_mask'] template_mask_2d = template_mask[:, None] * template_mask[None, :] template_mask_2d = template_mask_2d.astype(dtype) template_dgram = dgram_from_positions(batch['template_pseudo_beta'], **self.config.dgram_features) template_dgram = template_dgram.astype(dtype) to_concat = [template_dgram, template_mask_2d[:, :, None]] aatype = jax.nn.one_hot(batch['template_aatype'], 22, axis=-1, dtype=dtype) to_concat.append(jnp.tile(aatype[None, :, :], [num_res, 1, 1])) to_concat.append(jnp.tile(aatype[:, None, :], [1, num_res, 1])) n, ca, c = [residue_constants.atom_order[a] for a in ('N', 'CA', 'C')] rot, trans = quat_affine.make_transform_from_reference( n_xyz=batch['template_all_atom_positions'][:, n], ca_xyz=batch['template_all_atom_positions'][:, ca], c_xyz=batch['template_all_atom_positions'][:, c]) affines = quat_affine.QuatAffine( quaternion=quat_affine.rot_to_quat(rot, unstack_inputs=True), translation=trans, rotation=rot, unstack_inputs=True) points = [jnp.expand_dims(x, axis=-2) for x in affines.translation] affine_vec = affines.invert_point(points, extra_dims=1) inv_distance_scalar = jax.lax.rsqrt( 1e-6 + sum([jnp.square(x) for x in affine_vec])) # Backbone affine mask: whether the residue has C, CA, N # (the template mask defined above only considers pseudo CB). template_mask = ( batch['template_all_atom_masks'][..., n] * batch['template_all_atom_masks'][..., ca] * batch['template_all_atom_masks'][..., c]) template_mask_2d = template_mask[:, None] * template_mask[None, :] inv_distance_scalar *= template_mask_2d.astype(inv_distance_scalar.dtype) unit_vector = [(x * inv_distance_scalar)[..., None] for x in affine_vec] unit_vector = [x.astype(dtype) for x in unit_vector] template_mask_2d = template_mask_2d.astype(dtype) if not self.config.use_template_unit_vector: unit_vector = [jnp.zeros_like(x) for x in unit_vector] to_concat.extend(unit_vector) to_concat.append(template_mask_2d[..., None]) act = jnp.concatenate(to_concat, axis=-1) # Mask out non-template regions so we don't get arbitrary values in the # distogram for these regions. act *= template_mask_2d[..., None] # Jumper et al. (2021) Suppl. Alg. 2 "Inference" line 9 act = common_modules.Linear( num_channels, initializer='relu', name='embedding2d')( act) # Jumper et al. (2021) Suppl. Alg. 2 "Inference" line 11 act = TemplatePairStack( self.config.template_pair_stack, self.global_config)( act, mask_2d, is_training) act = common_modules.LayerNorm([-1], True, True, name='output_layer_norm')(act) return act class TemplateEmbedding(hk.Module): """Embeds a set of templates. Jumper et al. (2021) Suppl. Alg. 2 "Inference" lines 9-12 Jumper et al. (2021) Suppl. Alg. 17 "TemplatePointwiseAttention" """ def __init__(self, config, global_config, name='template_embedding'): super().__init__(name=name) self.config = config self.global_config = global_config def __call__(self, query_embedding, template_batch, mask_2d, is_training): """Build TemplateEmbedding module. Arguments: query_embedding: Query pair representation, shape [N_res, N_res, c_z]. template_batch: A batch of template features. mask_2d: Padding mask (Note: this doesn't care if a template exists, unlike the template_pseudo_beta_mask). is_training: Whether the module is in training mode. Returns: A template embedding [N_res, N_res, c_z]. """ num_templates = template_batch['template_mask'].shape[0] num_channels = (self.config.template_pair_stack .triangle_attention_ending_node.value_dim) num_res = query_embedding.shape[0] dtype = query_embedding.dtype template_mask = template_batch['template_mask'] template_mask = template_mask.astype(dtype) query_num_channels = query_embedding.shape[-1] # Make sure the weights are shared across templates by constructing the # embedder here. # Jumper et al. (2021) Suppl. Alg. 2 "Inference" lines 9-12 template_embedder = SingleTemplateEmbedding(self.config, self.global_config) def map_fn(batch): return template_embedder(query_embedding, batch, mask_2d, is_training) template_pair_representation = mapping.sharded_map(map_fn, in_axes=0)( template_batch) # Cross attend from the query to the templates along the residue # dimension by flattening everything else into the batch dimension. # Jumper et al. (2021) Suppl. Alg. 17 "TemplatePointwiseAttention" flat_query = jnp.reshape(query_embedding, [num_res * num_res, 1, query_num_channels]) flat_templates = jnp.reshape( jnp.transpose(template_pair_representation, [1, 2, 0, 3]), [num_res * num_res, num_templates, num_channels]) bias = (1e9 * (template_mask[None, None, None, :] - 1.)) template_pointwise_attention_module = Attention( self.config.attention, self.global_config, query_num_channels) nonbatched_args = [bias] batched_args = [flat_query, flat_templates] embedding = mapping.inference_subbatch( template_pointwise_attention_module, self.config.subbatch_size, batched_args=batched_args, nonbatched_args=nonbatched_args, low_memory=not is_training) embedding = jnp.reshape(embedding, [num_res, num_res, query_num_channels]) # No gradients if no templates. embedding *= (jnp.sum(template_mask) > 0.).astype(embedding.dtype) return embedding ================================================ FILE: alphafold/model/modules_multimer.py ================================================ # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Core modules, which have been refactored in AlphaFold-Multimer. The main difference is that MSA sampling pipeline is moved inside the JAX model for easier implementation of recycling and ensembling. Lower-level modules up to EvoformerIteration are reused from modules.py. """ import functools from typing import Sequence from alphafold.common import residue_constants from alphafold.model import all_atom_multimer from alphafold.model import common_modules from alphafold.model import folding_multimer from alphafold.model import geometry from alphafold.model import layer_stack from alphafold.model import modules from alphafold.model import prng from alphafold.model import utils import haiku as hk import jax import jax.numpy as jnp import numpy as np def reduce_fn(x, mode): if mode == 'none' or mode is None: return jnp.asarray(x) elif mode == 'sum': return jnp.asarray(x).sum() elif mode == 'mean': return jnp.mean(jnp.asarray(x)) else: raise ValueError('Unsupported reduction option.') def gumbel_noise(key: jnp.ndarray, shape: Sequence[int]) -> jnp.ndarray: """Generate Gumbel Noise of given Shape. This generates samples from Gumbel(0, 1). Args: key: Jax random number key. shape: Shape of noise to return. Returns: Gumbel noise of given shape. """ epsilon = 1e-6 uniform = utils.padding_consistent_rng(jax.random.uniform) uniform_noise = uniform( key, shape=shape, dtype=jnp.float32, minval=0., maxval=1.) gumbel = -jnp.log(-jnp.log(uniform_noise + epsilon) + epsilon) return gumbel def gumbel_max_sample(key: jnp.ndarray, logits: jnp.ndarray) -> jnp.ndarray: """Samples from a probability distribution given by 'logits'. This uses Gumbel-max trick to implement the sampling in an efficient manner. Args: key: prng key. logits: Logarithm of probabilities to sample from, probabilities can be unnormalized. Returns: Sample from logprobs in one-hot form. """ z = gumbel_noise(key, logits.shape) return jax.nn.one_hot( jnp.argmax(logits + z, axis=-1), logits.shape[-1], dtype=logits.dtype) def gumbel_argsort_sample_idx(key: jnp.ndarray, logits: jnp.ndarray) -> jnp.ndarray: """Samples with replacement from a distribution given by 'logits'. This uses Gumbel trick to implement the sampling an efficient manner. For a distribution over k items this samples k times without replacement, so this is effectively sampling a random permutation with probabilities over the permutations derived from the logprobs. Args: key: prng key. logits: Logarithm of probabilities to sample from, probabilities can be unnormalized. Returns: Sample from logprobs in one-hot form. """ z = gumbel_noise(key, logits.shape) # This construction is equivalent to jnp.argsort, but using a non stable sort, # since stable sort's aren't supported by jax2tf. axis = len(logits.shape) - 1 iota = jax.lax.broadcasted_iota(jnp.int64, logits.shape, axis) _, perm = jax.lax.sort_key_val( logits + z, iota, dimension=-1, is_stable=False) return perm[::-1] def make_masked_msa(batch, key, config, epsilon=1e-6): """Create data for BERT on raw MSA.""" # Add a random amino acid uniformly. random_aa = jnp.array([0.05] * 20 + [0., 0.], dtype=jnp.float32) categorical_probs = ( config.uniform_prob * random_aa + config.profile_prob * batch['msa_profile'] + config.same_prob * jax.nn.one_hot(batch['msa'], 22)) # Put all remaining probability on [MASK] which is a new column. pad_shapes = [[0, 0] for _ in range(len(categorical_probs.shape))] pad_shapes[-1][1] = 1 mask_prob = 1. - config.profile_prob - config.same_prob - config.uniform_prob assert mask_prob >= 0. categorical_probs = jnp.pad( categorical_probs, pad_shapes, constant_values=mask_prob) sh = batch['msa'].shape key, mask_subkey, gumbel_subkey = key.split(3) uniform = utils.padding_consistent_rng(jax.random.uniform) mask_position = uniform(mask_subkey.get(), sh) < config.replace_fraction mask_position *= batch['msa_mask'] logits = jnp.log(categorical_probs + epsilon) bert_msa = gumbel_max_sample(gumbel_subkey.get(), logits) bert_msa = jnp.where(mask_position, jnp.argmax(bert_msa, axis=-1), batch['msa']) bert_msa *= batch['msa_mask'] # Mix real and masked MSA. if 'bert_mask' in batch: batch['bert_mask'] *= mask_position.astype(jnp.float32) else: batch['bert_mask'] = mask_position.astype(jnp.float32) batch['true_msa'] = batch['msa'] batch['msa'] = bert_msa return batch def nearest_neighbor_clusters(batch, gap_agreement_weight=0.): """Assign each extra MSA sequence to its nearest neighbor in sampled MSA.""" # Determine how much weight we assign to each agreement. In theory, we could # use a full blosum matrix here, but right now let's just down-weight gap # agreement because it could be spurious. # Never put weight on agreeing on BERT mask. weights = jnp.array( [1.] * 21 + [gap_agreement_weight] + [0.], dtype=jnp.float32) msa_mask = batch['msa_mask'] msa_one_hot = jax.nn.one_hot(batch['msa'], 23) extra_mask = batch['extra_msa_mask'] extra_one_hot = jax.nn.one_hot(batch['extra_msa'], 23) msa_one_hot_masked = msa_mask[:, :, None] * msa_one_hot extra_one_hot_masked = extra_mask[:, :, None] * extra_one_hot agreement = jnp.einsum('mrc, nrc->nm', extra_one_hot_masked, weights * msa_one_hot_masked) cluster_assignment = jax.nn.softmax(1e3 * agreement, axis=0) cluster_assignment *= jnp.einsum('mr, nr->mn', msa_mask, extra_mask) cluster_count = jnp.sum(cluster_assignment, axis=-1) cluster_count += 1. # We always include the sequence itself. msa_sum = jnp.einsum('nm, mrc->nrc', cluster_assignment, extra_one_hot_masked) msa_sum += msa_one_hot_masked cluster_profile = msa_sum / cluster_count[:, None, None] extra_deletion_matrix = batch['extra_deletion_matrix'] deletion_matrix = batch['deletion_matrix'] del_sum = jnp.einsum('nm, mc->nc', cluster_assignment, extra_mask * extra_deletion_matrix) del_sum += deletion_matrix # Original sequence. cluster_deletion_mean = del_sum / cluster_count[:, None] return cluster_profile, cluster_deletion_mean def create_msa_feat(batch): """Create and concatenate MSA features.""" msa_1hot = jax.nn.one_hot(batch['msa'], 23) deletion_matrix = batch['deletion_matrix'] has_deletion = jnp.clip(deletion_matrix, 0., 1.)[..., None] deletion_value = (jnp.arctan(deletion_matrix / 3.) * (2. / jnp.pi))[..., None] deletion_mean_value = (jnp.arctan(batch['cluster_deletion_mean'] / 3.) * (2. / jnp.pi))[..., None] msa_feat = [ msa_1hot, has_deletion, deletion_value, batch['cluster_profile'], deletion_mean_value ] return jnp.concatenate(msa_feat, axis=-1) def create_extra_msa_feature(batch, num_extra_msa): """Expand extra_msa into 1hot and concat with other extra msa features. We do this as late as possible as the one_hot extra msa can be very large. Args: batch: a dictionary with the following keys: * 'extra_msa': [num_seq, num_res] MSA that wasn't selected as a cluster centre. Note - This isn't one-hotted. * 'extra_deletion_matrix': [num_seq, num_res] Number of deletions at given position. num_extra_msa: Number of extra msa to use. Returns: Concatenated tensor of extra MSA features. """ # 23 = 20 amino acids + 'X' for unknown + gap + bert mask extra_msa = batch['extra_msa'][:num_extra_msa] deletion_matrix = batch['extra_deletion_matrix'][:num_extra_msa] msa_1hot = jax.nn.one_hot(extra_msa, 23) has_deletion = jnp.clip(deletion_matrix, 0., 1.)[..., None] deletion_value = (jnp.arctan(deletion_matrix / 3.) * (2. / jnp.pi))[..., None] extra_msa_mask = batch['extra_msa_mask'][:num_extra_msa] return jnp.concatenate([msa_1hot, has_deletion, deletion_value], axis=-1), extra_msa_mask def sample_msa(key, batch, max_seq): """Sample MSA randomly, remaining sequences are stored as `extra_*`. Args: key: safe key for random number generation. batch: batch to sample msa from. max_seq: number of sequences to sample. Returns: Protein with sampled msa. """ # Sample uniformly among sequences with at least one non-masked position. logits = (jnp.clip(jnp.sum(batch['msa_mask'], axis=-1), 0., 1.) - 1.) * 1e6 # The cluster_bias_mask can be used to preserve the first row (target # sequence) for each chain, for example. if 'cluster_bias_mask' not in batch: cluster_bias_mask = jnp.pad( jnp.zeros(batch['msa'].shape[0] - 1), (1, 0), constant_values=1.) else: cluster_bias_mask = batch['cluster_bias_mask'] logits += cluster_bias_mask * 1e6 index_order = gumbel_argsort_sample_idx(key.get(), logits) sel_idx = index_order[:max_seq] extra_idx = index_order[max_seq:] for k in ['msa', 'deletion_matrix', 'msa_mask', 'bert_mask']: if k in batch: batch['extra_' + k] = batch[k][extra_idx] batch[k] = batch[k][sel_idx] return batch def make_msa_profile(batch): """Compute the MSA profile.""" # Compute the profile for every residue (over all MSA sequences). return utils.mask_mean( batch['msa_mask'][:, :, None], jax.nn.one_hot(batch['msa'], 22), axis=0) class AlphaFoldIteration(hk.Module): """A single recycling iteration of AlphaFold architecture. Computes ensembled (averaged) representations from the provided features. These representations are then passed to the various heads that have been requested by the configuration file. """ def __init__(self, config, global_config, name='alphafold_iteration'): super().__init__(name=name) self.config = config self.global_config = global_config def __call__(self, batch, is_training, return_representations=False, safe_key=None): if is_training: num_ensemble = np.asarray(self.config.num_ensemble_train) else: num_ensemble = np.asarray(self.config.num_ensemble_eval) # Compute representations for each MSA sample and average. embedding_module = EmbeddingsAndEvoformer( self.config.embeddings_and_evoformer, self.global_config) repr_shape = hk.eval_shape( lambda: embedding_module(batch, is_training)) representations = { k: jnp.zeros(v.shape, v.dtype) for (k, v) in repr_shape.items() } def ensemble_body(x, unused_y): """Add into representations ensemble.""" del unused_y representations, safe_key = x safe_key, safe_subkey = safe_key.split() representations_update = embedding_module( batch, is_training, safe_key=safe_subkey) for k in representations: if k not in {'msa', 'true_msa', 'bert_mask'}: representations[k] += representations_update[k] * ( 1. / num_ensemble).astype(representations[k].dtype) else: representations[k] = representations_update[k] return (representations, safe_key), None (representations, _), _ = hk.scan( ensemble_body, (representations, safe_key), None, length=num_ensemble) self.representations = representations self.batch = batch self.heads = {} for head_name, head_config in sorted(self.config.heads.items()): if not head_config.weight: continue # Do not instantiate zero-weight heads. head_factory = { 'masked_msa': modules.MaskedMsaHead, 'distogram': modules.DistogramHead, 'structure_module': folding_multimer.StructureModule, 'predicted_aligned_error': modules.PredictedAlignedErrorHead, 'predicted_lddt': modules.PredictedLDDTHead, 'experimentally_resolved': modules.ExperimentallyResolvedHead, }[head_name] self.heads[head_name] = (head_config, head_factory(head_config, self.global_config)) structure_module_output = None if 'entity_id' in batch and 'all_atom_positions' in batch: _, fold_module = self.heads['structure_module'] structure_module_output = fold_module(representations, batch, is_training) ret = {} ret['representations'] = representations for name, (head_config, module) in self.heads.items(): if name == 'structure_module' and structure_module_output is not None: ret[name] = structure_module_output representations['structure_module'] = structure_module_output.pop('act') # Skip confidence heads until StructureModule is executed. elif name in {'predicted_lddt', 'predicted_aligned_error', 'experimentally_resolved'}: continue else: ret[name] = module(representations, batch, is_training) # Add confidence heads after StructureModule is executed. if self.config.heads.get('predicted_lddt.weight', 0.0): name = 'predicted_lddt' head_config, module = self.heads[name] ret[name] = module(representations, batch, is_training) if self.config.heads.experimentally_resolved.weight: name = 'experimentally_resolved' head_config, module = self.heads[name] ret[name] = module(representations, batch, is_training) if self.config.heads.get('predicted_aligned_error.weight', 0.0): name = 'predicted_aligned_error' head_config, module = self.heads[name] ret[name] = module(representations, batch, is_training) # Will be used for ipTM computation. ret[name]['asym_id'] = batch['asym_id'] return ret class AlphaFold(hk.Module): """AlphaFold-Multimer model with recycling. """ def __init__(self, config, name='alphafold'): super().__init__(name=name) self.config = config self.global_config = config.global_config def __call__( self, batch, is_training, return_representations=False, safe_key=None): c = self.config impl = AlphaFoldIteration(c, self.global_config) if safe_key is None: safe_key = prng.SafeKey(hk.next_rng_key()) elif isinstance(safe_key, jnp.ndarray): safe_key = prng.SafeKey(safe_key) assert isinstance(batch, dict) num_res = batch['aatype'].shape[0] def get_prev(ret): new_prev = { 'prev_pos': ret['structure_module']['final_atom_positions'], 'prev_msa_first_row': ret['representations']['msa_first_row'], 'prev_pair': ret['representations']['pair'], } return jax.tree_map(jax.lax.stop_gradient, new_prev) def apply_network(prev, safe_key): recycled_batch = {**batch, **prev} return impl( batch=recycled_batch, is_training=is_training, safe_key=safe_key) prev = {} emb_config = self.config.embeddings_and_evoformer if emb_config.recycle_pos: prev['prev_pos'] = jnp.zeros( [num_res, residue_constants.atom_type_num, 3]) if emb_config.recycle_features: prev['prev_msa_first_row'] = jnp.zeros( [num_res, emb_config.msa_channel]) prev['prev_pair'] = jnp.zeros( [num_res, num_res, emb_config.pair_channel]) if self.config.num_recycle: if 'num_iter_recycling' in batch: # Training time: num_iter_recycling is in batch. # Value for each ensemble batch is the same, so arbitrarily taking 0-th. num_iter = batch['num_iter_recycling'][0] # Add insurance that even when ensembling, we will not run more # recyclings than the model is configured to run. num_iter = jnp.minimum(num_iter, c.num_recycle) else: # Eval mode or tests: use the maximum number of iterations. num_iter = c.num_recycle def distances(points): """Compute all pairwise distances for a set of points.""" return jnp.sqrt(jnp.sum((points[:, None] - points[None, :])**2, axis=-1)) def recycle_body(x): i, _, prev, safe_key = x safe_key1, safe_key2 = safe_key.split() if c.resample_msa_in_recycling else safe_key.duplicate() # pylint: disable=line-too-long ret = apply_network(prev=prev, safe_key=safe_key2) return i+1, prev, get_prev(ret), safe_key1 def recycle_cond(x): i, prev, next_in, _ = x ca_idx = residue_constants.atom_order['CA'] sq_diff = jnp.square(distances(prev['prev_pos'][:, ca_idx, :]) - distances(next_in['prev_pos'][:, ca_idx, :])) mask = batch['seq_mask'][:, None] * batch['seq_mask'][None, :] sq_diff = utils.mask_mean(mask, sq_diff) # Early stopping criteria based on criteria used in # AF2Complex: https://www.nature.com/articles/s41467-022-29394-2 diff = jnp.sqrt(sq_diff + 1e-8) # avoid bad numerics giving negatives less_than_max_recycles = (i < num_iter) has_exceeded_tolerance = ( (i == 0) | (diff > c.recycle_early_stop_tolerance)) return less_than_max_recycles & has_exceeded_tolerance if hk.running_init(): num_recycles, _, prev, safe_key = recycle_body( (0, prev, prev, safe_key)) else: num_recycles, _, prev, safe_key = hk.while_loop( recycle_cond, recycle_body, (0, prev, prev, safe_key)) else: # No recycling. num_recycles = 0 # Run extra iteration. ret = apply_network(prev=prev, safe_key=safe_key) if not return_representations: del ret['representations'] ret['num_recycles'] = num_recycles return ret class EmbeddingsAndEvoformer(hk.Module): """Embeds the input data and runs Evoformer. Produces the MSA, single and pair representations. """ def __init__(self, config, global_config, name='evoformer'): super().__init__(name=name) self.config = config self.global_config = global_config def _relative_encoding(self, batch): """Add relative position encodings. For position (i, j), the value is (i-j) clipped to [-k, k] and one-hotted. When not using 'use_chain_relative' the residue indices are used as is, e.g. for heteromers relative positions will be computed using the positions in the corresponding chains. When using 'use_chain_relative' we add an extra bin that denotes 'different chain'. Furthermore we also provide the relative chain index (i.e. sym_id) clipped and one-hotted to the network. And an extra feature which denotes whether they belong to the same chain type, i.e. it's 0 if they are in different heteromer chains and 1 otherwise. Args: batch: batch. Returns: Feature embedding using the features as described before. """ c = self.config gc = self.global_config rel_feats = [] pos = batch['residue_index'] asym_id = batch['asym_id'] asym_id_same = jnp.equal(asym_id[:, None], asym_id[None, :]) offset = pos[:, None] - pos[None, :] dtype = jnp.bfloat16 if gc.bfloat16 else jnp.float32 clipped_offset = jnp.clip( offset + c.max_relative_idx, a_min=0, a_max=2 * c.max_relative_idx) if c.use_chain_relative: final_offset = jnp.where(asym_id_same, clipped_offset, (2 * c.max_relative_idx + 1) * jnp.ones_like(clipped_offset)) rel_pos = jax.nn.one_hot(final_offset, 2 * c.max_relative_idx + 2) rel_feats.append(rel_pos) entity_id = batch['entity_id'] entity_id_same = jnp.equal(entity_id[:, None], entity_id[None, :]) rel_feats.append(entity_id_same.astype(rel_pos.dtype)[..., None]) sym_id = batch['sym_id'] rel_sym_id = sym_id[:, None] - sym_id[None, :] max_rel_chain = c.max_relative_chain clipped_rel_chain = jnp.clip( rel_sym_id + max_rel_chain, a_min=0, a_max=2 * max_rel_chain) final_rel_chain = jnp.where(entity_id_same, clipped_rel_chain, (2 * max_rel_chain + 1) * jnp.ones_like(clipped_rel_chain)) rel_chain = jax.nn.one_hot(final_rel_chain, 2 * c.max_relative_chain + 2) rel_feats.append(rel_chain) else: rel_pos = jax.nn.one_hot(clipped_offset, 2 * c.max_relative_idx + 1) rel_feats.append(rel_pos) rel_feat = jnp.concatenate(rel_feats, axis=-1) rel_feat = rel_feat.astype(dtype) return common_modules.Linear( c.pair_channel, name='position_activations')( rel_feat) def __call__(self, batch, is_training, safe_key=None): c = self.config gc = self.global_config batch = dict(batch) dtype = jnp.bfloat16 if gc.bfloat16 else jnp.float32 if safe_key is None: safe_key = prng.SafeKey(hk.next_rng_key()) output = {} batch['msa_profile'] = make_msa_profile(batch) with utils.bfloat16_context(): target_feat = jax.nn.one_hot(batch['aatype'], 21).astype(dtype) preprocess_1d = common_modules.Linear( c.msa_channel, name='preprocess_1d')( target_feat) safe_key, sample_key, mask_key = safe_key.split(3) batch = sample_msa(sample_key, batch, c.num_msa) batch = make_masked_msa(batch, mask_key, c.masked_msa) (batch['cluster_profile'], batch['cluster_deletion_mean']) = nearest_neighbor_clusters(batch) msa_feat = create_msa_feat(batch).astype(dtype) preprocess_msa = common_modules.Linear( c.msa_channel, name='preprocess_msa')( msa_feat) msa_activations = jnp.expand_dims(preprocess_1d, axis=0) + preprocess_msa left_single = common_modules.Linear( c.pair_channel, name='left_single')( target_feat) right_single = common_modules.Linear( c.pair_channel, name='right_single')( target_feat) pair_activations = left_single[:, None] + right_single[None] mask_2d = batch['seq_mask'][:, None] * batch['seq_mask'][None, :] mask_2d = mask_2d.astype(dtype) if c.recycle_pos: prev_pseudo_beta = modules.pseudo_beta_fn( batch['aatype'], batch['prev_pos'], None) dgram = modules.dgram_from_positions( prev_pseudo_beta, **self.config.prev_pos) dgram = dgram.astype(dtype) pair_activations += common_modules.Linear( c.pair_channel, name='prev_pos_linear')( dgram) if c.recycle_features: prev_msa_first_row = common_modules.LayerNorm( axis=[-1], create_scale=True, create_offset=True, name='prev_msa_first_row_norm')( batch['prev_msa_first_row']).astype(dtype) msa_activations = msa_activations.at[0].add(prev_msa_first_row) pair_activations += common_modules.LayerNorm( axis=[-1], create_scale=True, create_offset=True, name='prev_pair_norm')( batch['prev_pair']).astype(dtype) if c.max_relative_idx: pair_activations += self._relative_encoding(batch) if c.template.enabled: template_module = TemplateEmbedding(c.template, gc) template_batch = { 'template_aatype': batch['template_aatype'], 'template_all_atom_positions': batch['template_all_atom_positions'], 'template_all_atom_mask': batch['template_all_atom_mask'] } # Construct a mask such that only intra-chain template features are # computed, since all templates are for each chain individually. multichain_mask = batch['asym_id'][:, None] == batch['asym_id'][None, :] safe_key, safe_subkey = safe_key.split() template_act = template_module( query_embedding=pair_activations, template_batch=template_batch, padding_mask_2d=mask_2d, multichain_mask_2d=multichain_mask, is_training=is_training, safe_key=safe_subkey) pair_activations += template_act # Extra MSA stack. (extra_msa_feat, extra_msa_mask) = create_extra_msa_feature(batch, c.num_extra_msa) extra_msa_activations = common_modules.Linear( c.extra_msa_channel, name='extra_msa_activations')( extra_msa_feat).astype(dtype) extra_msa_mask = extra_msa_mask.astype(dtype) extra_evoformer_input = { 'msa': extra_msa_activations, 'pair': pair_activations, } extra_masks = {'msa': extra_msa_mask, 'pair': mask_2d} extra_evoformer_iteration = modules.EvoformerIteration( c.evoformer, gc, is_extra_msa=True, name='extra_msa_stack') def extra_evoformer_fn(x): act, safe_key = x safe_key, safe_subkey = safe_key.split() extra_evoformer_output = extra_evoformer_iteration( activations=act, masks=extra_masks, is_training=is_training, safe_key=safe_subkey) return (extra_evoformer_output, safe_key) if gc.use_remat: extra_evoformer_fn = hk.remat(extra_evoformer_fn) safe_key, safe_subkey = safe_key.split() extra_evoformer_stack = layer_stack.layer_stack( c.extra_msa_stack_num_block)( extra_evoformer_fn) extra_evoformer_output, safe_key = extra_evoformer_stack( (extra_evoformer_input, safe_subkey)) pair_activations = extra_evoformer_output['pair'] # Get the size of the MSA before potentially adding templates, so we # can crop out the templates later. num_msa_sequences = msa_activations.shape[0] evoformer_input = { 'msa': msa_activations, 'pair': pair_activations, } evoformer_masks = { 'msa': batch['msa_mask'].astype(dtype), 'pair': mask_2d } if c.template.enabled: template_features, template_masks = ( template_embedding_1d( batch=batch, num_channel=c.msa_channel, global_config=gc)) evoformer_input['msa'] = jnp.concatenate( [evoformer_input['msa'], template_features], axis=0) evoformer_masks['msa'] = jnp.concatenate( [evoformer_masks['msa'], template_masks], axis=0) evoformer_iteration = modules.EvoformerIteration( c.evoformer, gc, is_extra_msa=False, name='evoformer_iteration') def evoformer_fn(x): act, safe_key = x safe_key, safe_subkey = safe_key.split() evoformer_output = evoformer_iteration( activations=act, masks=evoformer_masks, is_training=is_training, safe_key=safe_subkey) return (evoformer_output, safe_key) if gc.use_remat: evoformer_fn = hk.remat(evoformer_fn) safe_key, safe_subkey = safe_key.split() evoformer_stack = layer_stack.layer_stack(c.evoformer_num_block)( evoformer_fn) def run_evoformer(evoformer_input): evoformer_output, _ = evoformer_stack((evoformer_input, safe_subkey)) return evoformer_output evoformer_output = run_evoformer(evoformer_input) msa_activations = evoformer_output['msa'] pair_activations = evoformer_output['pair'] single_activations = common_modules.Linear( c.seq_channel, name='single_activations')( msa_activations[0]) output.update({ 'single': single_activations, 'pair': pair_activations, # Crop away template rows such that they are not used in MaskedMsaHead. 'msa': msa_activations[:num_msa_sequences, :, :], 'msa_first_row': msa_activations[0], }) # Convert back to float32 if we're not saving memory. if not gc.bfloat16_output: for k, v in output.items(): if v.dtype == jnp.bfloat16: output[k] = v.astype(jnp.float32) return output class TemplateEmbedding(hk.Module): """Embed a set of templates.""" def __init__(self, config, global_config, name='template_embedding'): super().__init__(name=name) self.config = config self.global_config = global_config def __call__(self, query_embedding, template_batch, padding_mask_2d, multichain_mask_2d, is_training, safe_key=None): """Generate an embedding for a set of templates. Args: query_embedding: [num_res, num_res, num_channel] a query tensor that will be used to attend over the templates to remove the num_templates dimension. template_batch: A dictionary containing: `template_aatype`: [num_templates, num_res] aatype for each template. `template_all_atom_positions`: [num_templates, num_res, 37, 3] atom positions for all templates. `template_all_atom_mask`: [num_templates, num_res, 37] mask for each template. padding_mask_2d: [num_res, num_res] Pair mask for attention operations. multichain_mask_2d: [num_res, num_res] Mask indicating which residue pairs are intra-chain, used to mask out residue distance based features between chains. is_training: bool indicating where we are running in training mode. safe_key: random key generator. Returns: An embedding of size [num_res, num_res, num_channels] """ c = self.config if safe_key is None: safe_key = prng.SafeKey(hk.next_rng_key()) num_templates = template_batch['template_aatype'].shape[0] num_res, _, query_num_channels = query_embedding.shape # Embed each template separately. template_embedder = SingleTemplateEmbedding(self.config, self.global_config) def partial_template_embedder(template_aatype, template_all_atom_positions, template_all_atom_mask, unsafe_key): safe_key = prng.SafeKey(unsafe_key) return template_embedder(query_embedding, template_aatype, template_all_atom_positions, template_all_atom_mask, padding_mask_2d, multichain_mask_2d, is_training, safe_key) safe_key, unsafe_key = safe_key.split() unsafe_keys = jax.random.split(unsafe_key._key, num_templates) def scan_fn(carry, x): return carry + partial_template_embedder(*x), None scan_init = jnp.zeros((num_res, num_res, c.num_channels), dtype=query_embedding.dtype) summed_template_embeddings, _ = hk.scan( scan_fn, scan_init, (template_batch['template_aatype'], template_batch['template_all_atom_positions'], template_batch['template_all_atom_mask'], unsafe_keys)) embedding = summed_template_embeddings / num_templates embedding = jax.nn.relu(embedding) embedding = common_modules.Linear( query_num_channels, initializer='relu', name='output_linear')(embedding) return embedding class SingleTemplateEmbedding(hk.Module): """Embed a single template.""" def __init__(self, config, global_config, name='single_template_embedding'): super().__init__(name=name) self.config = config self.global_config = global_config def __call__(self, query_embedding, template_aatype, template_all_atom_positions, template_all_atom_mask, padding_mask_2d, multichain_mask_2d, is_training, safe_key): """Build the single template embedding graph. Args: query_embedding: (num_res, num_res, num_channels) - embedding of the query sequence/msa. template_aatype: [num_res] aatype for each template. template_all_atom_positions: [num_res, 37, 3] atom positions for all templates. template_all_atom_mask: [num_res, 37] mask for each template. padding_mask_2d: Padding mask (Note: this doesn't care if a template exists, unlike the template_pseudo_beta_mask). multichain_mask_2d: A mask indicating intra-chain residue pairs, used to mask out between chain distances/features when templates are for single chains. is_training: Are we in training mode. safe_key: Random key generator. Returns: A template embedding (num_res, num_res, num_channels). """ gc = self.global_config c = self.config assert padding_mask_2d.dtype == query_embedding.dtype dtype = query_embedding.dtype num_channels = self.config.num_channels def construct_input(query_embedding, template_aatype, template_all_atom_positions, template_all_atom_mask, multichain_mask_2d): # Compute distogram feature for the template. template_positions, pseudo_beta_mask = modules.pseudo_beta_fn( template_aatype, template_all_atom_positions, template_all_atom_mask) pseudo_beta_mask_2d = (pseudo_beta_mask[:, None] * pseudo_beta_mask[None, :]) pseudo_beta_mask_2d *= multichain_mask_2d template_dgram = modules.dgram_from_positions( template_positions, **self.config.dgram_features) template_dgram *= pseudo_beta_mask_2d[..., None] template_dgram = template_dgram.astype(dtype) pseudo_beta_mask_2d = pseudo_beta_mask_2d.astype(dtype) to_concat = [(template_dgram, 1), (pseudo_beta_mask_2d, 0)] aatype = jax.nn.one_hot(template_aatype, 22, axis=-1, dtype=dtype) to_concat.append((aatype[None, :, :], 1)) to_concat.append((aatype[:, None, :], 1)) # Compute a feature representing the normalized vector between each # backbone affine - i.e. in each residues local frame, what direction are # each of the other residues. raw_atom_pos = template_all_atom_positions if gc.bfloat16: # Vec3Arrays are required to be float32 raw_atom_pos = raw_atom_pos.astype(jnp.float32) atom_pos = geometry.Vec3Array.from_array(raw_atom_pos) rigid, backbone_mask = folding_multimer.make_backbone_affine( atom_pos, template_all_atom_mask, template_aatype) points = rigid.translation rigid_vec = rigid[:, None].inverse().apply_to_point(points) unit_vector = rigid_vec.normalized() unit_vector = [unit_vector.x, unit_vector.y, unit_vector.z] if gc.bfloat16: unit_vector = [x.astype(jnp.bfloat16) for x in unit_vector] backbone_mask = backbone_mask.astype(jnp.bfloat16) backbone_mask_2d = backbone_mask[:, None] * backbone_mask[None, :] backbone_mask_2d *= multichain_mask_2d unit_vector = [x*backbone_mask_2d for x in unit_vector] # Note that the backbone_mask takes into account C, CA and N (unlike # pseudo beta mask which just needs CB) so we add both masks as features. to_concat.extend([(x, 0) for x in unit_vector]) to_concat.append((backbone_mask_2d, 0)) query_embedding = common_modules.LayerNorm( axis=[-1], create_scale=True, create_offset=True, name='query_embedding_norm')( query_embedding) # Allow the template embedder to see the query embedding. Note this # contains the position relative feature, so this is how the network knows # which residues are next to each other. to_concat.append((query_embedding, 1)) act = 0 for i, (x, n_input_dims) in enumerate(to_concat): act += common_modules.Linear( num_channels, num_input_dims=n_input_dims, initializer='relu', name=f'template_pair_embedding_{i}')(x) return act act = construct_input(query_embedding, template_aatype, template_all_atom_positions, template_all_atom_mask, multichain_mask_2d) template_iteration = TemplateEmbeddingIteration( c.template_pair_stack, gc, name='template_embedding_iteration') def template_iteration_fn(x): act, safe_key = x safe_key, safe_subkey = safe_key.split() act = template_iteration( act=act, pair_mask=padding_mask_2d, is_training=is_training, safe_key=safe_subkey) return (act, safe_key) if gc.use_remat: template_iteration_fn = hk.remat(template_iteration_fn) safe_key, safe_subkey = safe_key.split() template_stack = layer_stack.layer_stack( c.template_pair_stack.num_block)( template_iteration_fn) act, safe_key = template_stack((act, safe_subkey)) act = common_modules.LayerNorm( axis=[-1], create_scale=True, create_offset=True, name='output_layer_norm')( act) return act class TemplateEmbeddingIteration(hk.Module): """Single Iteration of Template Embedding.""" def __init__(self, config, global_config, name='template_embedding_iteration'): super().__init__(name=name) self.config = config self.global_config = global_config def __call__(self, act, pair_mask, is_training=True, safe_key=None): """Build a single iteration of the template embedder. Args: act: [num_res, num_res, num_channel] Input pairwise activations. pair_mask: [num_res, num_res] padding mask. is_training: Whether to run in training mode. safe_key: Safe pseudo-random generator key. Returns: [num_res, num_res, num_channel] tensor of activations. """ c = self.config gc = self.global_config if safe_key is None: safe_key = prng.SafeKey(hk.next_rng_key()) dropout_wrapper_fn = functools.partial( modules.dropout_wrapper, is_training=is_training, global_config=gc) safe_key, *sub_keys = safe_key.split(20) sub_keys = iter(sub_keys) act = dropout_wrapper_fn( modules.TriangleMultiplication(c.triangle_multiplication_outgoing, gc, name='triangle_multiplication_outgoing'), act, pair_mask, safe_key=next(sub_keys)) act = dropout_wrapper_fn( modules.TriangleMultiplication(c.triangle_multiplication_incoming, gc, name='triangle_multiplication_incoming'), act, pair_mask, safe_key=next(sub_keys)) act = dropout_wrapper_fn( modules.TriangleAttention(c.triangle_attention_starting_node, gc, name='triangle_attention_starting_node'), act, pair_mask, safe_key=next(sub_keys)) act = dropout_wrapper_fn( modules.TriangleAttention(c.triangle_attention_ending_node, gc, name='triangle_attention_ending_node'), act, pair_mask, safe_key=next(sub_keys)) act = dropout_wrapper_fn( modules.Transition(c.pair_transition, gc, name='pair_transition'), act, pair_mask, safe_key=next(sub_keys)) return act def template_embedding_1d(batch, num_channel, global_config): """Embed templates into an (num_res, num_templates, num_channels) embedding. Args: batch: A batch containing: template_aatype, (num_templates, num_res) aatype for the templates. template_all_atom_positions, (num_templates, num_residues, 37, 3) atom positions for the templates. template_all_atom_mask, (num_templates, num_residues, 37) atom mask for each template. num_channel: The number of channels in the output. global_config: The global_config. Returns: An embedding of shape (num_templates, num_res, num_channels) and a mask of shape (num_templates, num_res). """ # Embed the templates aatypes. aatype_one_hot = jax.nn.one_hot(batch['template_aatype'], 22, axis=-1) num_templates = batch['template_aatype'].shape[0] all_chi_angles = [] all_chi_masks = [] for i in range(num_templates): atom_pos = geometry.Vec3Array.from_array( batch['template_all_atom_positions'][i, :, :, :]) template_chi_angles, template_chi_mask = all_atom_multimer.compute_chi_angles( atom_pos, batch['template_all_atom_mask'][i, :, :], batch['template_aatype'][i, :]) all_chi_angles.append(template_chi_angles) all_chi_masks.append(template_chi_mask) chi_angles = jnp.stack(all_chi_angles, axis=0) chi_mask = jnp.stack(all_chi_masks, axis=0) template_features = jnp.concatenate([ aatype_one_hot, jnp.sin(chi_angles) * chi_mask, jnp.cos(chi_angles) * chi_mask, chi_mask], axis=-1) template_mask = chi_mask[:, :, 0] if global_config.bfloat16: template_features = template_features.astype(jnp.bfloat16) template_mask = template_mask.astype(jnp.bfloat16) template_activations = common_modules.Linear( num_channel, initializer='relu', name='template_single_embedding')( template_features) template_activations = jax.nn.relu(template_activations) template_activations = common_modules.Linear( num_channel, initializer='relu', name='template_projection')( template_activations) return template_activations, template_mask ================================================ FILE: alphafold/model/prng.py ================================================ # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """A collection of utilities surrounding PRNG usage in protein folding.""" import haiku as hk import jax def safe_dropout(*, tensor, safe_key, rate, is_deterministic, is_training): if is_training and rate != 0.0 and not is_deterministic: return hk.dropout(safe_key.get(), rate, tensor) else: return tensor class SafeKey: """Safety wrapper for PRNG keys.""" def __init__(self, key): self._key = key self._used = False def _assert_not_used(self): if self._used: raise RuntimeError('Random key has been used previously.') def get(self): self._assert_not_used() self._used = True return self._key def split(self, num_keys=2): self._assert_not_used() self._used = True new_keys = jax.random.split(self._key, num_keys) return jax.tree_map(SafeKey, tuple(new_keys)) def duplicate(self, num_keys=2): self._assert_not_used() self._used = True return tuple(SafeKey(self._key) for _ in range(num_keys)) def _safe_key_flatten(safe_key): # Flatten transfers "ownership" to the tree return (safe_key._key,), safe_key._used # pylint: disable=protected-access def _safe_key_unflatten(aux_data, children): ret = SafeKey(children[0]) ret._used = aux_data # pylint: disable=protected-access return ret jax.tree_util.register_pytree_node( SafeKey, _safe_key_flatten, _safe_key_unflatten) ================================================ FILE: alphafold/model/prng_test.py ================================================ # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Tests for prng.""" from absl.testing import absltest from alphafold.model import prng import jax class PrngTest(absltest.TestCase): def test_key_reuse(self): init_key = jax.random.PRNGKey(42) safe_key = prng.SafeKey(init_key) _, safe_key = safe_key.split() raw_key = safe_key.get() self.assertNotEqual(raw_key[0], init_key[0]) self.assertNotEqual(raw_key[1], init_key[1]) with self.assertRaises(RuntimeError): safe_key.get() with self.assertRaises(RuntimeError): safe_key.split() with self.assertRaises(RuntimeError): safe_key.duplicate() if __name__ == '__main__': absltest.main() ================================================ FILE: alphafold/model/quat_affine.py ================================================ # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Quaternion geometry modules. This introduces a representation of coordinate frames that is based around a ‘QuatAffine’ object. This object describes an array of coordinate frames. It consists of vectors corresponding to the origin of the frames as well as orientations which are stored in two ways, as unit quaternions as well as a rotation matrices. The rotation matrices are derived from the unit quaternions and the two are kept in sync. For an explanation of the relation between unit quaternions and rotations see https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation This representation is used in the model for the backbone frames. One important thing to note here, is that while we update both representations the jit compiler is going to ensure that only the parts that are actually used are executed. """ import functools from typing import Tuple import jax import jax.numpy as jnp import numpy as np # pylint: disable=bad-whitespace QUAT_TO_ROT = np.zeros((4, 4, 3, 3), dtype=np.float32) QUAT_TO_ROT[0, 0] = [[ 1, 0, 0], [ 0, 1, 0], [ 0, 0, 1]] # rr QUAT_TO_ROT[1, 1] = [[ 1, 0, 0], [ 0,-1, 0], [ 0, 0,-1]] # ii QUAT_TO_ROT[2, 2] = [[-1, 0, 0], [ 0, 1, 0], [ 0, 0,-1]] # jj QUAT_TO_ROT[3, 3] = [[-1, 0, 0], [ 0,-1, 0], [ 0, 0, 1]] # kk QUAT_TO_ROT[1, 2] = [[ 0, 2, 0], [ 2, 0, 0], [ 0, 0, 0]] # ij QUAT_TO_ROT[1, 3] = [[ 0, 0, 2], [ 0, 0, 0], [ 2, 0, 0]] # ik QUAT_TO_ROT[2, 3] = [[ 0, 0, 0], [ 0, 0, 2], [ 0, 2, 0]] # jk QUAT_TO_ROT[0, 1] = [[ 0, 0, 0], [ 0, 0,-2], [ 0, 2, 0]] # ir QUAT_TO_ROT[0, 2] = [[ 0, 0, 2], [ 0, 0, 0], [-2, 0, 0]] # jr QUAT_TO_ROT[0, 3] = [[ 0,-2, 0], [ 2, 0, 0], [ 0, 0, 0]] # kr QUAT_MULTIPLY = np.zeros((4, 4, 4), dtype=np.float32) QUAT_MULTIPLY[:, :, 0] = [[ 1, 0, 0, 0], [ 0,-1, 0, 0], [ 0, 0,-1, 0], [ 0, 0, 0,-1]] QUAT_MULTIPLY[:, :, 1] = [[ 0, 1, 0, 0], [ 1, 0, 0, 0], [ 0, 0, 0, 1], [ 0, 0,-1, 0]] QUAT_MULTIPLY[:, :, 2] = [[ 0, 0, 1, 0], [ 0, 0, 0,-1], [ 1, 0, 0, 0], [ 0, 1, 0, 0]] QUAT_MULTIPLY[:, :, 3] = [[ 0, 0, 0, 1], [ 0, 0, 1, 0], [ 0,-1, 0, 0], [ 1, 0, 0, 0]] QUAT_MULTIPLY_BY_VEC = QUAT_MULTIPLY[:, 1:, :] # pylint: enable=bad-whitespace def rot_to_quat(rot, unstack_inputs=False): """Convert rotation matrix to quaternion. Note that this function calls self_adjoint_eig which is extremely expensive on the GPU. If at all possible, this function should run on the CPU. Args: rot: rotation matrix (see below for format). unstack_inputs: If true, rotation matrix should be shape (..., 3, 3) otherwise the rotation matrix should be a list of lists of tensors. Returns: Quaternion as (..., 4) tensor. """ if unstack_inputs: rot = [jnp.moveaxis(x, -1, 0) for x in jnp.moveaxis(rot, -2, 0)] [[xx, xy, xz], [yx, yy, yz], [zx, zy, zz]] = rot # pylint: disable=bad-whitespace k = [[ xx + yy + zz, zy - yz, xz - zx, yx - xy,], [ zy - yz, xx - yy - zz, xy + yx, xz + zx,], [ xz - zx, xy + yx, yy - xx - zz, yz + zy,], [ yx - xy, xz + zx, yz + zy, zz - xx - yy,]] # pylint: enable=bad-whitespace k = (1./3.) * jnp.stack([jnp.stack(x, axis=-1) for x in k], axis=-2) # Get eigenvalues in non-decreasing order and associated. _, qs = jnp.linalg.eigh(k) return qs[..., -1] def rot_list_to_tensor(rot_list): """Convert list of lists to rotation tensor.""" return jnp.stack( [jnp.stack(rot_list[0], axis=-1), jnp.stack(rot_list[1], axis=-1), jnp.stack(rot_list[2], axis=-1)], axis=-2) def vec_list_to_tensor(vec_list): """Convert list to vector tensor.""" return jnp.stack(vec_list, axis=-1) def quat_to_rot(normalized_quat): """Convert a normalized quaternion to a rotation matrix.""" rot_tensor = jnp.sum( np.reshape(QUAT_TO_ROT, (4, 4, 9)) * normalized_quat[..., :, None, None] * normalized_quat[..., None, :, None], axis=(-3, -2)) rot = jnp.moveaxis(rot_tensor, -1, 0) # Unstack. return [[rot[0], rot[1], rot[2]], [rot[3], rot[4], rot[5]], [rot[6], rot[7], rot[8]]] def quat_multiply_by_vec(quat, vec): """Multiply a quaternion by a pure-vector quaternion.""" return jnp.sum( QUAT_MULTIPLY_BY_VEC * quat[..., :, None, None] * vec[..., None, :, None], axis=(-3, -2)) def quat_multiply(quat1, quat2): """Multiply a quaternion by another quaternion.""" return jnp.sum( QUAT_MULTIPLY * quat1[..., :, None, None] * quat2[..., None, :, None], axis=(-3, -2)) def apply_rot_to_vec(rot, vec, unstack=False): """Multiply rotation matrix by a vector.""" if unstack: x, y, z = [vec[:, i] for i in range(3)] else: x, y, z = vec return [rot[0][0] * x + rot[0][1] * y + rot[0][2] * z, rot[1][0] * x + rot[1][1] * y + rot[1][2] * z, rot[2][0] * x + rot[2][1] * y + rot[2][2] * z] def apply_inverse_rot_to_vec(rot, vec): """Multiply the inverse of a rotation matrix by a vector.""" # Inverse rotation is just transpose return [rot[0][0] * vec[0] + rot[1][0] * vec[1] + rot[2][0] * vec[2], rot[0][1] * vec[0] + rot[1][1] * vec[1] + rot[2][1] * vec[2], rot[0][2] * vec[0] + rot[1][2] * vec[1] + rot[2][2] * vec[2]] class QuatAffine(object): """Affine transformation represented by quaternion and vector.""" def __init__(self, quaternion, translation, rotation=None, normalize=True, unstack_inputs=False): """Initialize from quaternion and translation. Args: quaternion: Rotation represented by a quaternion, to be applied before translation. Must be a unit quaternion unless normalize==True. translation: Translation represented as a vector. rotation: Same rotation as the quaternion, represented as a (..., 3, 3) tensor. If None, rotation will be calculated from the quaternion. normalize: If True, l2 normalize the quaternion on input. unstack_inputs: If True, translation is a vector with last component 3 """ if quaternion is not None: assert quaternion.shape[-1] == 4 if unstack_inputs: if rotation is not None: rotation = [jnp.moveaxis(x, -1, 0) # Unstack. for x in jnp.moveaxis(rotation, -2, 0)] # Unstack. translation = jnp.moveaxis(translation, -1, 0) # Unstack. if normalize and quaternion is not None: quaternion = quaternion / jnp.linalg.norm(quaternion, axis=-1, keepdims=True) if rotation is None: rotation = quat_to_rot(quaternion) self.quaternion = quaternion self.rotation = [list(row) for row in rotation] self.translation = list(translation) assert all(len(row) == 3 for row in self.rotation) assert len(self.translation) == 3 def to_tensor(self): return jnp.concatenate( [self.quaternion] + [jnp.expand_dims(x, axis=-1) for x in self.translation], axis=-1) def apply_tensor_fn(self, tensor_fn): """Return a new QuatAffine with tensor_fn applied (e.g. stop_gradient).""" return QuatAffine( tensor_fn(self.quaternion), [tensor_fn(x) for x in self.translation], rotation=[[tensor_fn(x) for x in row] for row in self.rotation], normalize=False) def apply_rotation_tensor_fn(self, tensor_fn): """Return a new QuatAffine with tensor_fn applied to the rotation part.""" return QuatAffine( tensor_fn(self.quaternion), [x for x in self.translation], rotation=[[tensor_fn(x) for x in row] for row in self.rotation], normalize=False) def scale_translation(self, position_scale): """Return a new quat affine with a different scale for translation.""" return QuatAffine( self.quaternion, [x * position_scale for x in self.translation], rotation=[[x for x in row] for row in self.rotation], normalize=False) @classmethod def from_tensor(cls, tensor, normalize=False): quaternion, tx, ty, tz = jnp.split(tensor, [4, 5, 6], axis=-1) return cls(quaternion, [tx[..., 0], ty[..., 0], tz[..., 0]], normalize=normalize) def pre_compose(self, update): """Return a new QuatAffine which applies the transformation update first. Args: update: Length-6 vector. 3-vector of x, y, and z such that the quaternion update is (1, x, y, z) and zero for the 3-vector is the identity quaternion. 3-vector for translation concatenated. Returns: New QuatAffine object. """ vector_quaternion_update, x, y, z = jnp.split(update, [3, 4, 5], axis=-1) trans_update = [jnp.squeeze(x, axis=-1), jnp.squeeze(y, axis=-1), jnp.squeeze(z, axis=-1)] new_quaternion = (self.quaternion + quat_multiply_by_vec(self.quaternion, vector_quaternion_update)) trans_update = apply_rot_to_vec(self.rotation, trans_update) new_translation = [ self.translation[0] + trans_update[0], self.translation[1] + trans_update[1], self.translation[2] + trans_update[2]] return QuatAffine(new_quaternion, new_translation) def apply_to_point(self, point, extra_dims=0): """Apply affine to a point. Args: point: List of 3 tensors to apply affine. extra_dims: Number of dimensions at the end of the transformed_point shape that are not present in the rotation and translation. The most common use is rotation N points at once with extra_dims=1 for use in a network. Returns: Transformed point after applying affine. """ rotation = self.rotation translation = self.translation for _ in range(extra_dims): expand_fn = functools.partial(jnp.expand_dims, axis=-1) rotation = jax.tree_map(expand_fn, rotation) translation = jax.tree_map(expand_fn, translation) rot_point = apply_rot_to_vec(rotation, point) return [ rot_point[0] + translation[0], rot_point[1] + translation[1], rot_point[2] + translation[2]] def invert_point(self, transformed_point, extra_dims=0): """Apply inverse of transformation to a point. Args: transformed_point: List of 3 tensors to apply affine extra_dims: Number of dimensions at the end of the transformed_point shape that are not present in the rotation and translation. The most common use is rotation N points at once with extra_dims=1 for use in a network. Returns: Transformed point after applying affine. """ rotation = self.rotation translation = self.translation for _ in range(extra_dims): expand_fn = functools.partial(jnp.expand_dims, axis=-1) rotation = jax.tree_map(expand_fn, rotation) translation = jax.tree_map(expand_fn, translation) rot_point = [ transformed_point[0] - translation[0], transformed_point[1] - translation[1], transformed_point[2] - translation[2]] return apply_inverse_rot_to_vec(rotation, rot_point) def __repr__(self): return 'QuatAffine(%r, %r)' % (self.quaternion, self.translation) def _multiply(a, b): return jnp.stack([ jnp.array([a[0][0]*b[0][0] + a[0][1]*b[1][0] + a[0][2]*b[2][0], a[0][0]*b[0][1] + a[0][1]*b[1][1] + a[0][2]*b[2][1], a[0][0]*b[0][2] + a[0][1]*b[1][2] + a[0][2]*b[2][2]]), jnp.array([a[1][0]*b[0][0] + a[1][1]*b[1][0] + a[1][2]*b[2][0], a[1][0]*b[0][1] + a[1][1]*b[1][1] + a[1][2]*b[2][1], a[1][0]*b[0][2] + a[1][1]*b[1][2] + a[1][2]*b[2][2]]), jnp.array([a[2][0]*b[0][0] + a[2][1]*b[1][0] + a[2][2]*b[2][0], a[2][0]*b[0][1] + a[2][1]*b[1][1] + a[2][2]*b[2][1], a[2][0]*b[0][2] + a[2][1]*b[1][2] + a[2][2]*b[2][2]])]) def make_canonical_transform( n_xyz: jnp.ndarray, ca_xyz: jnp.ndarray, c_xyz: jnp.ndarray) -> Tuple[jnp.ndarray, jnp.ndarray]: """Returns translation and rotation matrices to canonicalize residue atoms. Note that this method does not take care of symmetries. If you provide the atom positions in the non-standard way, the N atom will end up not at [-0.527250, 1.359329, 0.0] but instead at [-0.527250, -1.359329, 0.0]. You need to take care of such cases in your code. Args: n_xyz: An array of shape [batch, 3] of nitrogen xyz coordinates. ca_xyz: An array of shape [batch, 3] of carbon alpha xyz coordinates. c_xyz: An array of shape [batch, 3] of carbon xyz coordinates. Returns: A tuple (translation, rotation) where: translation is an array of shape [batch, 3] defining the translation. rotation is an array of shape [batch, 3, 3] defining the rotation. After applying the translation and rotation to all atoms in a residue: * All atoms will be shifted so that CA is at the origin, * All atoms will be rotated so that C is at the x-axis, * All atoms will be shifted so that N is in the xy plane. """ assert len(n_xyz.shape) == 2, n_xyz.shape assert n_xyz.shape[-1] == 3, n_xyz.shape assert n_xyz.shape == ca_xyz.shape == c_xyz.shape, ( n_xyz.shape, ca_xyz.shape, c_xyz.shape) # Place CA at the origin. translation = -ca_xyz n_xyz = n_xyz + translation c_xyz = c_xyz + translation # Place C on the x-axis. c_x, c_y, c_z = [c_xyz[:, i] for i in range(3)] # Rotate by angle c1 in the x-y plane (around the z-axis). sin_c1 = -c_y / jnp.sqrt(1e-20 + c_x**2 + c_y**2) cos_c1 = c_x / jnp.sqrt(1e-20 + c_x**2 + c_y**2) zeros = jnp.zeros_like(sin_c1) ones = jnp.ones_like(sin_c1) # pylint: disable=bad-whitespace c1_rot_matrix = jnp.stack([jnp.array([cos_c1, -sin_c1, zeros]), jnp.array([sin_c1, cos_c1, zeros]), jnp.array([zeros, zeros, ones])]) # Rotate by angle c2 in the x-z plane (around the y-axis). sin_c2 = c_z / jnp.sqrt(1e-20 + c_x**2 + c_y**2 + c_z**2) cos_c2 = jnp.sqrt(c_x**2 + c_y**2) / jnp.sqrt( 1e-20 + c_x**2 + c_y**2 + c_z**2) c2_rot_matrix = jnp.stack([jnp.array([cos_c2, zeros, sin_c2]), jnp.array([zeros, ones, zeros]), jnp.array([-sin_c2, zeros, cos_c2])]) c_rot_matrix = _multiply(c2_rot_matrix, c1_rot_matrix) n_xyz = jnp.stack(apply_rot_to_vec(c_rot_matrix, n_xyz, unstack=True)).T # Place N in the x-y plane. _, n_y, n_z = [n_xyz[:, i] for i in range(3)] # Rotate by angle alpha in the y-z plane (around the x-axis). sin_n = -n_z / jnp.sqrt(1e-20 + n_y**2 + n_z**2) cos_n = n_y / jnp.sqrt(1e-20 + n_y**2 + n_z**2) n_rot_matrix = jnp.stack([jnp.array([ones, zeros, zeros]), jnp.array([zeros, cos_n, -sin_n]), jnp.array([zeros, sin_n, cos_n])]) # pylint: enable=bad-whitespace return (translation, jnp.transpose(_multiply(n_rot_matrix, c_rot_matrix), [2, 0, 1])) def make_transform_from_reference( n_xyz: jnp.ndarray, ca_xyz: jnp.ndarray, c_xyz: jnp.ndarray) -> Tuple[jnp.ndarray, jnp.ndarray]: """Returns rotation and translation matrices to convert from reference. Note that this method does not take care of symmetries. If you provide the atom positions in the non-standard way, the N atom will end up not at [-0.527250, 1.359329, 0.0] but instead at [-0.527250, -1.359329, 0.0]. You need to take care of such cases in your code. Args: n_xyz: An array of shape [batch, 3] of nitrogen xyz coordinates. ca_xyz: An array of shape [batch, 3] of carbon alpha xyz coordinates. c_xyz: An array of shape [batch, 3] of carbon xyz coordinates. Returns: A tuple (rotation, translation) where: rotation is an array of shape [batch, 3, 3] defining the rotation. translation is an array of shape [batch, 3] defining the translation. After applying the translation and rotation to the reference backbone, the coordinates will approximately equal to the input coordinates. The order of translation and rotation differs from make_canonical_transform because the rotation from this function should be applied before the translation, unlike make_canonical_transform. """ translation, rotation = make_canonical_transform(n_xyz, ca_xyz, c_xyz) return np.transpose(rotation, (0, 2, 1)), -translation ================================================ FILE: alphafold/model/quat_affine_test.py ================================================ # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Tests for quat_affine.""" from absl import logging from absl.testing import absltest from alphafold.model import quat_affine import jax import jax.numpy as jnp import numpy as np VERBOSE = False np.set_printoptions(precision=3, suppress=True) r2t = quat_affine.rot_list_to_tensor v2t = quat_affine.vec_list_to_tensor q2r = lambda q: r2t(quat_affine.quat_to_rot(q)) class QuatAffineTest(absltest.TestCase): def _assert_check(self, to_check, tol=1e-5): for k, (correct, generated) in to_check.items(): if VERBOSE: logging.info(k) logging.info('Correct %s', correct) logging.info('Predicted %s', generated) self.assertLess(np.max(np.abs(correct - generated)), tol) def test_conversion(self): quat = jnp.array([-2., 5., -1., 4.]) rotation = jnp.array([ [0.26087, 0.130435, 0.956522], [-0.565217, -0.782609, 0.26087], [0.782609, -0.608696, -0.130435]]) translation = jnp.array([1., -3., 4.]) point = jnp.array([0.7, 3.2, -2.9]) a = quat_affine.QuatAffine(quat, translation, unstack_inputs=True) true_new_point = jnp.matmul(rotation, point[:, None])[:, 0] + translation self._assert_check({ 'rot': (rotation, r2t(a.rotation)), 'trans': (translation, v2t(a.translation)), 'point': (true_new_point, v2t(a.apply_to_point(jnp.moveaxis(point, -1, 0)))), # Because of the double cover, we must be careful and compare rotations 'quat': (q2r(a.quaternion), q2r(quat_affine.rot_to_quat(a.rotation))), }) def test_double_cover(self): """Test that -q is the same rotation as q.""" rng = jax.random.PRNGKey(42) keys = jax.random.split(rng) q = jax.random.normal(keys[0], (2, 4)) trans = jax.random.normal(keys[1], (2, 3)) a1 = quat_affine.QuatAffine(q, trans, unstack_inputs=True) a2 = quat_affine.QuatAffine(-q, trans, unstack_inputs=True) self._assert_check({ 'rot': (r2t(a1.rotation), r2t(a2.rotation)), 'trans': (v2t(a1.translation), v2t(a2.translation)), }) def test_homomorphism(self): rng = jax.random.PRNGKey(42) keys = jax.random.split(rng, 4) vec_q1 = jax.random.normal(keys[0], (2, 3)) q1 = jnp.concatenate([ jnp.ones_like(vec_q1)[:, :1], vec_q1], axis=-1) q2 = jax.random.normal(keys[1], (2, 4)) t1 = jax.random.normal(keys[2], (2, 3)) t2 = jax.random.normal(keys[3], (2, 3)) a1 = quat_affine.QuatAffine(q1, t1, unstack_inputs=True) a2 = quat_affine.QuatAffine(q2, t2, unstack_inputs=True) a21 = a2.pre_compose(jnp.concatenate([vec_q1, t1], axis=-1)) rng, key = jax.random.split(rng) x = jax.random.normal(key, (2, 3)) new_x = a21.apply_to_point(jnp.moveaxis(x, -1, 0)) new_x_apply2 = a2.apply_to_point(a1.apply_to_point(jnp.moveaxis(x, -1, 0))) self._assert_check({ 'quat': (q2r(quat_affine.quat_multiply(a2.quaternion, a1.quaternion)), q2r(a21.quaternion)), 'rot': (jnp.matmul(r2t(a2.rotation), r2t(a1.rotation)), r2t(a21.rotation)), 'point': (v2t(new_x_apply2), v2t(new_x)), 'inverse': (x, v2t(a21.invert_point(new_x))), }) def test_batching(self): """Test that affine applies batchwise.""" rng = jax.random.PRNGKey(42) keys = jax.random.split(rng, 3) q = jax.random.uniform(keys[0], (5, 2, 4)) t = jax.random.uniform(keys[1], (2, 3)) x = jax.random.uniform(keys[2], (5, 1, 3)) a = quat_affine.QuatAffine(q, t, unstack_inputs=True) y = v2t(a.apply_to_point(jnp.moveaxis(x, -1, 0))) y_list = [] for i in range(5): for j in range(2): a_local = quat_affine.QuatAffine(q[i, j], t[j], unstack_inputs=True) y_local = v2t(a_local.apply_to_point(jnp.moveaxis(x[i, 0], -1, 0))) y_list.append(y_local) y_combine = jnp.reshape(jnp.stack(y_list, axis=0), (5, 2, 3)) self._assert_check({ 'batch': (y_combine, y), 'quat': (q2r(a.quaternion), q2r(quat_affine.rot_to_quat(a.rotation))), }) def assertAllClose(self, a, b, rtol=1e-06, atol=1e-06): self.assertTrue(np.allclose(a, b, rtol=rtol, atol=atol)) def assertAllEqual(self, a, b): self.assertTrue(np.all(np.array(a) == np.array(b))) if __name__ == '__main__': absltest.main() ================================================ FILE: alphafold/model/r3.py ================================================ # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Transformations for 3D coordinates. This Module contains objects for representing Vectors (Vecs), Rotation Matrices (Rots) and proper Rigid transformation (Rigids). These are represented as named tuples with arrays for each entry, for example a set of [N, M] points would be represented as a Vecs object with arrays of shape [N, M] for x, y and z. This is being done to improve readability by making it very clear what objects are geometric objects rather than relying on comments and array shapes. Another reason for this is to avoid using matrix multiplication primitives like matmul or einsum, on modern accelerator hardware these can end up on specialized cores such as tensor cores on GPU or the MXU on cloud TPUs, this often involves lower computational precision which can be problematic for coordinate geometry. Also these cores are typically optimized for larger matrices than 3 dimensional, this code is written to avoid any unintended use of these cores on both GPUs and TPUs. """ import collections from typing import List from alphafold.model import quat_affine import jax.numpy as jnp import tree # Array of 3-component vectors, stored as individual array for # each component. Vecs = collections.namedtuple('Vecs', ['x', 'y', 'z']) # Array of 3x3 rotation matrices, stored as individual array for # each component. Rots = collections.namedtuple('Rots', ['xx', 'xy', 'xz', 'yx', 'yy', 'yz', 'zx', 'zy', 'zz']) # Array of rigid 3D transformations, stored as array of rotations and # array of translations. Rigids = collections.namedtuple('Rigids', ['rot', 'trans']) def squared_difference(x, y): return jnp.square(x - y) def invert_rigids(r: Rigids) -> Rigids: """Computes group inverse of rigid transformations 'r'.""" inv_rots = invert_rots(r.rot) t = rots_mul_vecs(inv_rots, r.trans) inv_trans = Vecs(-t.x, -t.y, -t.z) return Rigids(inv_rots, inv_trans) def invert_rots(m: Rots) -> Rots: """Computes inverse of rotations 'm'.""" return Rots(m.xx, m.yx, m.zx, m.xy, m.yy, m.zy, m.xz, m.yz, m.zz) def rigids_from_3_points( point_on_neg_x_axis: Vecs, # shape (...) origin: Vecs, # shape (...) point_on_xy_plane: Vecs, # shape (...) ) -> Rigids: # shape (...) """Create Rigids from 3 points. Jumper et al. (2021) Suppl. Alg. 21 "rigidFrom3Points" This creates a set of rigid transformations from 3 points by Gram Schmidt orthogonalization. Args: point_on_neg_x_axis: Vecs corresponding to points on the negative x axis origin: Origin of resulting rigid transformations point_on_xy_plane: Vecs corresponding to points in the xy plane Returns: Rigid transformations from global frame to local frames derived from the input points. """ m = rots_from_two_vecs( e0_unnormalized=vecs_sub(origin, point_on_neg_x_axis), e1_unnormalized=vecs_sub(point_on_xy_plane, origin)) return Rigids(rot=m, trans=origin) def rigids_from_list(l: List[jnp.ndarray]) -> Rigids: """Converts flat list of arrays to rigid transformations.""" assert len(l) == 12 return Rigids(Rots(*(l[:9])), Vecs(*(l[9:]))) def rigids_from_quataffine(a: quat_affine.QuatAffine) -> Rigids: """Converts QuatAffine object to the corresponding Rigids object.""" return Rigids(Rots(*tree.flatten(a.rotation)), Vecs(*a.translation)) def rigids_from_tensor4x4( m: jnp.ndarray # shape (..., 4, 4) ) -> Rigids: # shape (...) """Construct Rigids object from an 4x4 array. Here the 4x4 is representing the transformation in homogeneous coordinates. Args: m: Array representing transformations in homogeneous coordinates. Returns: Rigids object corresponding to transformations m """ assert m.shape[-1] == 4 assert m.shape[-2] == 4 return Rigids( Rots(m[..., 0, 0], m[..., 0, 1], m[..., 0, 2], m[..., 1, 0], m[..., 1, 1], m[..., 1, 2], m[..., 2, 0], m[..., 2, 1], m[..., 2, 2]), Vecs(m[..., 0, 3], m[..., 1, 3], m[..., 2, 3])) def rigids_from_tensor_flat9( m: jnp.ndarray # shape (..., 9) ) -> Rigids: # shape (...) """Flat9 encoding: first two columns of rotation matrix + translation.""" assert m.shape[-1] == 9 e0 = Vecs(m[..., 0], m[..., 1], m[..., 2]) e1 = Vecs(m[..., 3], m[..., 4], m[..., 5]) trans = Vecs(m[..., 6], m[..., 7], m[..., 8]) return Rigids(rot=rots_from_two_vecs(e0, e1), trans=trans) def rigids_from_tensor_flat12( m: jnp.ndarray # shape (..., 12) ) -> Rigids: # shape (...) """Flat12 encoding: rotation matrix (9 floats) + translation (3 floats).""" assert m.shape[-1] == 12 x = jnp.moveaxis(m, -1, 0) # Unstack return Rigids(Rots(*x[:9]), Vecs(*x[9:])) def rigids_mul_rigids(a: Rigids, b: Rigids) -> Rigids: """Group composition of Rigids 'a' and 'b'.""" return Rigids( rots_mul_rots(a.rot, b.rot), vecs_add(a.trans, rots_mul_vecs(a.rot, b.trans))) def rigids_mul_rots(r: Rigids, m: Rots) -> Rigids: """Compose rigid transformations 'r' with rotations 'm'.""" return Rigids(rots_mul_rots(r.rot, m), r.trans) def rigids_mul_vecs(r: Rigids, v: Vecs) -> Vecs: """Apply rigid transforms 'r' to points 'v'.""" return vecs_add(rots_mul_vecs(r.rot, v), r.trans) def rigids_to_list(r: Rigids) -> List[jnp.ndarray]: """Turn Rigids into flat list, inverse of 'rigids_from_list'.""" return list(r.rot) + list(r.trans) def rigids_to_quataffine(r: Rigids) -> quat_affine.QuatAffine: """Convert Rigids r into QuatAffine, inverse of 'rigids_from_quataffine'.""" return quat_affine.QuatAffine( quaternion=None, rotation=[[r.rot.xx, r.rot.xy, r.rot.xz], [r.rot.yx, r.rot.yy, r.rot.yz], [r.rot.zx, r.rot.zy, r.rot.zz]], translation=[r.trans.x, r.trans.y, r.trans.z]) def rigids_to_tensor_flat9( r: Rigids # shape (...) ) -> jnp.ndarray: # shape (..., 9) """Flat9 encoding: first two columns of rotation matrix + translation.""" return jnp.stack( [r.rot.xx, r.rot.yx, r.rot.zx, r.rot.xy, r.rot.yy, r.rot.zy] + list(r.trans), axis=-1) def rigids_to_tensor_flat12( r: Rigids # shape (...) ) -> jnp.ndarray: # shape (..., 12) """Flat12 encoding: rotation matrix (9 floats) + translation (3 floats).""" return jnp.stack(list(r.rot) + list(r.trans), axis=-1) def rots_from_tensor3x3( m: jnp.ndarray, # shape (..., 3, 3) ) -> Rots: # shape (...) """Convert rotations represented as (3, 3) array to Rots.""" assert m.shape[-1] == 3 assert m.shape[-2] == 3 return Rots(m[..., 0, 0], m[..., 0, 1], m[..., 0, 2], m[..., 1, 0], m[..., 1, 1], m[..., 1, 2], m[..., 2, 0], m[..., 2, 1], m[..., 2, 2]) def rots_from_two_vecs(e0_unnormalized: Vecs, e1_unnormalized: Vecs) -> Rots: """Create rotation matrices from unnormalized vectors for the x and y-axes. This creates a rotation matrix from two vectors using Gram-Schmidt orthogonalization. Args: e0_unnormalized: vectors lying along x-axis of resulting rotation e1_unnormalized: vectors lying in xy-plane of resulting rotation Returns: Rotations resulting from Gram-Schmidt procedure. """ # Normalize the unit vector for the x-axis, e0. e0 = vecs_robust_normalize(e0_unnormalized) # make e1 perpendicular to e0. c = vecs_dot_vecs(e1_unnormalized, e0) e1 = Vecs(e1_unnormalized.x - c * e0.x, e1_unnormalized.y - c * e0.y, e1_unnormalized.z - c * e0.z) e1 = vecs_robust_normalize(e1) # Compute e2 as cross product of e0 and e1. e2 = vecs_cross_vecs(e0, e1) return Rots(e0.x, e1.x, e2.x, e0.y, e1.y, e2.y, e0.z, e1.z, e2.z) def rots_mul_rots(a: Rots, b: Rots) -> Rots: """Composition of rotations 'a' and 'b'.""" c0 = rots_mul_vecs(a, Vecs(b.xx, b.yx, b.zx)) c1 = rots_mul_vecs(a, Vecs(b.xy, b.yy, b.zy)) c2 = rots_mul_vecs(a, Vecs(b.xz, b.yz, b.zz)) return Rots(c0.x, c1.x, c2.x, c0.y, c1.y, c2.y, c0.z, c1.z, c2.z) def rots_mul_vecs(m: Rots, v: Vecs) -> Vecs: """Apply rotations 'm' to vectors 'v'.""" return Vecs(m.xx * v.x + m.xy * v.y + m.xz * v.z, m.yx * v.x + m.yy * v.y + m.yz * v.z, m.zx * v.x + m.zy * v.y + m.zz * v.z) def vecs_add(v1: Vecs, v2: Vecs) -> Vecs: """Add two vectors 'v1' and 'v2'.""" return Vecs(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z) def vecs_dot_vecs(v1: Vecs, v2: Vecs) -> jnp.ndarray: """Dot product of vectors 'v1' and 'v2'.""" return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z def vecs_cross_vecs(v1: Vecs, v2: Vecs) -> Vecs: """Cross product of vectors 'v1' and 'v2'.""" return Vecs(v1.y * v2.z - v1.z * v2.y, v1.z * v2.x - v1.x * v2.z, v1.x * v2.y - v1.y * v2.x) def vecs_from_tensor(x: jnp.ndarray # shape (..., 3) ) -> Vecs: # shape (...) """Converts from tensor of shape (3,) to Vecs.""" num_components = x.shape[-1] assert num_components == 3 return Vecs(x[..., 0], x[..., 1], x[..., 2]) def vecs_robust_normalize(v: Vecs, epsilon: float = 1e-8) -> Vecs: """Normalizes vectors 'v'. Args: v: vectors to be normalized. epsilon: small regularizer added to squared norm before taking square root. Returns: normalized vectors """ norms = vecs_robust_norm(v, epsilon) return Vecs(v.x / norms, v.y / norms, v.z / norms) def vecs_robust_norm(v: Vecs, epsilon: float = 1e-8) -> jnp.ndarray: """Computes norm of vectors 'v'. Args: v: vectors to be normalized. epsilon: small regularizer added to squared norm before taking square root. Returns: norm of 'v' """ return jnp.sqrt(jnp.square(v.x) + jnp.square(v.y) + jnp.square(v.z) + epsilon) def vecs_sub(v1: Vecs, v2: Vecs) -> Vecs: """Computes v1 - v2.""" return Vecs(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z) def vecs_squared_distance(v1: Vecs, v2: Vecs) -> jnp.ndarray: """Computes squared euclidean difference between 'v1' and 'v2'.""" return (squared_difference(v1.x, v2.x) + squared_difference(v1.y, v2.y) + squared_difference(v1.z, v2.z)) def vecs_to_tensor(v: Vecs # shape (...) ) -> jnp.ndarray: # shape(..., 3) """Converts 'v' to tensor with shape 3, inverse of 'vecs_from_tensor'.""" return jnp.stack([v.x, v.y, v.z], axis=-1) ================================================ FILE: alphafold/model/tf/__init__.py ================================================ # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Alphafold model TensorFlow code.""" ================================================ FILE: alphafold/model/tf/data_transforms.py ================================================ # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Data for AlphaFold.""" from alphafold.common import residue_constants from alphafold.model.tf import shape_helpers from alphafold.model.tf import shape_placeholders from alphafold.model.tf import utils import numpy as np import tensorflow.compat.v1 as tf # Pylint gets confused by the curry1 decorator because it changes the number # of arguments to the function. # pylint:disable=no-value-for-parameter NUM_RES = shape_placeholders.NUM_RES NUM_MSA_SEQ = shape_placeholders.NUM_MSA_SEQ NUM_EXTRA_SEQ = shape_placeholders.NUM_EXTRA_SEQ NUM_TEMPLATES = shape_placeholders.NUM_TEMPLATES def cast_64bit_ints(protein): for k, v in protein.items(): if v.dtype == tf.int64: protein[k] = tf.cast(v, tf.int32) return protein _MSA_FEATURE_NAMES = [ 'msa', 'deletion_matrix', 'msa_mask', 'msa_row_mask', 'bert_mask', 'true_msa' ] def make_seq_mask(protein): protein['seq_mask'] = tf.ones( shape_helpers.shape_list(protein['aatype']), dtype=tf.float32) return protein def make_template_mask(protein): protein['template_mask'] = tf.ones( shape_helpers.shape_list(protein['template_domain_names']), dtype=tf.float32) return protein def curry1(f): """Supply all arguments but the first.""" def fc(*args, **kwargs): return lambda x: f(x, *args, **kwargs) return fc @curry1 def add_distillation_flag(protein, distillation): protein['is_distillation'] = tf.constant(float(distillation), shape=[], dtype=tf.float32) return protein def make_all_atom_aatype(protein): protein['all_atom_aatype'] = protein['aatype'] return protein def fix_templates_aatype(protein): """Fixes aatype encoding of templates.""" # Map one-hot to indices. protein['template_aatype'] = tf.argmax( protein['template_aatype'], output_type=tf.int32, axis=-1) # Map hhsearch-aatype to our aatype. new_order_list = residue_constants.MAP_HHBLITS_AATYPE_TO_OUR_AATYPE new_order = tf.constant(new_order_list, dtype=tf.int32) protein['template_aatype'] = tf.gather(params=new_order, indices=protein['template_aatype']) return protein def correct_msa_restypes(protein): """Correct MSA restype to have the same order as residue_constants.""" new_order_list = residue_constants.MAP_HHBLITS_AATYPE_TO_OUR_AATYPE new_order = tf.constant(new_order_list, dtype=protein['msa'].dtype) protein['msa'] = tf.gather(new_order, protein['msa'], axis=0) perm_matrix = np.zeros((22, 22), dtype=np.float32) perm_matrix[range(len(new_order_list)), new_order_list] = 1. for k in protein: if 'profile' in k: # Include both hhblits and psiblast profiles num_dim = protein[k].shape.as_list()[-1] assert num_dim in [20, 21, 22], ( 'num_dim for %s out of expected range: %s' % (k, num_dim)) protein[k] = tf.tensordot(protein[k], perm_matrix[:num_dim, :num_dim], 1) return protein def squeeze_features(protein): """Remove singleton and repeated dimensions in protein features.""" protein['aatype'] = tf.argmax( protein['aatype'], axis=-1, output_type=tf.int32) for k in [ 'domain_name', 'msa', 'num_alignments', 'seq_length', 'sequence', 'superfamily', 'deletion_matrix', 'resolution', 'between_segment_residues', 'residue_index', 'template_all_atom_masks']: if k in protein: final_dim = shape_helpers.shape_list(protein[k])[-1] if isinstance(final_dim, int) and final_dim == 1: protein[k] = tf.squeeze(protein[k], axis=-1) for k in ['seq_length', 'num_alignments']: if k in protein: protein[k] = protein[k][0] # Remove fake sequence dimension return protein def make_random_crop_to_size_seed(protein): """Random seed for cropping residues and templates.""" protein['random_crop_to_size_seed'] = utils.make_random_seed() return protein @curry1 def randomly_replace_msa_with_unknown(protein, replace_proportion): """Replace a proportion of the MSA with 'X'.""" msa_mask = (tf.random.uniform(shape_helpers.shape_list(protein['msa'])) < replace_proportion) x_idx = 20 gap_idx = 21 msa_mask = tf.logical_and(msa_mask, protein['msa'] != gap_idx) protein['msa'] = tf.where(msa_mask, tf.ones_like(protein['msa']) * x_idx, protein['msa']) aatype_mask = ( tf.random.uniform(shape_helpers.shape_list(protein['aatype'])) < replace_proportion) protein['aatype'] = tf.where(aatype_mask, tf.ones_like(protein['aatype']) * x_idx, protein['aatype']) return protein @curry1 def sample_msa(protein, max_seq, keep_extra): """Sample MSA randomly, remaining sequences are stored as `extra_*`. Args: protein: batch to sample msa from. max_seq: number of sequences to sample. keep_extra: When True sequences not sampled are put into fields starting with 'extra_*'. Returns: Protein with sampled msa. """ num_seq = tf.shape(protein['msa'])[0] shuffled = tf.random_shuffle(tf.range(1, num_seq)) index_order = tf.concat([[0], shuffled], axis=0) num_sel = tf.minimum(max_seq, num_seq) sel_seq, not_sel_seq = tf.split(index_order, [num_sel, num_seq - num_sel]) for k in _MSA_FEATURE_NAMES: if k in protein: if keep_extra: protein['extra_' + k] = tf.gather(protein[k], not_sel_seq) protein[k] = tf.gather(protein[k], sel_seq) return protein @curry1 def crop_extra_msa(protein, max_extra_msa): """MSA features are cropped so only `max_extra_msa` sequences are kept.""" num_seq = tf.shape(protein['extra_msa'])[0] num_sel = tf.minimum(max_extra_msa, num_seq) select_indices = tf.random_shuffle(tf.range(0, num_seq))[:num_sel] for k in _MSA_FEATURE_NAMES: if 'extra_' + k in protein: protein['extra_' + k] = tf.gather(protein['extra_' + k], select_indices) return protein def delete_extra_msa(protein): for k in _MSA_FEATURE_NAMES: if 'extra_' + k in protein: del protein['extra_' + k] return protein @curry1 def block_delete_msa(protein, config): """Sample MSA by deleting contiguous blocks. Jumper et al. (2021) Suppl. Alg. 1 "MSABlockDeletion" Arguments: protein: batch dict containing the msa config: ConfigDict with parameters Returns: updated protein """ num_seq = shape_helpers.shape_list(protein['msa'])[0] block_num_seq = tf.cast( tf.floor(tf.cast(num_seq, tf.float32) * config.msa_fraction_per_block), tf.int32) if config.randomize_num_blocks: nb = tf.random.uniform([], 0, config.num_blocks + 1, dtype=tf.int32) else: nb = config.num_blocks del_block_starts = tf.random.uniform([nb], 0, num_seq, dtype=tf.int32) del_blocks = del_block_starts[:, None] + tf.range(block_num_seq) del_blocks = tf.clip_by_value(del_blocks, 0, num_seq - 1) del_indices = tf.unique(tf.sort(tf.reshape(del_blocks, [-1])))[0] # Make sure we keep the original sequence sparse_diff = tf.sets.difference(tf.range(1, num_seq)[None], del_indices[None]) keep_indices = tf.squeeze(tf.sparse.to_dense(sparse_diff), 0) keep_indices = tf.concat([[0], keep_indices], axis=0) for k in _MSA_FEATURE_NAMES: if k in protein: protein[k] = tf.gather(protein[k], keep_indices) return protein @curry1 def nearest_neighbor_clusters(protein, gap_agreement_weight=0.): """Assign each extra MSA sequence to its nearest neighbor in sampled MSA.""" # Determine how much weight we assign to each agreement. In theory, we could # use a full blosum matrix here, but right now let's just down-weight gap # agreement because it could be spurious. # Never put weight on agreeing on BERT mask weights = tf.concat([ tf.ones(21), gap_agreement_weight * tf.ones(1), np.zeros(1)], 0) # Make agreement score as weighted Hamming distance sample_one_hot = (protein['msa_mask'][:, :, None] * tf.one_hot(protein['msa'], 23)) extra_one_hot = (protein['extra_msa_mask'][:, :, None] * tf.one_hot(protein['extra_msa'], 23)) num_seq, num_res, _ = shape_helpers.shape_list(sample_one_hot) extra_num_seq, _, _ = shape_helpers.shape_list(extra_one_hot) # Compute tf.einsum('mrc,nrc,c->mn', sample_one_hot, extra_one_hot, weights) # in an optimized fashion to avoid possible memory or computation blowup. agreement = tf.matmul( tf.reshape(extra_one_hot, [extra_num_seq, num_res * 23]), tf.reshape(sample_one_hot * weights, [num_seq, num_res * 23]), transpose_b=True) # Assign each sequence in the extra sequences to the closest MSA sample protein['extra_cluster_assignment'] = tf.argmax( agreement, axis=1, output_type=tf.int32) return protein @curry1 def summarize_clusters(protein): """Produce profile and deletion_matrix_mean within each cluster.""" num_seq = shape_helpers.shape_list(protein['msa'])[0] def csum(x): return tf.math.unsorted_segment_sum( x, protein['extra_cluster_assignment'], num_seq) mask = protein['extra_msa_mask'] mask_counts = 1e-6 + protein['msa_mask'] + csum(mask) # Include center msa_sum = csum(mask[:, :, None] * tf.one_hot(protein['extra_msa'], 23)) msa_sum += tf.one_hot(protein['msa'], 23) # Original sequence protein['cluster_profile'] = msa_sum / mask_counts[:, :, None] del msa_sum del_sum = csum(mask * protein['extra_deletion_matrix']) del_sum += protein['deletion_matrix'] # Original sequence protein['cluster_deletion_mean'] = del_sum / mask_counts del del_sum return protein def make_msa_mask(protein): """Mask features are all ones, but will later be zero-padded.""" protein['msa_mask'] = tf.ones( shape_helpers.shape_list(protein['msa']), dtype=tf.float32) protein['msa_row_mask'] = tf.ones( shape_helpers.shape_list(protein['msa'])[0], dtype=tf.float32) return protein def pseudo_beta_fn(aatype, all_atom_positions, all_atom_masks): """Create pseudo beta features.""" is_gly = tf.equal(aatype, residue_constants.restype_order['G']) ca_idx = residue_constants.atom_order['CA'] cb_idx = residue_constants.atom_order['CB'] pseudo_beta = tf.where( tf.tile(is_gly[..., None], [1] * len(is_gly.shape) + [3]), all_atom_positions[..., ca_idx, :], all_atom_positions[..., cb_idx, :]) if all_atom_masks is not None: pseudo_beta_mask = tf.where( is_gly, all_atom_masks[..., ca_idx], all_atom_masks[..., cb_idx]) pseudo_beta_mask = tf.cast(pseudo_beta_mask, tf.float32) return pseudo_beta, pseudo_beta_mask else: return pseudo_beta @curry1 def make_pseudo_beta(protein, prefix=''): """Create pseudo-beta (alpha for glycine) position and mask.""" assert prefix in ['', 'template_'] protein[prefix + 'pseudo_beta'], protein[prefix + 'pseudo_beta_mask'] = ( pseudo_beta_fn( protein['template_aatype' if prefix else 'all_atom_aatype'], protein[prefix + 'all_atom_positions'], protein['template_all_atom_masks' if prefix else 'all_atom_mask'])) return protein @curry1 def add_constant_field(protein, key, value): protein[key] = tf.convert_to_tensor(value) return protein def shaped_categorical(probs, epsilon=1e-10): ds = shape_helpers.shape_list(probs) num_classes = ds[-1] counts = tf.random.categorical( tf.reshape(tf.log(probs + epsilon), [-1, num_classes]), 1, dtype=tf.int32) return tf.reshape(counts, ds[:-1]) def make_hhblits_profile(protein): """Compute the HHblits MSA profile if not already present.""" if 'hhblits_profile' in protein: return protein # Compute the profile for every residue (over all MSA sequences). protein['hhblits_profile'] = tf.reduce_mean( tf.one_hot(protein['msa'], 22), axis=0) return protein @curry1 def make_masked_msa(protein, config, replace_fraction): """Create data for BERT on raw MSA.""" # Add a random amino acid uniformly random_aa = tf.constant([0.05] * 20 + [0., 0.], dtype=tf.float32) categorical_probs = ( config.uniform_prob * random_aa + config.profile_prob * protein['hhblits_profile'] + config.same_prob * tf.one_hot(protein['msa'], 22)) # Put all remaining probability on [MASK] which is a new column pad_shapes = [[0, 0] for _ in range(len(categorical_probs.shape))] pad_shapes[-1][1] = 1 mask_prob = 1. - config.profile_prob - config.same_prob - config.uniform_prob assert mask_prob >= 0. categorical_probs = tf.pad( categorical_probs, pad_shapes, constant_values=mask_prob) sh = shape_helpers.shape_list(protein['msa']) mask_position = tf.random.uniform(sh) < replace_fraction bert_msa = shaped_categorical(categorical_probs) bert_msa = tf.where(mask_position, bert_msa, protein['msa']) # Mix real and masked MSA protein['bert_mask'] = tf.cast(mask_position, tf.float32) protein['true_msa'] = protein['msa'] protein['msa'] = bert_msa return protein @curry1 def make_fixed_size(protein, shape_schema, msa_cluster_size, extra_msa_size, num_res, num_templates=0): """Guess at the MSA and sequence dimensions to make fixed size.""" pad_size_map = { NUM_RES: num_res, NUM_MSA_SEQ: msa_cluster_size, NUM_EXTRA_SEQ: extra_msa_size, NUM_TEMPLATES: num_templates, } for k, v in protein.items(): # Don't transfer this to the accelerator. if k == 'extra_cluster_assignment': continue shape = v.shape.as_list() schema = shape_schema[k] assert len(shape) == len(schema), ( f'Rank mismatch between shape and shape schema for {k}: ' f'{shape} vs {schema}') pad_size = [ pad_size_map.get(s2, None) or s1 for (s1, s2) in zip(shape, schema) ] padding = [(0, p - tf.shape(v)[i]) for i, p in enumerate(pad_size)] if padding: protein[k] = tf.pad( v, padding, name=f'pad_to_fixed_{k}') protein[k].set_shape(pad_size) return protein @curry1 def make_msa_feat(protein): """Create and concatenate MSA features.""" # Whether there is a domain break. Always zero for chains, but keeping # for compatibility with domain datasets. has_break = tf.clip_by_value( tf.cast(protein['between_segment_residues'], tf.float32), 0, 1) aatype_1hot = tf.one_hot(protein['aatype'], 21, axis=-1) target_feat = [ tf.expand_dims(has_break, axis=-1), aatype_1hot, # Everyone gets the original sequence. ] msa_1hot = tf.one_hot(protein['msa'], 23, axis=-1) has_deletion = tf.clip_by_value(protein['deletion_matrix'], 0., 1.) deletion_value = tf.atan(protein['deletion_matrix'] / 3.) * (2. / np.pi) msa_feat = [ msa_1hot, tf.expand_dims(has_deletion, axis=-1), tf.expand_dims(deletion_value, axis=-1), ] if 'cluster_profile' in protein: deletion_mean_value = ( tf.atan(protein['cluster_deletion_mean'] / 3.) * (2. / np.pi)) msa_feat.extend([ protein['cluster_profile'], tf.expand_dims(deletion_mean_value, axis=-1), ]) if 'extra_deletion_matrix' in protein: protein['extra_has_deletion'] = tf.clip_by_value( protein['extra_deletion_matrix'], 0., 1.) protein['extra_deletion_value'] = tf.atan( protein['extra_deletion_matrix'] / 3.) * (2. / np.pi) protein['msa_feat'] = tf.concat(msa_feat, axis=-1) protein['target_feat'] = tf.concat(target_feat, axis=-1) return protein @curry1 def select_feat(protein, feature_list): return {k: v for k, v in protein.items() if k in feature_list} @curry1 def crop_templates(protein, max_templates): for k, v in protein.items(): if k.startswith('template_'): protein[k] = v[:max_templates] return protein @curry1 def random_crop_to_size(protein, crop_size, max_templates, shape_schema, subsample_templates=False): """Crop randomly to `crop_size`, or keep as is if shorter than that.""" seq_length = protein['seq_length'] if 'template_mask' in protein: num_templates = tf.cast( shape_helpers.shape_list(protein['template_mask'])[0], tf.int32) else: num_templates = tf.constant(0, dtype=tf.int32) num_res_crop_size = tf.math.minimum(seq_length, crop_size) # Ensures that the cropping of residues and templates happens in the same way # across ensembling iterations. # Do not use for randomness that should vary in ensembling. seed_maker = utils.SeedMaker(initial_seed=protein['random_crop_to_size_seed']) if subsample_templates: templates_crop_start = tf.random.stateless_uniform( shape=(), minval=0, maxval=num_templates + 1, dtype=tf.int32, seed=seed_maker()) else: templates_crop_start = 0 num_templates_crop_size = tf.math.minimum( num_templates - templates_crop_start, max_templates) num_res_crop_start = tf.random.stateless_uniform( shape=(), minval=0, maxval=seq_length - num_res_crop_size + 1, dtype=tf.int32, seed=seed_maker()) templates_select_indices = tf.argsort(tf.random.stateless_uniform( [num_templates], seed=seed_maker())) for k, v in protein.items(): if k not in shape_schema or ( 'template' not in k and NUM_RES not in shape_schema[k]): continue # randomly permute the templates before cropping them. if k.startswith('template') and subsample_templates: v = tf.gather(v, templates_select_indices) crop_sizes = [] crop_starts = [] for i, (dim_size, dim) in enumerate(zip(shape_schema[k], shape_helpers.shape_list(v))): is_num_res = (dim_size == NUM_RES) if i == 0 and k.startswith('template'): crop_size = num_templates_crop_size crop_start = templates_crop_start else: crop_start = num_res_crop_start if is_num_res else 0 crop_size = (num_res_crop_size if is_num_res else (-1 if dim is None else dim)) crop_sizes.append(crop_size) crop_starts.append(crop_start) protein[k] = tf.slice(v, crop_starts, crop_sizes) protein['seq_length'] = num_res_crop_size return protein def make_atom14_masks(protein): """Construct denser atom positions (14 dimensions instead of 37).""" restype_atom14_to_atom37 = [] # mapping (restype, atom14) --> atom37 restype_atom37_to_atom14 = [] # mapping (restype, atom37) --> atom14 restype_atom14_mask = [] for rt in residue_constants.restypes: atom_names = residue_constants.restype_name_to_atom14_names[ residue_constants.restype_1to3[rt]] restype_atom14_to_atom37.append([ (residue_constants.atom_order[name] if name else 0) for name in atom_names ]) atom_name_to_idx14 = {name: i for i, name in enumerate(atom_names)} restype_atom37_to_atom14.append([ (atom_name_to_idx14[name] if name in atom_name_to_idx14 else 0) for name in residue_constants.atom_types ]) restype_atom14_mask.append([(1. if name else 0.) for name in atom_names]) # Add dummy mapping for restype 'UNK' restype_atom14_to_atom37.append([0] * 14) restype_atom37_to_atom14.append([0] * 37) restype_atom14_mask.append([0.] * 14) restype_atom14_to_atom37 = np.array(restype_atom14_to_atom37, dtype=np.int32) restype_atom37_to_atom14 = np.array(restype_atom37_to_atom14, dtype=np.int32) restype_atom14_mask = np.array(restype_atom14_mask, dtype=np.float32) # create the mapping for (residx, atom14) --> atom37, i.e. an array # with shape (num_res, 14) containing the atom37 indices for this protein residx_atom14_to_atom37 = tf.gather(restype_atom14_to_atom37, protein['aatype']) residx_atom14_mask = tf.gather(restype_atom14_mask, protein['aatype']) protein['atom14_atom_exists'] = residx_atom14_mask protein['residx_atom14_to_atom37'] = residx_atom14_to_atom37 # create the gather indices for mapping back residx_atom37_to_atom14 = tf.gather(restype_atom37_to_atom14, protein['aatype']) protein['residx_atom37_to_atom14'] = residx_atom37_to_atom14 # create the corresponding mask restype_atom37_mask = np.zeros([21, 37], dtype=np.float32) for restype, restype_letter in enumerate(residue_constants.restypes): restype_name = residue_constants.restype_1to3[restype_letter] atom_names = residue_constants.residue_atoms[restype_name] for atom_name in atom_names: atom_type = residue_constants.atom_order[atom_name] restype_atom37_mask[restype, atom_type] = 1 residx_atom37_mask = tf.gather(restype_atom37_mask, protein['aatype']) protein['atom37_atom_exists'] = residx_atom37_mask return protein ================================================ FILE: alphafold/model/tf/input_pipeline.py ================================================ # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Feature pre-processing input pipeline for AlphaFold.""" from alphafold.model.tf import data_transforms from alphafold.model.tf import shape_placeholders import tensorflow.compat.v1 as tf import tree # Pylint gets confused by the curry1 decorator because it changes the number # of arguments to the function. # pylint:disable=no-value-for-parameter NUM_RES = shape_placeholders.NUM_RES NUM_MSA_SEQ = shape_placeholders.NUM_MSA_SEQ NUM_EXTRA_SEQ = shape_placeholders.NUM_EXTRA_SEQ NUM_TEMPLATES = shape_placeholders.NUM_TEMPLATES def nonensembled_map_fns(data_config): """Input pipeline functions which are not ensembled.""" common_cfg = data_config.common map_fns = [ data_transforms.correct_msa_restypes, data_transforms.add_distillation_flag(False), data_transforms.cast_64bit_ints, data_transforms.squeeze_features, # Keep to not disrupt RNG. data_transforms.randomly_replace_msa_with_unknown(0.0), data_transforms.make_seq_mask, data_transforms.make_msa_mask, # Compute the HHblits profile if it's not set. This has to be run before # sampling the MSA. data_transforms.make_hhblits_profile, data_transforms.make_random_crop_to_size_seed, ] if common_cfg.use_templates: map_fns.extend([ data_transforms.fix_templates_aatype, data_transforms.make_template_mask, data_transforms.make_pseudo_beta('template_') ]) map_fns.extend([ data_transforms.make_atom14_masks, ]) return map_fns def ensembled_map_fns(data_config): """Input pipeline functions that can be ensembled and averaged.""" common_cfg = data_config.common eval_cfg = data_config.eval map_fns = [] if common_cfg.reduce_msa_clusters_by_max_templates: pad_msa_clusters = eval_cfg.max_msa_clusters - eval_cfg.max_templates else: pad_msa_clusters = eval_cfg.max_msa_clusters max_msa_clusters = pad_msa_clusters max_extra_msa = common_cfg.max_extra_msa map_fns.append( data_transforms.sample_msa( max_msa_clusters, keep_extra=True)) if 'masked_msa' in common_cfg: # Masked MSA should come *before* MSA clustering so that # the clustering and full MSA profile do not leak information about # the masked locations and secret corrupted locations. map_fns.append( data_transforms.make_masked_msa(common_cfg.masked_msa, eval_cfg.masked_msa_replace_fraction)) if common_cfg.msa_cluster_features: map_fns.append(data_transforms.nearest_neighbor_clusters()) map_fns.append(data_transforms.summarize_clusters()) # Crop after creating the cluster profiles. if max_extra_msa: map_fns.append(data_transforms.crop_extra_msa(max_extra_msa)) else: map_fns.append(data_transforms.delete_extra_msa) map_fns.append(data_transforms.make_msa_feat()) crop_feats = dict(eval_cfg.feat) if eval_cfg.fixed_size: map_fns.append(data_transforms.select_feat(list(crop_feats))) map_fns.append(data_transforms.random_crop_to_size( eval_cfg.crop_size, eval_cfg.max_templates, crop_feats, eval_cfg.subsample_templates)) map_fns.append(data_transforms.make_fixed_size( crop_feats, pad_msa_clusters, common_cfg.max_extra_msa, eval_cfg.crop_size, eval_cfg.max_templates)) else: map_fns.append(data_transforms.crop_templates(eval_cfg.max_templates)) return map_fns def process_tensors_from_config(tensors, data_config): """Apply filters and maps to an existing dataset, based on the config.""" def wrap_ensemble_fn(data, i): """Function to be mapped over the ensemble dimension.""" d = data.copy() fns = ensembled_map_fns(data_config) fn = compose(fns) d['ensemble_index'] = i return fn(d) eval_cfg = data_config.eval tensors = compose( nonensembled_map_fns( data_config))( tensors) tensors_0 = wrap_ensemble_fn(tensors, tf.constant(0)) num_ensemble = eval_cfg.num_ensemble if data_config.common.resample_msa_in_recycling: # Separate batch per ensembling & recycling step. num_ensemble *= data_config.common.num_recycle + 1 if isinstance(num_ensemble, tf.Tensor) or num_ensemble > 1: fn_output_signature = tree.map_structure( tf.TensorSpec.from_tensor, tensors_0) tensors = tf.map_fn( lambda x: wrap_ensemble_fn(tensors, x), tf.range(num_ensemble), parallel_iterations=1, fn_output_signature=fn_output_signature) else: tensors = tree.map_structure(lambda x: x[None], tensors_0) return tensors @data_transforms.curry1 def compose(x, fs): for f in fs: x = f(x) return x ================================================ FILE: alphafold/model/tf/protein_features.py ================================================ # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Contains descriptions of various protein features.""" import enum from typing import Dict, Optional, Sequence, Tuple, Union from alphafold.common import residue_constants import tensorflow.compat.v1 as tf # Type aliases. FeaturesMetadata = Dict[str, Tuple[tf.dtypes.DType, Sequence[Union[str, int]]]] class FeatureType(enum.Enum): ZERO_DIM = 0 # Shape [x] ONE_DIM = 1 # Shape [num_res, x] TWO_DIM = 2 # Shape [num_res, num_res, x] MSA = 3 # Shape [msa_length, num_res, x] # Placeholder values that will be replaced with their true value at runtime. NUM_RES = "num residues placeholder" NUM_SEQ = "length msa placeholder" NUM_TEMPLATES = "num templates placeholder" # Sizes of the protein features, NUM_RES and NUM_SEQ are allowed as placeholders # to be replaced with the number of residues and the number of sequences in the # multiple sequence alignment, respectively. FEATURES = { #### Static features of a protein sequence #### "aatype": (tf.float32, [NUM_RES, 21]), "between_segment_residues": (tf.int64, [NUM_RES, 1]), "deletion_matrix": (tf.float32, [NUM_SEQ, NUM_RES, 1]), "domain_name": (tf.string, [1]), "msa": (tf.int64, [NUM_SEQ, NUM_RES, 1]), "num_alignments": (tf.int64, [NUM_RES, 1]), "residue_index": (tf.int64, [NUM_RES, 1]), "seq_length": (tf.int64, [NUM_RES, 1]), "sequence": (tf.string, [1]), "all_atom_positions": (tf.float32, [NUM_RES, residue_constants.atom_type_num, 3]), "all_atom_mask": (tf.int64, [NUM_RES, residue_constants.atom_type_num]), "resolution": (tf.float32, [1]), "template_domain_names": (tf.string, [NUM_TEMPLATES]), "template_sum_probs": (tf.float32, [NUM_TEMPLATES, 1]), "template_aatype": (tf.float32, [NUM_TEMPLATES, NUM_RES, 22]), "template_all_atom_positions": (tf.float32, [ NUM_TEMPLATES, NUM_RES, residue_constants.atom_type_num, 3 ]), "template_all_atom_masks": (tf.float32, [ NUM_TEMPLATES, NUM_RES, residue_constants.atom_type_num, 1 ]), } FEATURE_TYPES = {k: v[0] for k, v in FEATURES.items()} FEATURE_SIZES = {k: v[1] for k, v in FEATURES.items()} def register_feature(name: str, type_: tf.dtypes.DType, shape_: Tuple[Union[str, int]]): """Register extra features used in custom datasets.""" FEATURES[name] = (type_, shape_) FEATURE_TYPES[name] = type_ FEATURE_SIZES[name] = shape_ def shape(feature_name: str, num_residues: int, msa_length: int, num_templates: Optional[int] = None, features: Optional[FeaturesMetadata] = None): """Get the shape for the given feature name. This is near identical to _get_tf_shape_no_placeholders() but with 2 differences: * This method does not calculate a single placeholder from the total number of elements (eg givenand size := 12, this won't deduce NUM_RES must be 4) * This method will work with tensors Args: feature_name: String identifier for the feature. If the feature name ends with "_unnormalized", this suffix is stripped off. num_residues: The number of residues in the current domain - some elements of the shape can be dynamic and will be replaced by this value. msa_length: The number of sequences in the multiple sequence alignment, some elements of the shape can be dynamic and will be replaced by this value. If the number of alignments is unknown / not read, please pass None for msa_length. num_templates (optional): The number of templates in this tfexample. features: A feature_name to (tf_dtype, shape) lookup; defaults to FEATURES. Returns: List of ints representation the tensor size. Raises: ValueError: If a feature is requested but no concrete placeholder value is given. """ features = features or FEATURES if feature_name.endswith("_unnormalized"): feature_name = feature_name[:-13] unused_dtype, raw_sizes = features[feature_name] replacements = {NUM_RES: num_residues, NUM_SEQ: msa_length} if num_templates is not None: replacements[NUM_TEMPLATES] = num_templates sizes = [replacements.get(dimension, dimension) for dimension in raw_sizes] for dimension in sizes: if isinstance(dimension, str): raise ValueError("Could not parse %s (shape: %s) with values: %s" % ( feature_name, raw_sizes, replacements)) return sizes ================================================ FILE: alphafold/model/tf/protein_features_test.py ================================================ # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Tests for protein_features.""" import uuid from absl.testing import absltest from absl.testing import parameterized from alphafold.model.tf import protein_features import tensorflow.compat.v1 as tf def _random_bytes(): return str(uuid.uuid4()).encode('utf-8') class FeaturesTest(parameterized.TestCase, tf.test.TestCase): def setUp(self): super().setUp() tf.disable_v2_behavior() def testFeatureNames(self): self.assertEqual(len(protein_features.FEATURE_SIZES), len(protein_features.FEATURE_TYPES)) sorted_size_names = sorted(protein_features.FEATURE_SIZES.keys()) sorted_type_names = sorted(protein_features.FEATURE_TYPES.keys()) for i, size_name in enumerate(sorted_size_names): self.assertEqual(size_name, sorted_type_names[i]) def testReplacement(self): for name in protein_features.FEATURE_SIZES.keys(): sizes = protein_features.shape(name, num_residues=12, msa_length=24, num_templates=3) for x in sizes: self.assertEqual(type(x), int) self.assertGreater(x, 0) if __name__ == '__main__': absltest.main() ================================================ FILE: alphafold/model/tf/proteins_dataset.py ================================================ # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Datasets consisting of proteins.""" from typing import Dict, Mapping, Optional, Sequence from alphafold.model.tf import protein_features import numpy as np import tensorflow.compat.v1 as tf TensorDict = Dict[str, tf.Tensor] def parse_tfexample( raw_data: bytes, features: protein_features.FeaturesMetadata, key: Optional[str] = None) -> Dict[str, tf.train.Feature]: """Read a single TF Example proto and return a subset of its features. Args: raw_data: A serialized tf.Example proto. features: A dictionary of features, mapping string feature names to a tuple (dtype, shape). This dictionary should be a subset of protein_features.FEATURES (or the dictionary itself for all features). key: Optional string with the SSTable key of that tf.Example. This will be added into features as a 'key' but only if requested in features. Returns: A dictionary of features mapping feature names to features. Only the given features are returned, all other ones are filtered out. """ feature_map = { k: tf.io.FixedLenSequenceFeature(shape=(), dtype=v[0], allow_missing=True) for k, v in features.items() } parsed_features = tf.io.parse_single_example(raw_data, feature_map) reshaped_features = parse_reshape_logic(parsed_features, features, key=key) return reshaped_features def _first(tensor: tf.Tensor) -> tf.Tensor: """Returns the 1st element - the input can be a tensor or a scalar.""" return tf.reshape(tensor, shape=(-1,))[0] def parse_reshape_logic( parsed_features: TensorDict, features: protein_features.FeaturesMetadata, key: Optional[str] = None) -> TensorDict: """Transforms parsed serial features to the correct shape.""" # Find out what is the number of sequences and the number of alignments. num_residues = tf.cast(_first(parsed_features["seq_length"]), dtype=tf.int32) if "num_alignments" in parsed_features: num_msa = tf.cast(_first(parsed_features["num_alignments"]), dtype=tf.int32) else: num_msa = 0 if "template_domain_names" in parsed_features: num_templates = tf.cast( tf.shape(parsed_features["template_domain_names"])[0], dtype=tf.int32) else: num_templates = 0 if key is not None and "key" in features: parsed_features["key"] = [key] # Expand dims from () to (1,). # Reshape the tensors according to the sequence length and num alignments. for k, v in parsed_features.items(): new_shape = protein_features.shape( feature_name=k, num_residues=num_residues, msa_length=num_msa, num_templates=num_templates, features=features) new_shape_size = tf.constant(1, dtype=tf.int32) for dim in new_shape: new_shape_size *= tf.cast(dim, tf.int32) assert_equal = tf.assert_equal( tf.size(v), new_shape_size, name="assert_%s_shape_correct" % k, message="The size of feature %s (%s) could not be reshaped " "into %s" % (k, tf.size(v), new_shape)) if "template" not in k: # Make sure the feature we are reshaping is not empty. assert_non_empty = tf.assert_greater( tf.size(v), 0, name="assert_%s_non_empty" % k, message="The feature %s is not set in the tf.Example. Either do not " "request the feature or use a tf.Example that has the " "feature set." % k) with tf.control_dependencies([assert_non_empty, assert_equal]): parsed_features[k] = tf.reshape(v, new_shape, name="reshape_%s" % k) else: with tf.control_dependencies([assert_equal]): parsed_features[k] = tf.reshape(v, new_shape, name="reshape_%s" % k) return parsed_features def _make_features_metadata( feature_names: Sequence[str]) -> protein_features.FeaturesMetadata: """Makes a feature name to type and shape mapping from a list of names.""" # Make sure these features are always read. required_features = ["aatype", "sequence", "seq_length"] feature_names = list(set(feature_names) | set(required_features)) features_metadata = {name: protein_features.FEATURES[name] for name in feature_names} return features_metadata def create_tensor_dict( raw_data: bytes, features: Sequence[str], key: Optional[str] = None, ) -> TensorDict: """Creates a dictionary of tensor features. Args: raw_data: A serialized tf.Example proto. features: A list of strings of feature names to be returned in the dataset. key: Optional string with the SSTable key of that tf.Example. This will be added into features as a 'key' but only if requested in features. Returns: A dictionary of features mapping feature names to features. Only the given features are returned, all other ones are filtered out. """ features_metadata = _make_features_metadata(features) return parse_tfexample(raw_data, features_metadata, key) def np_to_tensor_dict( np_example: Mapping[str, np.ndarray], features: Sequence[str], ) -> TensorDict: """Creates dict of tensors from a dict of NumPy arrays. Args: np_example: A dict of NumPy feature arrays. features: A list of strings of feature names to be returned in the dataset. Returns: A dictionary of features mapping feature names to features. Only the given features are returned, all other ones are filtered out. """ features_metadata = _make_features_metadata(features) tensor_dict = {k: tf.constant(v) for k, v in np_example.items() if k in features_metadata} # Ensures shapes are as expected. Needed for setting size of empty features # e.g. when no template hits were found. tensor_dict = parse_reshape_logic(tensor_dict, features_metadata) return tensor_dict ================================================ FILE: alphafold/model/tf/shape_helpers.py ================================================ # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Utilities for dealing with shapes of TensorFlow tensors.""" import tensorflow.compat.v1 as tf def shape_list(x): """Return list of dimensions of a tensor, statically where possible. Like `x.shape.as_list()` but with tensors instead of `None`s. Args: x: A tensor. Returns: A list with length equal to the rank of the tensor. The n-th element of the list is an integer when that dimension is statically known otherwise it is the n-th element of `tf.shape(x)`. """ x = tf.convert_to_tensor(x) # If unknown rank, return dynamic shape if x.get_shape().dims is None: return tf.shape(x) static = x.get_shape().as_list() shape = tf.shape(x) ret = [] for i in range(len(static)): dim = static[i] if dim is None: dim = shape[i] ret.append(dim) return ret ================================================ FILE: alphafold/model/tf/shape_helpers_test.py ================================================ # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Tests for shape_helpers.""" from alphafold.model.tf import shape_helpers import numpy as np import tensorflow.compat.v1 as tf class ShapeTest(tf.test.TestCase): def setUp(self): super().setUp() tf.disable_v2_behavior() def test_shape_list(self): """Test that shape_list can allow for reshaping to dynamic shapes.""" a = tf.zeros([10, 4, 4, 2]) p = tf.placeholder(tf.float32, shape=[None, None, 1, 4, 4]) shape_dyn = shape_helpers.shape_list(p)[:2] + [4, 4] b = tf.reshape(a, shape_dyn) with self.session() as sess: out = sess.run(b, feed_dict={p: np.ones((20, 1, 1, 4, 4))}) self.assertAllEqual(out.shape, (20, 1, 4, 4)) if __name__ == '__main__': tf.test.main() ================================================ FILE: alphafold/model/tf/shape_placeholders.py ================================================ # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Placeholder values for run-time varying dimension sizes.""" NUM_RES = 'num residues placeholder' NUM_MSA_SEQ = 'msa placeholder' NUM_EXTRA_SEQ = 'extra msa placeholder' NUM_TEMPLATES = 'num templates placeholder' ================================================ FILE: alphafold/model/tf/utils.py ================================================ # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Shared utilities for various components.""" import tensorflow.compat.v1 as tf def tf_combine_mask(*masks): """Take the intersection of float-valued masks.""" ret = 1 for m in masks: ret *= m return ret class SeedMaker(object): """Return unique seeds.""" def __init__(self, initial_seed=0): self.next_seed = initial_seed def __call__(self): i = self.next_seed self.next_seed += 1 return i seed_maker = SeedMaker() def make_random_seed(): return tf.random.uniform([2], tf.int32.min, tf.int32.max, tf.int32, seed=seed_maker()) ================================================ FILE: alphafold/model/utils.py ================================================ # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """A collection of JAX utility functions for use in protein folding.""" import collections import contextlib import functools import numbers from typing import Mapping import haiku as hk import jax import jax.numpy as jnp import numpy as np def bfloat16_creator(next_creator, shape, dtype, init, context): """Creates float32 variables when bfloat16 is requested.""" if context.original_dtype == jnp.bfloat16: dtype = jnp.float32 return next_creator(shape, dtype, init) def bfloat16_getter(next_getter, value, context): """Casts float32 to bfloat16 when bfloat16 was originally requested.""" if context.original_dtype == jnp.bfloat16: assert value.dtype == jnp.float32 value = value.astype(jnp.bfloat16) return next_getter(value) @contextlib.contextmanager def bfloat16_context(): with hk.custom_creator(bfloat16_creator), hk.custom_getter(bfloat16_getter): yield def final_init(config): if config.zero_init: return 'zeros' else: return 'linear' def batched_gather(params, indices, axis=0, batch_dims=0): """Implements a JAX equivalent of `tf.gather` with `axis` and `batch_dims`.""" take_fn = lambda p, i: jnp.take(p, i, axis=axis, mode='clip') for _ in range(batch_dims): take_fn = jax.vmap(take_fn) return take_fn(params, indices) def mask_mean(mask, value, axis=None, drop_mask_channel=False, eps=1e-10): """Masked mean.""" if drop_mask_channel: mask = mask[..., 0] mask_shape = mask.shape value_shape = value.shape assert len(mask_shape) == len(value_shape) if isinstance(axis, numbers.Integral): axis = [axis] elif axis is None: axis = list(range(len(mask_shape))) assert isinstance(axis, collections.abc.Iterable), ( 'axis needs to be either an iterable, integer or "None"') broadcast_factor = 1. for axis_ in axis: value_size = value_shape[axis_] mask_size = mask_shape[axis_] if mask_size == 1: broadcast_factor *= value_size else: assert mask_size == value_size return (jnp.sum(mask * value, axis=axis) / (jnp.sum(mask, axis=axis) * broadcast_factor + eps)) def flat_params_to_haiku(params: Mapping[str, np.ndarray]) -> hk.Params: """Convert a dictionary of NumPy arrays to Haiku parameters.""" hk_params = {} for path, array in params.items(): scope, name = path.split('//') if scope not in hk_params: hk_params[scope] = {} hk_params[scope][name] = jnp.array(array) return hk_params def padding_consistent_rng(f): """Modify any element-wise random function to be consistent with padding. Normally if you take a function like jax.random.normal and generate an array, say of size (10,10), you will get a different set of random numbers to if you add padding and take the first (10,10) sub-array. This function makes a random function that is consistent regardless of the amount of padding added. Note: The padding-consistent function is likely to be slower to compile and run than the function it is wrapping, but these slowdowns are likely to be negligible in a large network. Args: f: Any element-wise function that takes (PRNG key, shape) as the first 2 arguments. Returns: An equivalent function to f, that is now consistent for different amounts of padding. """ def grid_keys(key, shape): """Generate a grid of rng keys that is consistent with different padding. Generate random keys such that the keys will be identical, regardless of how much padding is added to any dimension. Args: key: A PRNG key. shape: The shape of the output array of keys that will be generated. Returns: An array of shape `shape` consisting of random keys. """ if not shape: return key new_keys = jax.vmap(functools.partial(jax.random.fold_in, key))( jnp.arange(shape[0])) return jax.vmap(functools.partial(grid_keys, shape=shape[1:]))(new_keys) def inner(key, shape, **kwargs): return jnp.vectorize( lambda key: f(key, shape=(), **kwargs), signature='(2)->()')( grid_keys(key, shape)) return inner ================================================ FILE: alphafold/notebooks/__init__.py ================================================ # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """AlphaFold Colab notebook.""" ================================================ FILE: alphafold/notebooks/notebook_utils.py ================================================ # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Helper methods for the AlphaFold Colab notebook.""" import json from typing import Any, Mapping, Optional, Sequence, Tuple from alphafold.common import residue_constants from alphafold.data import parsers from matplotlib import pyplot as plt import numpy as np def clean_and_validate_single_sequence( input_sequence: str, min_length: int, max_length: int) -> str: """Checks that the input sequence is ok and returns a clean version of it.""" # Remove all whitespaces, tabs and end lines; upper-case. clean_sequence = input_sequence.translate( str.maketrans('', '', ' \n\t')).upper() aatypes = set(residue_constants.restypes) # 20 standard aatypes. if not set(clean_sequence).issubset(aatypes): raise ValueError( f'Input sequence contains non-amino acid letters: ' f'{set(clean_sequence) - aatypes}. AlphaFold only supports 20 standard ' 'amino acids as inputs.') if len(clean_sequence) < min_length: raise ValueError( f'Input sequence is too short: {len(clean_sequence)} amino acids, ' f'while the minimum is {min_length}') if len(clean_sequence) > max_length: raise ValueError( f'Input sequence is too long: {len(clean_sequence)} amino acids, while ' f'the maximum is {max_length}. You may be able to run it with the full ' f'AlphaFold system depending on your resources (system memory, ' f'GPU memory).') return clean_sequence def clean_and_validate_input_sequences( input_sequences: Sequence[str], min_sequence_length: int, max_sequence_length: int) -> Sequence[str]: """Validates and cleans input sequences.""" sequences = [] for input_sequence in input_sequences: if input_sequence.strip(): input_sequence = clean_and_validate_single_sequence( input_sequence=input_sequence, min_length=min_sequence_length, max_length=max_sequence_length) sequences.append(input_sequence) if sequences: return sequences else: raise ValueError('No input amino acid sequence provided, please provide at ' 'least one sequence.') def merge_chunked_msa( results: Sequence[Mapping[str, Any]], max_hits: Optional[int] = None ) -> parsers.Msa: """Merges chunked database hits together into hits for the full database.""" unsorted_results = [] for chunk_index, chunk in enumerate(results): msa = parsers.parse_stockholm(chunk['sto']) e_values_dict = parsers.parse_e_values_from_tblout(chunk['tbl']) # Jackhmmer lists sequences as / - . e_values = [e_values_dict[t.partition('/')[0]] for t in msa.descriptions] chunk_results = zip( msa.sequences, msa.deletion_matrix, msa.descriptions, e_values) if chunk_index != 0: next(chunk_results) # Only take query (first hit) from the first chunk. unsorted_results.extend(chunk_results) sorted_by_evalue = sorted(unsorted_results, key=lambda x: x[-1]) merged_sequences, merged_deletion_matrix, merged_descriptions, _ = zip( *sorted_by_evalue) merged_msa = parsers.Msa(sequences=merged_sequences, deletion_matrix=merged_deletion_matrix, descriptions=merged_descriptions) if max_hits is not None: merged_msa = merged_msa.truncate(max_seqs=max_hits) return merged_msa def show_msa_info( single_chain_msas: Sequence[parsers.Msa], sequence_index: int): """Prints info and shows a plot of the deduplicated single chain MSA.""" full_single_chain_msa = [] for single_chain_msa in single_chain_msas: full_single_chain_msa.extend(single_chain_msa.sequences) # Deduplicate but preserve order (hence can't use set). deduped_full_single_chain_msa = list(dict.fromkeys(full_single_chain_msa)) total_msa_size = len(deduped_full_single_chain_msa) print(f'\n{total_msa_size} unique sequences found in total for sequence ' f'{sequence_index}\n') aa_map = {res: i for i, res in enumerate('ABCDEFGHIJKLMNOPQRSTUVWXYZ-')} msa_arr = np.array( [[aa_map[aa] for aa in seq] for seq in deduped_full_single_chain_msa]) plt.figure(figsize=(12, 3)) plt.title(f'Per-Residue Count of Non-Gap Amino Acids in the MSA for Sequence ' f'{sequence_index}') plt.plot(np.sum(msa_arr != aa_map['-'], axis=0), color='black') plt.ylabel('Non-Gap Count') plt.yticks(range(0, total_msa_size + 1, max(1, int(total_msa_size / 3)))) plt.show() def empty_placeholder_template_features( num_templates: int, num_res: int) -> Mapping[str, np.ndarray]: return { 'template_aatype': np.zeros( (num_templates, num_res, len(residue_constants.restypes_with_x_and_gap)), dtype=np.float32), 'template_all_atom_masks': np.zeros( (num_templates, num_res, residue_constants.atom_type_num), dtype=np.float32), 'template_all_atom_positions': np.zeros( (num_templates, num_res, residue_constants.atom_type_num, 3), dtype=np.float32), 'template_domain_names': np.zeros([num_templates], dtype=object), 'template_sequence': np.zeros([num_templates], dtype=object), 'template_sum_probs': np.zeros([num_templates], dtype=np.float32), } def get_pae_json(pae: np.ndarray, max_pae: float) -> str: """Returns the PAE in the same format as is used in the AFDB. Note that the values are presented as floats to 1 decimal place, whereas AFDB returns integer values. Args: pae: The n_res x n_res PAE array. max_pae: The maximum possible PAE value. Returns: PAE output format as a JSON string. """ # Check the PAE array is the correct shape. if (pae.ndim != 2 or pae.shape[0] != pae.shape[1]): raise ValueError(f'PAE must be a square matrix, got {pae.shape}') # Round the predicted aligned errors to 1 decimal place. rounded_errors = np.round(pae.astype(np.float64), decimals=1) formatted_output = [{ 'predicted_aligned_error': rounded_errors.tolist(), 'max_predicted_aligned_error': max_pae }] return json.dumps(formatted_output, indent=None, separators=(',', ':')) ================================================ FILE: alphafold/notebooks/notebook_utils_test.py ================================================ # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Tests for notebook_utils.""" import io from absl.testing import absltest from absl.testing import parameterized from alphafold.data import parsers from alphafold.data import templates from alphafold.notebooks import notebook_utils import mock import numpy as np ONLY_QUERY_HIT = { 'sto': ( '# STOCKHOLM 1.0\n' '#=GF ID query-i1\n' 'query MAAHKGAEHHHKAAEHHEQAAKHHHAAAEHHEKGEHEQAAHHADTAYAHHKHAEEH\n' '//\n'), 'tbl': '', 'stderr': b'', 'n_iter': 1, 'e_value': 0.0001} # pylint: disable=line-too-long MULTI_SEQUENCE_HIT_1 = { 'sto': ( '# STOCKHOLM 1.0\n' '#=GF ID query-i1\n' '#=GS ERR1700680_4602609/41-109 DE [subseq from] ERR1700680_4602609\n' '#=GS ERR1019366_5760491/40-105 DE [subseq from] ERR1019366_5760491\n' '#=GS SRR5580704_12853319/61-125 DE [subseq from] SRR5580704_12853319\n' 'query MAAHKGAEHHHKAAEHHEQAAKHHHAAAEHHEKGEHEQAAHHADTAYAHHKHAEEHAAQAAKHDAEHHAPKPH\n' 'ERR1700680_4602609/41-109 --INKGAEYHKKAAEHHELAAKHHREAAKHHEAGSHEKAAHHSEIAAGHGLTAVHHTEEATK-HHPEEHTEK--\n' 'ERR1019366_5760491/40-105 ---RSGAQHHDAAAQHYEEAARHHRMAAKQYQASHHEKAAHYAQLAYAHHMYAEQHAAEAAK-AHAKNHG----\n' 'SRR5580704_12853319/61-125 ----PAADHHMKAAEHHEEAAKHHRAAAEHHTAGDHQKAGHHAHVANGHHVNAVHHAEEASK-HHATDHS----\n' '//\n'), 'tbl': ( 'ERR1700680_4602609 - query - 7.7e-09 47.7 33.8 1.1e-08 47.2 33.8 1.2 1 0 0 1 1 1 1 -\n' 'ERR1019366_5760491 - query - 1.7e-08 46.6 33.1 2.5e-08 46.1 33.1 1.3 1 0 0 1 1 1 1 -\n' 'SRR5580704_12853319 - query - 1.1e-07 44.0 41.6 2e-07 43.1 41.6 1.4 1 0 0 1 1 1 1 -\n'), 'stderr': b'', 'n_iter': 1, 'e_value': 0.0001} MULTI_SEQUENCE_HIT_2 = { 'sto': ( '# STOCKHOLM 1.0\n' '#=GF ID query-i1\n' '#=GS ERR1700719_3476944/70-137 DE [subseq from] ERR1700719_3476944\n' '#=GS ERR1700761_4254522/72-138 DE [subseq from] ERR1700761_4254522\n' '#=GS SRR5438477_9761204/64-132 DE [subseq from] SRR5438477_9761204\n' 'query MAAHKGAEHHHKAAEHHEQAAKHHHAAAEHHEKGEHEQAAHHADTAYAHHKHAEEHAAQAAKHDAEHHAPKPH\n' 'ERR1700719_3476944/70-137 ---KQAAEHHHQAAEHHEHAARHHREAAKHHEAGDHESAAHHAHTAQGHLHQATHHASEAAKLHVEHHGQK--\n' 'ERR1700761_4254522/72-138 ----QASEHHNLAAEHHEHAARHHRDAAKHHKAGDHEKAAHHAHVAHGHHLHATHHATEAAKHHVEAHGEK--\n' 'SRR5438477_9761204/64-132 MPKHEGAEHHKKAAEHNEHAARHHKEAARHHEEGSHEKVGHHAHIAHGHHLHATHHAEEAAKTHSNQHE----\n' '//\n'), 'tbl': ( 'ERR1700719_3476944 - query - 2e-07 43.2 47.5 3.5e-07 42.4 47.5 1.4 1 0 0 1 1 1 1 -\n' 'ERR1700761_4254522 - query - 6.1e-07 41.6 48.1 8.1e-07 41.3 48.1 1.2 1 0 0 1 1 1 1 -\n' 'SRR5438477_9761204 - query - 1.8e-06 40.2 46.9 2.3e-06 39.8 46.9 1.2 1 0 0 1 1 1 1 -\n'), 'stderr': b'', 'n_iter': 1, 'e_value': 0.0001} # pylint: enable=line-too-long class NotebookUtilsTest(parameterized.TestCase): @parameterized.parameters( ('DeepMind', 'DEEPMIND'), ('A ', 'A'), ('\tA', 'A'), (' A\t\n', 'A'), ('ACDEFGHIKLMNPQRSTVWY', 'ACDEFGHIKLMNPQRSTVWY')) def test_clean_and_validate_sequence_ok(self, sequence, exp_clean): clean = notebook_utils.clean_and_validate_single_sequence( sequence, min_length=1, max_length=100) self.assertEqual(clean, exp_clean) @parameterized.named_parameters( ('too_short', 'AA', 'too short'), ('too_long', 'AAAAAAAAAA', 'too long'), ('bad_amino_acids_B', 'BBBB', 'non-amino acid'), ('bad_amino_acids_J', 'JJJJ', 'non-amino acid'), ('bad_amino_acids_O', 'OOOO', 'non-amino acid'), ('bad_amino_acids_U', 'UUUU', 'non-amino acid'), ('bad_amino_acids_X', 'XXXX', 'non-amino acid'), ('bad_amino_acids_Z', 'ZZZZ', 'non-amino acid')) def test_clean_and_validate_sequence_bad(self, sequence, exp_error): with self.assertRaisesRegex(ValueError, f'.*{exp_error}.*'): notebook_utils.clean_and_validate_single_sequence( sequence, min_length=4, max_length=8) @parameterized.parameters( (['A', '', '', ' ', '\t', ' \t\n', '', ''], ['A']), (['', 'A'], ['A']), (['A', 'C ', ''], ['A', 'C']), (['', 'A', '', 'C '], ['A', 'C'])) def test_validate_input_ok(self, input_sequences, exp_sequences): sequences = notebook_utils.clean_and_validate_input_sequences( input_sequences=input_sequences, min_sequence_length=1, max_sequence_length=100) self.assertSequenceEqual(sequences, exp_sequences) @parameterized.named_parameters( ('no_input_sequence', ['', '\t', '\n'], 'No input amino acid sequence'), ('too_long_single', ['AAAAAAAAA', 'AAAA'], 'Input sequence is too long'), ('too_short_single', ['AAA', 'AAAA'], 'Input sequence is too short')) def test_validate_input_bad(self, input_sequences, exp_error): with self.assertRaisesRegex(ValueError, f'.*{exp_error}.*'): notebook_utils.clean_and_validate_input_sequences( input_sequences=input_sequences, min_sequence_length=4, max_sequence_length=8) def test_merge_chunked_msa_no_hits(self): results = [ONLY_QUERY_HIT, ONLY_QUERY_HIT] merged_msa = notebook_utils.merge_chunked_msa( results=results) self.assertSequenceEqual( merged_msa.sequences, ('MAAHKGAEHHHKAAEHHEQAAKHHHAAAEHHEKGEHEQAAHHADTAYAHHKHAEEH',)) self.assertSequenceEqual(merged_msa.deletion_matrix, ([0] * 56,)) def test_merge_chunked_msa(self): results = [MULTI_SEQUENCE_HIT_1, MULTI_SEQUENCE_HIT_2] merged_msa = notebook_utils.merge_chunked_msa( results=results) self.assertLen(merged_msa.sequences, 7) # The 1st one is the query. self.assertEqual( merged_msa.sequences[0], 'MAAHKGAEHHHKAAEHHEQAAKHHHAAAEHHEKGEHEQAAHHADTAYAHHKHAEEHAAQAAKHDAEHHAP' 'KPH') # The 2nd one is the one with the lowest e-value: ERR1700680_4602609. self.assertEqual( merged_msa.sequences[1], '--INKGAEYHKKAAEHHELAAKHHREAAKHHEAGSHEKAAHHSEIAAGHGLTAVHHTEEATK-HHPEEHT' 'EK-') # The last one is the one with the largest e-value: SRR5438477_9761204. self.assertEqual( merged_msa.sequences[-1], 'MPKHEGAEHHKKAAEHNEHAARHHKEAARHHEEGSHEKVGHHAHIAHGHHLHATHHAEEAAKTHSNQHE-' '---') self.assertLen(merged_msa.deletion_matrix, 7) @mock.patch('sys.stdout', new_callable=io.StringIO) def test_show_msa_info(self, mocked_stdout): single_chain_msas = [ parsers.Msa(sequences=['A', 'B', 'C', 'C'], deletion_matrix=[None] * 4, descriptions=[''] * 4), parsers.Msa(sequences=['A', 'A', 'A', 'D'], deletion_matrix=[None] * 4, descriptions=[''] * 4) ] notebook_utils.show_msa_info( single_chain_msas=single_chain_msas, sequence_index=1) self.assertEqual(mocked_stdout.getvalue(), '\n4 unique sequences found in total for sequence 1\n\n') @parameterized.named_parameters( ('some_templates', 4), ('no_templates', 0)) def test_empty_placeholder_template_features(self, num_templates): template_features = notebook_utils.empty_placeholder_template_features( num_templates=num_templates, num_res=16) self.assertCountEqual(template_features.keys(), templates.TEMPLATE_FEATURES.keys()) self.assertSameElements( [v.shape[0] for v in template_features.values()], [num_templates]) self.assertSequenceEqual( [t.dtype for t in template_features.values()], [np.array([], dtype=templates.TEMPLATE_FEATURES[feat_name]).dtype for feat_name in template_features]) def test_get_pae_json(self): pae = np.array([[0.01, 13.12345], [20.0987, 0.0]]) pae_json = notebook_utils.get_pae_json(pae=pae, max_pae=31.75) self.assertEqual( pae_json, '[{"predicted_aligned_error":[[0.0,13.1],[20.1,0.0]],' '"max_predicted_aligned_error":31.75}]') if __name__ == '__main__': absltest.main() ================================================ FILE: alphafold/relax/__init__.py ================================================ # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Amber relaxation.""" ================================================ FILE: alphafold/relax/amber_minimize.py ================================================ # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Restrained Amber Minimization of a structure.""" import io import time from typing import Collection, Optional, Sequence from absl import logging from alphafold.common import protein from alphafold.common import residue_constants from alphafold.model import folding from alphafold.relax import cleanup from alphafold.relax import utils import ml_collections import numpy as np import jax import openmm from openmm import unit from openmm import app as openmm_app from openmm.app.internal.pdbstructure import PdbStructure ENERGY = unit.kilocalories_per_mole LENGTH = unit.angstroms def will_restrain(atom: openmm_app.Atom, rset: str) -> bool: """Returns True if the atom will be restrained by the given restraint set.""" if rset == "non_hydrogen": return atom.element.name != "hydrogen" elif rset == "c_alpha": return atom.name == "CA" def _add_restraints( system: openmm.System, reference_pdb: openmm_app.PDBFile, stiffness: unit.Unit, rset: str, exclude_residues: Sequence[int]): """Adds a harmonic potential that restrains the system to a structure.""" assert rset in ["non_hydrogen", "c_alpha"] force = openmm.CustomExternalForce( "0.5 * k * ((x-x0)^2 + (y-y0)^2 + (z-z0)^2)") force.addGlobalParameter("k", stiffness) for p in ["x0", "y0", "z0"]: force.addPerParticleParameter(p) for i, atom in enumerate(reference_pdb.topology.atoms()): if atom.residue.index in exclude_residues: continue if will_restrain(atom, rset): force.addParticle(i, reference_pdb.positions[i]) logging.info("Restraining %d / %d particles.", force.getNumParticles(), system.getNumParticles()) system.addForce(force) def _openmm_minimize( pdb_str: str, max_iterations: int, tolerance: unit.Unit, stiffness: unit.Unit, restraint_set: str, exclude_residues: Sequence[int], use_gpu: bool): """Minimize energy via openmm.""" pdb_file = io.StringIO(pdb_str) pdb = openmm_app.PDBFile(pdb_file) force_field = openmm_app.ForceField("amber99sb.xml") constraints = openmm_app.HBonds system = force_field.createSystem( pdb.topology, constraints=constraints) if stiffness > 0 * ENERGY / (LENGTH**2): _add_restraints(system, pdb, stiffness, restraint_set, exclude_residues) integrator = openmm.LangevinIntegrator(0, 0.01, 0.0) platform = openmm.Platform.getPlatformByName("CUDA" if use_gpu else "CPU") simulation = openmm_app.Simulation( pdb.topology, system, integrator, platform) simulation.context.setPositions(pdb.positions) ret = {} state = simulation.context.getState(getEnergy=True, getPositions=True) ret["einit"] = state.getPotentialEnergy().value_in_unit(ENERGY) ret["posinit"] = state.getPositions(asNumpy=True).value_in_unit(LENGTH) simulation.minimizeEnergy(maxIterations=max_iterations, tolerance=tolerance) state = simulation.context.getState(getEnergy=True, getPositions=True) ret["efinal"] = state.getPotentialEnergy().value_in_unit(ENERGY) ret["pos"] = state.getPositions(asNumpy=True).value_in_unit(LENGTH) ret["min_pdb"] = _get_pdb_string(simulation.topology, state.getPositions()) return ret def _get_pdb_string(topology: openmm_app.Topology, positions: unit.Quantity): """Returns a pdb string provided OpenMM topology and positions.""" with io.StringIO() as f: openmm_app.PDBFile.writeFile(topology, positions, f) return f.getvalue() def _check_cleaned_atoms(pdb_cleaned_string: str, pdb_ref_string: str): """Checks that no atom positions have been altered by cleaning.""" cleaned = openmm_app.PDBFile(io.StringIO(pdb_cleaned_string)) reference = openmm_app.PDBFile(io.StringIO(pdb_ref_string)) cl_xyz = np.array(cleaned.getPositions().value_in_unit(LENGTH)) ref_xyz = np.array(reference.getPositions().value_in_unit(LENGTH)) for ref_res, cl_res in zip(reference.topology.residues(), cleaned.topology.residues()): assert ref_res.name == cl_res.name for rat in ref_res.atoms(): for cat in cl_res.atoms(): if cat.name == rat.name: if not np.array_equal(cl_xyz[cat.index], ref_xyz[rat.index]): raise ValueError(f"Coordinates of cleaned atom {cat} do not match " f"coordinates of reference atom {rat}.") def _check_residues_are_well_defined(prot: protein.Protein): """Checks that all residues contain non-empty atom sets.""" if (prot.atom_mask.sum(axis=-1) == 0).any(): raise ValueError("Amber minimization can only be performed on proteins with" " well-defined residues. This protein contains at least" " one residue with no atoms.") def _check_atom_mask_is_ideal(prot): """Sanity-check the atom mask is ideal, up to a possible OXT.""" atom_mask = prot.atom_mask ideal_atom_mask = protein.ideal_atom_mask(prot) utils.assert_equal_nonterminal_atom_types(atom_mask, ideal_atom_mask) def clean_protein( prot: protein.Protein, checks: bool = True): """Adds missing atoms to Protein instance. Args: prot: A `protein.Protein` instance. checks: A `bool` specifying whether to add additional checks to the cleaning process. Returns: pdb_string: A string of the cleaned protein. """ _check_atom_mask_is_ideal(prot) # Clean pdb. prot_pdb_string = protein.to_pdb(prot) pdb_file = io.StringIO(prot_pdb_string) alterations_info = {} fixed_pdb = cleanup.fix_pdb(pdb_file, alterations_info) fixed_pdb_file = io.StringIO(fixed_pdb) pdb_structure = PdbStructure(fixed_pdb_file) cleanup.clean_structure(pdb_structure, alterations_info) logging.info("alterations info: %s", alterations_info) # Write pdb file of cleaned structure. as_file = openmm_app.PDBFile(pdb_structure) pdb_string = _get_pdb_string(as_file.getTopology(), as_file.getPositions()) if checks: _check_cleaned_atoms(pdb_string, prot_pdb_string) return pdb_string def make_atom14_positions(prot): """Constructs denser atom positions (14 dimensions instead of 37).""" restype_atom14_to_atom37 = [] # mapping (restype, atom14) --> atom37 restype_atom37_to_atom14 = [] # mapping (restype, atom37) --> atom14 restype_atom14_mask = [] for rt in residue_constants.restypes: atom_names = residue_constants.restype_name_to_atom14_names[ residue_constants.restype_1to3[rt]] restype_atom14_to_atom37.append([ (residue_constants.atom_order[name] if name else 0) for name in atom_names ]) atom_name_to_idx14 = {name: i for i, name in enumerate(atom_names)} restype_atom37_to_atom14.append([ (atom_name_to_idx14[name] if name in atom_name_to_idx14 else 0) for name in residue_constants.atom_types ]) restype_atom14_mask.append([(1. if name else 0.) for name in atom_names]) # Add dummy mapping for restype 'UNK'. restype_atom14_to_atom37.append([0] * 14) restype_atom37_to_atom14.append([0] * 37) restype_atom14_mask.append([0.] * 14) restype_atom14_to_atom37 = np.array(restype_atom14_to_atom37, dtype=np.int32) restype_atom37_to_atom14 = np.array(restype_atom37_to_atom14, dtype=np.int32) restype_atom14_mask = np.array(restype_atom14_mask, dtype=np.float32) # Create the mapping for (residx, atom14) --> atom37, i.e. an array # with shape (num_res, 14) containing the atom37 indices for this protein. residx_atom14_to_atom37 = restype_atom14_to_atom37[prot["aatype"]] residx_atom14_mask = restype_atom14_mask[prot["aatype"]] # Create a mask for known ground truth positions. residx_atom14_gt_mask = residx_atom14_mask * np.take_along_axis( prot["all_atom_mask"], residx_atom14_to_atom37, axis=1).astype(np.float32) # Gather the ground truth positions. residx_atom14_gt_positions = residx_atom14_gt_mask[:, :, None] * ( np.take_along_axis(prot["all_atom_positions"], residx_atom14_to_atom37[..., None], axis=1)) prot["atom14_atom_exists"] = residx_atom14_mask prot["atom14_gt_exists"] = residx_atom14_gt_mask prot["atom14_gt_positions"] = residx_atom14_gt_positions prot["residx_atom14_to_atom37"] = residx_atom14_to_atom37 # Create the gather indices for mapping back. residx_atom37_to_atom14 = restype_atom37_to_atom14[prot["aatype"]] prot["residx_atom37_to_atom14"] = residx_atom37_to_atom14 # Create the corresponding mask. restype_atom37_mask = np.zeros([21, 37], dtype=np.float32) for restype, restype_letter in enumerate(residue_constants.restypes): restype_name = residue_constants.restype_1to3[restype_letter] atom_names = residue_constants.residue_atoms[restype_name] for atom_name in atom_names: atom_type = residue_constants.atom_order[atom_name] restype_atom37_mask[restype, atom_type] = 1 residx_atom37_mask = restype_atom37_mask[prot["aatype"]] prot["atom37_atom_exists"] = residx_atom37_mask # As the atom naming is ambiguous for 7 of the 20 amino acids, provide # alternative ground truth coordinates where the naming is swapped restype_3 = [ residue_constants.restype_1to3[res] for res in residue_constants.restypes ] restype_3 += ["UNK"] # Matrices for renaming ambiguous atoms. all_matrices = {res: np.eye(14, dtype=np.float32) for res in restype_3} for resname, swap in residue_constants.residue_atom_renaming_swaps.items(): correspondences = np.arange(14) for source_atom_swap, target_atom_swap in swap.items(): source_index = residue_constants.restype_name_to_atom14_names[ resname].index(source_atom_swap) target_index = residue_constants.restype_name_to_atom14_names[ resname].index(target_atom_swap) correspondences[source_index] = target_index correspondences[target_index] = source_index renaming_matrix = np.zeros((14, 14), dtype=np.float32) for index, correspondence in enumerate(correspondences): renaming_matrix[index, correspondence] = 1. all_matrices[resname] = renaming_matrix.astype(np.float32) renaming_matrices = np.stack([all_matrices[restype] for restype in restype_3]) # Pick the transformation matrices for the given residue sequence # shape (num_res, 14, 14). renaming_transform = renaming_matrices[prot["aatype"]] # Apply it to the ground truth positions. shape (num_res, 14, 3). alternative_gt_positions = np.einsum("rac,rab->rbc", residx_atom14_gt_positions, renaming_transform) prot["atom14_alt_gt_positions"] = alternative_gt_positions # Create the mask for the alternative ground truth (differs from the # ground truth mask, if only one of the atoms in an ambiguous pair has a # ground truth position). alternative_gt_mask = np.einsum("ra,rab->rb", residx_atom14_gt_mask, renaming_transform) prot["atom14_alt_gt_exists"] = alternative_gt_mask # Create an ambiguous atoms mask. shape: (21, 14). restype_atom14_is_ambiguous = np.zeros((21, 14), dtype=np.float32) for resname, swap in residue_constants.residue_atom_renaming_swaps.items(): for atom_name1, atom_name2 in swap.items(): restype = residue_constants.restype_order[ residue_constants.restype_3to1[resname]] atom_idx1 = residue_constants.restype_name_to_atom14_names[resname].index( atom_name1) atom_idx2 = residue_constants.restype_name_to_atom14_names[resname].index( atom_name2) restype_atom14_is_ambiguous[restype, atom_idx1] = 1 restype_atom14_is_ambiguous[restype, atom_idx2] = 1 # From this create an ambiguous_mask for the given sequence. prot["atom14_atom_is_ambiguous"] = ( restype_atom14_is_ambiguous[prot["aatype"]]) return prot def find_violations(prot_np: protein.Protein): """Analyzes a protein and returns structural violation information. Args: prot_np: A protein. Returns: violations: A `dict` of structure components with structural violations. violation_metrics: A `dict` of violation metrics. """ batch = { "aatype": prot_np.aatype, "all_atom_positions": prot_np.atom_positions.astype(np.float32), "all_atom_mask": prot_np.atom_mask.astype(np.float32), "residue_index": prot_np.residue_index, } batch["seq_mask"] = np.ones_like(batch["aatype"], np.float32) batch = make_atom14_positions(batch) violations = folding.find_structural_violations( batch=batch, atom14_pred_positions=batch["atom14_gt_positions"], config=ml_collections.ConfigDict( {"violation_tolerance_factor": 12, # Taken from model config. "clash_overlap_tolerance": 1.5, # Taken from model config. })) violation_metrics = folding.compute_violation_metrics( batch=batch, atom14_pred_positions=batch["atom14_gt_positions"], violations=violations, ) return violations, violation_metrics def get_violation_metrics(prot: protein.Protein): """Computes violation and alignment metrics.""" structural_violations, struct_metrics = find_violations(prot) violation_idx = np.flatnonzero( structural_violations["total_per_residue_violations_mask"]) struct_metrics["residue_violations"] = violation_idx struct_metrics["num_residue_violations"] = len(violation_idx) struct_metrics["structural_violations"] = structural_violations return struct_metrics def _run_one_iteration( *, pdb_string: str, max_iterations: int, tolerance: float, stiffness: float, restraint_set: str, max_attempts: int, use_gpu: bool, exclude_residues: Optional[Collection[int]] = None): """Runs the minimization pipeline. Args: pdb_string: A pdb string. max_iterations: An `int` specifying the maximum number of L-BFGS iterations. A value of 0 specifies no limit. tolerance: kcal/mol, the energy tolerance of L-BFGS. stiffness: kcal/mol A**2, spring constant of heavy atom restraining potential. restraint_set: The set of atoms to restrain. max_attempts: The maximum number of minimization attempts. use_gpu: Whether to run on GPU. exclude_residues: An optional list of zero-indexed residues to exclude from restraints. Returns: A `dict` of minimization info. """ exclude_residues = exclude_residues or [] # Assign physical dimensions. tolerance = tolerance * ENERGY stiffness = stiffness * ENERGY / (LENGTH**2) start = time.time() minimized = False attempts = 0 while not minimized and attempts < max_attempts: attempts += 1 try: logging.info("Minimizing protein, attempt %d of %d.", attempts, max_attempts) ret = _openmm_minimize( pdb_string, max_iterations=max_iterations, tolerance=tolerance, stiffness=stiffness, restraint_set=restraint_set, exclude_residues=exclude_residues, use_gpu=use_gpu) minimized = True except Exception as e: # pylint: disable=broad-except logging.info(e) if not minimized: raise ValueError(f"Minimization failed after {max_attempts} attempts.") ret["opt_time"] = time.time() - start ret["min_attempts"] = attempts return ret def run_pipeline( prot: protein.Protein, stiffness: float, use_gpu: bool, max_outer_iterations: int = 1, place_hydrogens_every_iteration: bool = True, max_iterations: int = 0, tolerance: float = 2.39, restraint_set: str = "non_hydrogen", max_attempts: int = 100, checks: bool = True, exclude_residues: Optional[Sequence[int]] = None): """Run iterative amber relax. Successive relax iterations are performed until all violations have been resolved. Each iteration involves a restrained Amber minimization, with restraint exclusions determined by violation-participating residues. Args: prot: A protein to be relaxed. stiffness: kcal/mol A**2, the restraint stiffness. use_gpu: Whether to run on GPU. max_outer_iterations: The maximum number of iterative minimization. place_hydrogens_every_iteration: Whether hydrogens are re-initialized prior to every minimization. max_iterations: An `int` specifying the maximum number of L-BFGS steps per relax iteration. A value of 0 specifies no limit. tolerance: kcal/mol, the energy tolerance of L-BFGS. The default value is the OpenMM default. restraint_set: The set of atoms to restrain. max_attempts: The maximum number of minimization attempts per iteration. checks: Whether to perform cleaning checks. exclude_residues: An optional list of zero-indexed residues to exclude from restraints. Returns: out: A dictionary of output values. """ # `protein.to_pdb` will strip any poorly-defined residues so we need to # perform this check before `clean_protein`. _check_residues_are_well_defined(prot) pdb_string = clean_protein(prot, checks=checks) exclude_residues = exclude_residues or [] exclude_residues = set(exclude_residues) violations = np.inf iteration = 0 while violations > 0 and iteration < max_outer_iterations: ret = _run_one_iteration( pdb_string=pdb_string, exclude_residues=exclude_residues, max_iterations=max_iterations, tolerance=tolerance, stiffness=stiffness, restraint_set=restraint_set, max_attempts=max_attempts, use_gpu=use_gpu) prot = protein.from_pdb_string(ret["min_pdb"]) if place_hydrogens_every_iteration: pdb_string = clean_protein(prot, checks=True) else: pdb_string = ret["min_pdb"] # Calculation of violations can cause CUDA errors for some JAX versions. with jax.default_device(jax.devices("cpu")[0]): ret.update(get_violation_metrics(prot)) ret.update({ "num_exclusions": len(exclude_residues), "iteration": iteration, }) violations = ret["violations_per_residue"] exclude_residues = exclude_residues.union(ret["residue_violations"]) logging.info("Iteration completed: Einit %.2f Efinal %.2f Time %.2f s " "num residue violations %d num residue exclusions %d ", ret["einit"], ret["efinal"], ret["opt_time"], ret["num_residue_violations"], ret["num_exclusions"]) iteration += 1 return ret ================================================ FILE: alphafold/relax/amber_minimize_test.py ================================================ # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Tests for amber_minimize.""" import os from absl.testing import absltest from alphafold.common import protein from alphafold.relax import amber_minimize import numpy as np # Internal import (7716). _USE_GPU = False def _load_test_protein(data_path): pdb_path = os.path.join(absltest.get_default_test_srcdir(), data_path) with open(pdb_path, 'r') as f: return protein.from_pdb_string(f.read()) class AmberMinimizeTest(absltest.TestCase): def test_multiple_disulfides_target(self): prot = _load_test_protein( 'alphafold/relax/testdata/multiple_disulfides_target.pdb' ) ret = amber_minimize.run_pipeline(prot, max_iterations=10, max_attempts=1, stiffness=10., use_gpu=_USE_GPU) self.assertIn('opt_time', ret) self.assertIn('min_attempts', ret) def test_raises_invalid_protein_assertion(self): prot = _load_test_protein( 'alphafold/relax/testdata/multiple_disulfides_target.pdb' ) prot.atom_mask[4, :] = 0 with self.assertRaisesRegex( ValueError, 'Amber minimization can only be performed on proteins with well-defined' ' residues. This protein contains at least one residue with no atoms.'): amber_minimize.run_pipeline(prot, max_iterations=10, stiffness=1., max_attempts=1, use_gpu=_USE_GPU) def test_iterative_relax(self): prot = _load_test_protein( 'alphafold/relax/testdata/with_violations.pdb' ) violations = amber_minimize.get_violation_metrics(prot) self.assertGreater(violations['num_residue_violations'], 0) out = amber_minimize.run_pipeline( prot=prot, max_outer_iterations=10, stiffness=10., use_gpu=_USE_GPU) self.assertLess(out['efinal'], out['einit']) self.assertEqual(0, out['num_residue_violations']) def test_find_violations(self): prot = _load_test_protein( 'alphafold/relax/testdata/multiple_disulfides_target.pdb' ) viols, _ = amber_minimize.find_violations(prot) expected_between_residues_connection_mask = np.zeros((191,), np.float32) for residue in (42, 43, 59, 60, 135, 136): expected_between_residues_connection_mask[residue] = 1.0 expected_clash_indices = np.array([ [8, 4], [8, 5], [13, 3], [14, 1], [14, 4], [26, 4], [26, 5], [31, 8], [31, 10], [39, 0], [39, 1], [39, 2], [39, 3], [39, 4], [42, 5], [42, 6], [42, 7], [42, 8], [47, 7], [47, 8], [47, 9], [47, 10], [64, 4], [85, 5], [102, 4], [102, 5], [109, 13], [111, 5], [118, 6], [118, 7], [118, 8], [124, 4], [124, 5], [131, 5], [139, 7], [147, 4], [152, 7]], dtype=np.int32) expected_between_residues_clash_mask = np.zeros([191, 14]) expected_between_residues_clash_mask[expected_clash_indices[:, 0], expected_clash_indices[:, 1]] += 1 expected_per_atom_violations = np.zeros([191, 14]) np.testing.assert_array_equal( viols['between_residues']['connections_per_residue_violation_mask'], expected_between_residues_connection_mask) np.testing.assert_array_equal( viols['between_residues']['clashes_per_atom_clash_mask'], expected_between_residues_clash_mask) np.testing.assert_array_equal( viols['within_residues']['per_atom_violations'], expected_per_atom_violations) if __name__ == '__main__': absltest.main() ================================================ FILE: alphafold/relax/cleanup.py ================================================ # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Cleans up a PDB file using pdbfixer in preparation for OpenMM simulations. fix_pdb uses a third-party tool. We also support fixing some additional edge cases like removing chains of length one (see clean_structure). """ import io import pdbfixer from openmm import app from openmm.app import element def fix_pdb(pdbfile, alterations_info): """Apply pdbfixer to the contents of a PDB file; return a PDB string result. 1) Replaces nonstandard residues. 2) Removes heterogens (non protein residues) including water. 3) Adds missing residues and missing atoms within existing residues. 4) Adds hydrogens assuming pH=7.0. 5) KeepIds is currently true, so the fixer must keep the existing chain and residue identifiers. This will fail for some files in wider PDB that have invalid IDs. Args: pdbfile: Input PDB file handle. alterations_info: A dict that will store details of changes made. Returns: A PDB string representing the fixed structure. """ fixer = pdbfixer.PDBFixer(pdbfile=pdbfile) fixer.findNonstandardResidues() alterations_info['nonstandard_residues'] = fixer.nonstandardResidues fixer.replaceNonstandardResidues() _remove_heterogens(fixer, alterations_info, keep_water=False) fixer.findMissingResidues() alterations_info['missing_residues'] = fixer.missingResidues fixer.findMissingAtoms() alterations_info['missing_heavy_atoms'] = fixer.missingAtoms alterations_info['missing_terminals'] = fixer.missingTerminals fixer.addMissingAtoms(seed=0) fixer.addMissingHydrogens() out_handle = io.StringIO() app.PDBFile.writeFile(fixer.topology, fixer.positions, out_handle, keepIds=True) return out_handle.getvalue() def clean_structure(pdb_structure, alterations_info): """Applies additional fixes to an OpenMM structure, to handle edge cases. Args: pdb_structure: An OpenMM structure to modify and fix. alterations_info: A dict that will store details of changes made. """ _replace_met_se(pdb_structure, alterations_info) _remove_chains_of_length_one(pdb_structure, alterations_info) def _remove_heterogens(fixer, alterations_info, keep_water): """Removes the residues that Pdbfixer considers to be heterogens. Args: fixer: A Pdbfixer instance. alterations_info: A dict that will store details of changes made. keep_water: If True, water (HOH) is not considered to be a heterogen. """ initial_resnames = set() for chain in fixer.topology.chains(): for residue in chain.residues(): initial_resnames.add(residue.name) fixer.removeHeterogens(keepWater=keep_water) final_resnames = set() for chain in fixer.topology.chains(): for residue in chain.residues(): final_resnames.add(residue.name) alterations_info['removed_heterogens'] = ( initial_resnames.difference(final_resnames)) def _replace_met_se(pdb_structure, alterations_info): """Replace the Se in any MET residues that were not marked as modified.""" modified_met_residues = [] for res in pdb_structure.iter_residues(): name = res.get_name_with_spaces().strip() if name == 'MET': s_atom = res.get_atom('SD') if s_atom.element_symbol == 'Se': s_atom.element_symbol = 'S' s_atom.element = element.get_by_symbol('S') modified_met_residues.append(s_atom.residue_number) alterations_info['Se_in_MET'] = modified_met_residues def _remove_chains_of_length_one(pdb_structure, alterations_info): """Removes chains that correspond to a single amino acid. A single amino acid in a chain is both N and C terminus. There is no force template for this case. Args: pdb_structure: An OpenMM pdb_structure to modify and fix. alterations_info: A dict that will store details of changes made. """ removed_chains = {} for model in pdb_structure.iter_models(): valid_chains = [c for c in model.iter_chains() if len(c) > 1] invalid_chain_ids = [c.chain_id for c in model.iter_chains() if len(c) <= 1] model.chains = valid_chains for chain_id in invalid_chain_ids: model.chains_by_id.pop(chain_id) removed_chains[model.number] = invalid_chain_ids alterations_info['removed_chains'] = removed_chains ================================================ FILE: alphafold/relax/cleanup_test.py ================================================ # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Tests for relax.cleanup.""" import io from absl.testing import absltest from alphafold.relax import cleanup from openmm.app.internal import pdbstructure def _pdb_to_structure(pdb_str): handle = io.StringIO(pdb_str) return pdbstructure.PdbStructure(handle) def _lines_to_structure(pdb_lines): return _pdb_to_structure('\n'.join(pdb_lines)) class CleanupTest(absltest.TestCase): def test_missing_residues(self): pdb_lines = ['SEQRES 1 C 3 CYS GLY LEU', 'ATOM 1 N CYS C 1 -12.262 20.115 60.959 1.00 ' '19.08 N', 'ATOM 2 CA CYS C 1 -11.065 20.934 60.773 1.00 ' '17.23 C', 'ATOM 3 C CYS C 1 -10.002 20.742 61.844 1.00 ' '15.38 C', 'ATOM 4 O CYS C 1 -10.284 20.225 62.929 1.00 ' '16.04 O', 'ATOM 5 N LEU C 3 -7.688 18.700 62.045 1.00 ' '14.75 N', 'ATOM 6 CA LEU C 3 -7.256 17.320 62.234 1.00 ' '16.81 C', 'ATOM 7 C LEU C 3 -6.380 16.864 61.070 1.00 ' '16.95 C', 'ATOM 8 O LEU C 3 -6.551 17.332 59.947 1.00 ' '16.97 O'] input_handle = io.StringIO('\n'.join(pdb_lines)) alterations = {} result = cleanup.fix_pdb(input_handle, alterations) structure = _pdb_to_structure(result) residue_names = [r.get_name() for r in structure.iter_residues()] self.assertCountEqual(residue_names, ['CYS', 'GLY', 'LEU']) self.assertCountEqual(alterations['missing_residues'].values(), [['GLY']]) def test_missing_atoms(self): pdb_lines = ['SEQRES 1 A 1 PRO', 'ATOM 1 CA PRO A 1 1.000 1.000 1.000 1.00 ' ' 0.00 C'] input_handle = io.StringIO('\n'.join(pdb_lines)) alterations = {} result = cleanup.fix_pdb(input_handle, alterations) structure = _pdb_to_structure(result) atom_names = [a.get_name() for a in structure.iter_atoms()] self.assertCountEqual(atom_names, ['N', 'CD', 'HD2', 'HD3', 'CG', 'HG2', 'HG3', 'CB', 'HB2', 'HB3', 'CA', 'HA', 'C', 'O', 'H2', 'H3', 'OXT']) missing_atoms_by_residue = list(alterations['missing_heavy_atoms'].values()) self.assertLen(missing_atoms_by_residue, 1) atoms_added = [a.name for a in missing_atoms_by_residue[0]] self.assertCountEqual(atoms_added, ['N', 'CD', 'CG', 'CB', 'C', 'O']) missing_terminals_by_residue = alterations['missing_terminals'] self.assertLen(missing_terminals_by_residue, 1) has_missing_terminal = [r.name for r in missing_terminals_by_residue.keys()] self.assertCountEqual(has_missing_terminal, ['PRO']) self.assertCountEqual([t for t in missing_terminals_by_residue.values()], [['OXT']]) def test_remove_heterogens(self): pdb_lines = ['SEQRES 1 A 1 GLY', 'ATOM 1 CA GLY A 1 0.000 0.000 0.000 1.00 ' ' 0.00 C', 'ATOM 2 O HOH A 2 0.000 0.000 0.000 1.00 ' ' 0.00 O'] input_handle = io.StringIO('\n'.join(pdb_lines)) alterations = {} result = cleanup.fix_pdb(input_handle, alterations) structure = _pdb_to_structure(result) self.assertCountEqual([res.get_name() for res in structure.iter_residues()], ['GLY']) self.assertEqual(alterations['removed_heterogens'], set(['HOH'])) def test_fix_nonstandard_residues(self): pdb_lines = ['SEQRES 1 A 1 DAL', 'ATOM 1 CA DAL A 1 0.000 0.000 0.000 1.00 ' ' 0.00 C'] input_handle = io.StringIO('\n'.join(pdb_lines)) alterations = {} result = cleanup.fix_pdb(input_handle, alterations) structure = _pdb_to_structure(result) residue_names = [res.get_name() for res in structure.iter_residues()] self.assertCountEqual(residue_names, ['ALA']) self.assertLen(alterations['nonstandard_residues'], 1) original_res, new_name = alterations['nonstandard_residues'][0] self.assertEqual(original_res.id, '1') self.assertEqual(new_name, 'ALA') def test_replace_met_se(self): pdb_lines = ['SEQRES 1 A 1 MET', 'ATOM 1 SD MET A 1 0.000 0.000 0.000 1.00 ' ' 0.00 Se'] structure = _lines_to_structure(pdb_lines) alterations = {} cleanup._replace_met_se(structure, alterations) sd = [a for a in structure.iter_atoms() if a.get_name() == 'SD'] self.assertLen(sd, 1) self.assertEqual(sd[0].element_symbol, 'S') self.assertCountEqual(alterations['Se_in_MET'], [sd[0].residue_number]) def test_remove_chains_of_length_one(self): pdb_lines = ['SEQRES 1 A 1 GLY', 'ATOM 1 CA GLY A 1 0.000 0.000 0.000 1.00 ' ' 0.00 C'] structure = _lines_to_structure(pdb_lines) alterations = {} cleanup._remove_chains_of_length_one(structure, alterations) chains = list(structure.iter_chains()) self.assertEmpty(chains) self.assertCountEqual(alterations['removed_chains'].values(), [['A']]) if __name__ == '__main__': absltest.main() ================================================ FILE: alphafold/relax/relax.py ================================================ # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Amber relaxation.""" from typing import Any, Dict, Sequence, Tuple from alphafold.common import protein from alphafold.relax import amber_minimize from alphafold.relax import utils import numpy as np class AmberRelaxation(object): """Amber relaxation.""" def __init__(self, *, max_iterations: int, tolerance: float, stiffness: float, exclude_residues: Sequence[int], max_outer_iterations: int, use_gpu: bool): """Initialize Amber Relaxer. Args: max_iterations: Maximum number of L-BFGS iterations. 0 means no max. tolerance: kcal/mol, the energy tolerance of L-BFGS. stiffness: kcal/mol A**2, spring constant of heavy atom restraining potential. exclude_residues: Residues to exclude from per-atom restraining. Zero-indexed. max_outer_iterations: Maximum number of violation-informed relax iterations. A value of 1 will run the non-iterative procedure used in CASP14. Use 20 so that >95% of the bad cases are relaxed. Relax finishes as soon as there are no violations, hence in most cases this causes no slowdown. In the worst case we do 20 outer iterations. use_gpu: Whether to run on GPU. """ self._max_iterations = max_iterations self._tolerance = tolerance self._stiffness = stiffness self._exclude_residues = exclude_residues self._max_outer_iterations = max_outer_iterations self._use_gpu = use_gpu def process(self, *, prot: protein.Protein ) -> Tuple[str, Dict[str, Any], Sequence[float]]: """Runs Amber relax on a prediction, adds hydrogens, returns PDB string.""" out = amber_minimize.run_pipeline( prot=prot, max_iterations=self._max_iterations, tolerance=self._tolerance, stiffness=self._stiffness, exclude_residues=self._exclude_residues, max_outer_iterations=self._max_outer_iterations, use_gpu=self._use_gpu) min_pos = out['pos'] start_pos = out['posinit'] rmsd = np.sqrt(np.sum((start_pos - min_pos)**2) / start_pos.shape[0]) debug_data = { 'initial_energy': out['einit'], 'final_energy': out['efinal'], 'attempts': out['min_attempts'], 'rmsd': rmsd } min_pdb = out['min_pdb'] min_pdb = utils.overwrite_b_factors(min_pdb, prot.b_factors) utils.assert_equal_nonterminal_atom_types( protein.from_pdb_string(min_pdb).atom_mask, prot.atom_mask) violations = out['structural_violations'][ 'total_per_residue_violations_mask'].tolist() return min_pdb, debug_data, violations ================================================ FILE: alphafold/relax/relax_test.py ================================================ # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Tests for relax.""" import os from absl.testing import absltest from alphafold.common import protein from alphafold.relax import relax import numpy as np # Internal import (7716). class RunAmberRelaxTest(absltest.TestCase): def setUp(self): super().setUp() self.test_dir = os.path.join( absltest.get_default_test_srcdir(), 'alphafold/relax/testdata/') self.test_config = { 'max_iterations': 1, 'tolerance': 2.39, 'stiffness': 10.0, 'exclude_residues': [], 'max_outer_iterations': 1, 'use_gpu': False} def test_process(self): amber_relax = relax.AmberRelaxation(**self.test_config) with open(os.path.join(self.test_dir, 'model_output.pdb')) as f: test_prot = protein.from_pdb_string(f.read()) pdb_min, debug_info, num_violations = amber_relax.process(prot=test_prot) self.assertCountEqual(debug_info.keys(), set({'initial_energy', 'final_energy', 'attempts', 'rmsd'})) self.assertLess(debug_info['final_energy'], debug_info['initial_energy']) self.assertGreater(debug_info['rmsd'], 0) prot_min = protein.from_pdb_string(pdb_min) # Most protein properties should be unchanged. np.testing.assert_almost_equal(test_prot.aatype, prot_min.aatype) np.testing.assert_almost_equal(test_prot.residue_index, prot_min.residue_index) # Atom mask and bfactors identical except for terminal OXT of last residue. np.testing.assert_almost_equal(test_prot.atom_mask[:-1, :], prot_min.atom_mask[:-1, :]) np.testing.assert_almost_equal(test_prot.b_factors[:-1, :], prot_min.b_factors[:-1, :]) np.testing.assert_almost_equal(test_prot.atom_mask[:, :-1], prot_min.atom_mask[:, :-1]) np.testing.assert_almost_equal(test_prot.b_factors[:, :-1], prot_min.b_factors[:, :-1]) # There are no residues with violations. np.testing.assert_equal(num_violations, np.zeros_like(num_violations)) def test_unresolved_violations(self): amber_relax = relax.AmberRelaxation(**self.test_config) with open(os.path.join(self.test_dir, 'with_violations_casp14.pdb')) as f: test_prot = protein.from_pdb_string(f.read()) _, _, num_violations = amber_relax.process(prot=test_prot) exp_num_violations = np.array( [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0]) # Check no violations were added. Can't check exactly due to stochasticity. self.assertTrue(np.all(np.array(num_violations) <= exp_num_violations)) if __name__ == '__main__': absltest.main() ================================================ FILE: alphafold/relax/testdata/model_output.pdb ================================================ ATOM 1 C MET A 1 1.921 -46.152 7.786 1.00 4.39 C ATOM 2 CA MET A 1 1.631 -46.829 9.131 1.00 4.39 C ATOM 3 CB MET A 1 2.759 -47.768 9.578 1.00 4.39 C ATOM 4 CE MET A 1 3.466 -49.770 13.198 1.00 4.39 C ATOM 5 CG MET A 1 2.581 -48.221 11.034 1.00 4.39 C ATOM 6 H MET A 1 0.234 -48.249 8.549 1.00 4.39 H ATOM 7 H2 MET A 1 -0.424 -46.789 8.952 1.00 4.39 H ATOM 8 H3 MET A 1 0.111 -47.796 10.118 1.00 4.39 H ATOM 9 HA MET A 1 1.628 -46.009 9.849 1.00 4.39 H ATOM 10 HB2 MET A 1 3.701 -47.225 9.500 1.00 4.39 H ATOM 11 HB3 MET A 1 2.807 -48.640 8.926 1.00 4.39 H ATOM 12 HE1 MET A 1 2.747 -50.537 12.910 1.00 4.39 H ATOM 13 HE2 MET A 1 4.296 -50.241 13.725 1.00 4.39 H ATOM 14 HE3 MET A 1 2.988 -49.052 13.864 1.00 4.39 H ATOM 15 HG2 MET A 1 1.791 -48.971 11.083 1.00 4.39 H ATOM 16 HG3 MET A 1 2.295 -47.368 11.650 1.00 4.39 H ATOM 17 N MET A 1 0.291 -47.464 9.182 1.00 4.39 N ATOM 18 O MET A 1 2.091 -44.945 7.799 1.00 4.39 O ATOM 19 SD MET A 1 4.096 -48.921 11.725 1.00 4.39 S ATOM 20 C LYS A 2 1.366 -45.033 4.898 1.00 2.92 C ATOM 21 CA LYS A 2 2.235 -46.242 5.308 1.00 2.92 C ATOM 22 CB LYS A 2 2.206 -47.314 4.196 1.00 2.92 C ATOM 23 CD LYS A 2 3.331 -49.342 3.134 1.00 2.92 C ATOM 24 CE LYS A 2 4.434 -50.403 3.293 1.00 2.92 C ATOM 25 CG LYS A 2 3.294 -48.395 4.349 1.00 2.92 C ATOM 26 H LYS A 2 1.832 -47.853 6.656 1.00 2.92 H ATOM 27 HA LYS A 2 3.248 -45.841 5.355 1.00 2.92 H ATOM 28 HB2 LYS A 2 1.223 -47.785 4.167 1.00 2.92 H ATOM 29 HB3 LYS A 2 2.363 -46.812 3.241 1.00 2.92 H ATOM 30 HD2 LYS A 2 3.524 -48.754 2.237 1.00 2.92 H ATOM 31 HD3 LYS A 2 2.364 -49.833 3.031 1.00 2.92 H ATOM 32 HE2 LYS A 2 5.383 -49.891 3.455 1.00 2.92 H ATOM 33 HE3 LYS A 2 4.225 -51.000 4.180 1.00 2.92 H ATOM 34 HG2 LYS A 2 3.102 -48.977 5.250 1.00 2.92 H ATOM 35 HG3 LYS A 2 4.264 -47.909 4.446 1.00 2.92 H ATOM 36 HZ1 LYS A 2 4.763 -50.747 1.274 1.00 2.92 H ATOM 37 HZ2 LYS A 2 3.681 -51.785 1.931 1.00 2.92 H ATOM 38 HZ3 LYS A 2 5.280 -51.965 2.224 1.00 2.92 H ATOM 39 N LYS A 2 1.907 -46.846 6.629 1.00 2.92 N ATOM 40 NZ LYS A 2 4.542 -51.286 2.100 1.00 2.92 N ATOM 41 O LYS A 2 1.882 -44.093 4.312 1.00 2.92 O ATOM 42 C PHE A 3 -0.511 -42.597 5.624 1.00 4.39 C ATOM 43 CA PHE A 3 -0.853 -43.933 4.929 1.00 4.39 C ATOM 44 CB PHE A 3 -2.271 -44.408 5.285 1.00 4.39 C ATOM 45 CD1 PHE A 3 -3.760 -43.542 3.432 1.00 4.39 C ATOM 46 CD2 PHE A 3 -4.050 -42.638 5.675 1.00 4.39 C ATOM 47 CE1 PHE A 3 -4.797 -42.715 2.965 1.00 4.39 C ATOM 48 CE2 PHE A 3 -5.091 -41.818 5.207 1.00 4.39 C ATOM 49 CG PHE A 3 -3.382 -43.505 4.788 1.00 4.39 C ATOM 50 CZ PHE A 3 -5.463 -41.853 3.853 1.00 4.39 C ATOM 51 H PHE A 3 -0.311 -45.868 5.655 1.00 4.39 H ATOM 52 HA PHE A 3 -0.817 -43.746 3.856 1.00 4.39 H ATOM 53 HB2 PHE A 3 -2.353 -44.512 6.367 1.00 4.39 H ATOM 54 HB3 PHE A 3 -2.432 -45.393 4.848 1.00 4.39 H ATOM 55 HD1 PHE A 3 -3.255 -44.198 2.739 1.00 4.39 H ATOM 56 HD2 PHE A 3 -3.768 -42.590 6.716 1.00 4.39 H ATOM 57 HE1 PHE A 3 -5.083 -42.735 1.923 1.00 4.39 H ATOM 58 HE2 PHE A 3 -5.604 -41.151 5.885 1.00 4.39 H ATOM 59 HZ PHE A 3 -6.257 -41.215 3.493 1.00 4.39 H ATOM 60 N PHE A 3 0.079 -45.027 5.253 1.00 4.39 N ATOM 61 O PHE A 3 -0.633 -41.541 5.014 1.00 4.39 O ATOM 62 C LEU A 4 1.598 -40.732 7.042 1.00 4.39 C ATOM 63 CA LEU A 4 0.367 -41.437 7.633 1.00 4.39 C ATOM 64 CB LEU A 4 0.628 -41.823 9.104 1.00 4.39 C ATOM 65 CD1 LEU A 4 -0.319 -42.778 11.228 1.00 4.39 C ATOM 66 CD2 LEU A 4 -1.300 -40.694 10.309 1.00 4.39 C ATOM 67 CG LEU A 4 -0.650 -42.027 9.937 1.00 4.39 C ATOM 68 H LEU A 4 0.163 -43.538 7.292 1.00 4.39 H ATOM 69 HA LEU A 4 -0.445 -40.712 7.588 1.00 4.39 H ATOM 70 HB2 LEU A 4 1.213 -41.034 9.576 1.00 4.39 H ATOM 71 HB3 LEU A 4 1.235 -42.728 9.127 1.00 4.39 H ATOM 72 HD11 LEU A 4 0.380 -42.191 11.824 1.00 4.39 H ATOM 73 HD12 LEU A 4 0.127 -43.747 11.002 1.00 4.39 H ATOM 74 HD13 LEU A 4 -1.230 -42.927 11.808 1.00 4.39 H ATOM 75 HD21 LEU A 4 -0.606 -40.080 10.883 1.00 4.39 H ATOM 76 HD22 LEU A 4 -2.193 -40.869 10.909 1.00 4.39 H ATOM 77 HD23 LEU A 4 -1.593 -40.147 9.413 1.00 4.39 H ATOM 78 HG LEU A 4 -1.359 -42.630 9.370 1.00 4.39 H ATOM 79 N LEU A 4 -0.012 -42.638 6.869 1.00 4.39 N ATOM 80 O LEU A 4 1.655 -39.508 7.028 1.00 4.39 O ATOM 81 C VAL A 5 3.372 -40.190 4.573 1.00 4.39 C ATOM 82 CA VAL A 5 3.752 -40.956 5.845 1.00 4.39 C ATOM 83 CB VAL A 5 4.757 -42.083 5.528 1.00 4.39 C ATOM 84 CG1 VAL A 5 6.019 -41.568 4.827 1.00 4.39 C ATOM 85 CG2 VAL A 5 5.199 -42.807 6.810 1.00 4.39 C ATOM 86 H VAL A 5 2.440 -42.503 6.548 1.00 4.39 H ATOM 87 HA VAL A 5 4.234 -40.242 6.512 1.00 4.39 H ATOM 88 HB VAL A 5 4.279 -42.813 4.875 1.00 4.39 H ATOM 89 HG11 VAL A 5 6.494 -40.795 5.431 1.00 4.39 H ATOM 90 HG12 VAL A 5 5.770 -41.145 3.853 1.00 4.39 H ATOM 91 HG13 VAL A 5 6.725 -42.383 4.670 1.00 4.39 H ATOM 92 HG21 VAL A 5 4.347 -43.283 7.297 1.00 4.39 H ATOM 93 HG22 VAL A 5 5.933 -43.575 6.568 1.00 4.39 H ATOM 94 HG23 VAL A 5 5.651 -42.093 7.498 1.00 4.39 H ATOM 95 N VAL A 5 2.554 -41.501 6.509 1.00 4.39 N ATOM 96 O VAL A 5 3.937 -39.138 4.297 1.00 4.39 O TER 96 VAL A 5 END ================================================ FILE: alphafold/relax/testdata/multiple_disulfides_target.pdb ================================================ MODEL 0 ATOM 1 N MET A 1 19.164 -28.457 26.130 1.00 0.00 N ATOM 2 CA MET A 1 19.746 -27.299 25.456 1.00 0.00 C ATOM 3 C MET A 1 19.080 -26.008 25.921 1.00 0.00 C ATOM 4 CB MET A 1 19.615 -27.438 23.938 1.00 0.00 C ATOM 5 O MET A 1 17.853 -25.899 25.913 1.00 0.00 O ATOM 6 CG MET A 1 19.873 -28.846 23.427 1.00 0.00 C ATOM 7 SD MET A 1 21.636 -29.126 23.002 1.00 0.00 S ATOM 8 CE MET A 1 22.302 -27.462 23.284 1.00 0.00 C ATOM 9 N ALA A 2 19.679 -25.354 27.019 1.00 0.00 N ATOM 10 CA ALA A 2 19.241 -24.061 27.539 1.00 0.00 C ATOM 11 C ALA A 2 18.629 -23.204 26.434 1.00 0.00 C ATOM 12 CB ALA A 2 20.410 -23.326 28.192 1.00 0.00 C ATOM 13 O ALA A 2 19.158 -23.145 25.322 1.00 0.00 O ATOM 14 N HIS A 3 17.369 -23.382 26.161 1.00 0.00 N ATOM 15 CA HIS A 3 16.748 -22.427 25.250 1.00 0.00 C ATOM 16 C HIS A 3 17.419 -21.061 25.342 1.00 0.00 C ATOM 17 CB HIS A 3 15.252 -22.299 25.547 1.00 0.00 C ATOM 18 O HIS A 3 17.896 -20.669 26.409 1.00 0.00 O ATOM 19 CG HIS A 3 14.464 -23.520 25.196 1.00 0.00 C ATOM 20 CD2 HIS A 3 13.848 -24.436 25.979 1.00 0.00 C ATOM 21 ND1 HIS A 3 14.242 -23.914 23.894 1.00 0.00 N ATOM 22 CE1 HIS A 3 13.520 -25.022 23.892 1.00 0.00 C ATOM 23 NE2 HIS A 3 13.268 -25.360 25.145 1.00 0.00 N ATOM 24 N GLU A 4 18.306 -20.798 24.429 1.00 0.00 N ATOM 25 CA GLU A 4 18.907 -19.505 24.115 1.00 0.00 C ATOM 26 C GLU A 4 18.392 -18.415 25.050 1.00 0.00 C ATOM 27 CB GLU A 4 18.631 -19.123 22.659 1.00 0.00 C ATOM 28 O GLU A 4 17.240 -18.458 25.486 1.00 0.00 O ATOM 29 CG GLU A 4 19.253 -20.072 21.645 1.00 0.00 C ATOM 30 CD GLU A 4 20.767 -19.956 21.564 1.00 0.00 C ATOM 31 OE1 GLU A 4 21.330 -18.981 22.111 1.00 0.00 O ATOM 32 OE2 GLU A 4 21.394 -20.846 20.948 1.00 0.00 O ATOM 33 N GLU A 5 19.093 -18.090 26.026 1.00 0.00 N ATOM 34 CA GLU A 5 19.080 -16.885 26.849 1.00 0.00 C ATOM 35 C GLU A 5 17.938 -15.956 26.449 1.00 0.00 C ATOM 36 CB GLU A 5 20.418 -16.148 26.746 1.00 0.00 C ATOM 37 O GLU A 5 17.774 -15.636 25.269 1.00 0.00 O ATOM 38 CG GLU A 5 21.604 -16.952 27.257 1.00 0.00 C ATOM 39 CD GLU A 5 21.641 -17.070 28.772 1.00 0.00 C ATOM 40 OE1 GLU A 5 20.899 -16.330 29.457 1.00 0.00 O ATOM 41 OE2 GLU A 5 22.419 -17.909 29.279 1.00 0.00 O ATOM 42 N ASP A 6 16.721 -16.161 26.857 1.00 0.00 N ATOM 43 CA ASP A 6 15.629 -15.196 26.948 1.00 0.00 C ATOM 44 C ASP A 6 16.107 -13.791 26.591 1.00 0.00 C ATOM 45 CB ASP A 6 15.022 -15.204 28.353 1.00 0.00 C ATOM 46 O ASP A 6 17.144 -13.339 27.079 1.00 0.00 O ATOM 47 CG ASP A 6 14.317 -16.507 28.687 1.00 0.00 C ATOM 48 OD1 ASP A 6 14.123 -16.805 29.885 1.00 0.00 O ATOM 49 OD2 ASP A 6 13.956 -17.243 27.744 1.00 0.00 O ATOM 50 N GLY A 7 16.251 -13.433 25.339 1.00 0.00 N ATOM 51 CA GLY A 7 16.311 -11.996 25.123 1.00 0.00 C ATOM 52 C GLY A 7 15.833 -11.192 26.317 1.00 0.00 C ATOM 53 O GLY A 7 15.023 -11.674 27.112 1.00 0.00 O ATOM 54 N VAL A 8 16.762 -10.664 27.143 1.00 0.00 N ATOM 55 CA VAL A 8 16.521 -9.756 28.260 1.00 0.00 C ATOM 56 C VAL A 8 15.307 -8.880 27.960 1.00 0.00 C ATOM 57 CB VAL A 8 17.755 -8.875 28.552 1.00 0.00 C ATOM 58 O VAL A 8 15.173 -8.351 26.854 1.00 0.00 O ATOM 59 CG1 VAL A 8 17.461 -7.891 29.683 1.00 0.00 C ATOM 60 CG2 VAL A 8 18.962 -9.745 28.898 1.00 0.00 C ATOM 61 N CYS A 9 14.157 -9.255 28.398 1.00 0.00 N ATOM 62 CA CYS A 9 13.010 -8.353 28.403 1.00 0.00 C ATOM 63 C CYS A 9 13.310 -7.095 29.209 1.00 0.00 C ATOM 64 CB CYS A 9 11.779 -9.055 28.975 1.00 0.00 C ATOM 65 O CYS A 9 14.058 -7.142 30.187 1.00 0.00 O ATOM 66 SG CYS A 9 11.197 -10.439 27.970 1.00 0.00 S ATOM 67 N ASN A 10 13.304 -5.993 28.589 1.00 0.00 N ATOM 68 CA ASN A 10 13.371 -4.703 29.267 1.00 0.00 C ATOM 69 C ASN A 10 12.018 -3.997 29.264 1.00 0.00 C ATOM 70 CB ASN A 10 14.436 -3.812 28.624 1.00 0.00 C ATOM 71 O ASN A 10 11.047 -4.510 28.706 1.00 0.00 O ATOM 72 CG ASN A 10 14.149 -3.521 27.164 1.00 0.00 C ATOM 73 ND2 ASN A 10 15.189 -3.547 26.338 1.00 0.00 N ATOM 74 OD1 ASN A 10 13.003 -3.275 26.781 1.00 0.00 O ATOM 75 N SER A 11 11.830 -2.986 30.142 1.00 0.00 N ATOM 76 CA SER A 11 10.597 -2.233 30.343 1.00 0.00 C ATOM 77 C SER A 11 10.027 -1.741 29.017 1.00 0.00 C ATOM 78 CB SER A 11 10.840 -1.044 31.274 1.00 0.00 C ATOM 79 O SER A 11 8.847 -1.392 28.933 1.00 0.00 O ATOM 80 OG SER A 11 11.841 -0.190 30.748 1.00 0.00 O ATOM 81 N ASN A 12 10.789 -1.874 27.933 1.00 0.00 N ATOM 82 CA ASN A 12 10.334 -1.422 26.622 1.00 0.00 C ATOM 83 C ASN A 12 9.775 -2.576 25.795 1.00 0.00 C ATOM 84 CB ASN A 12 11.472 -0.730 25.868 1.00 0.00 C ATOM 85 O ASN A 12 9.262 -2.365 24.694 1.00 0.00 O ATOM 86 CG ASN A 12 11.875 0.587 26.501 1.00 0.00 C ATOM 87 ND2 ASN A 12 13.170 0.882 26.482 1.00 0.00 N ATOM 88 OD1 ASN A 12 11.031 1.333 27.004 1.00 0.00 O ATOM 89 N ALA A 13 10.045 -3.775 26.303 1.00 0.00 N ATOM 90 CA ALA A 13 9.523 -4.930 25.578 1.00 0.00 C ATOM 91 C ALA A 13 8.001 -4.994 25.671 1.00 0.00 C ATOM 92 CB ALA A 13 10.140 -6.219 26.115 1.00 0.00 C ATOM 93 O ALA A 13 7.423 -4.684 26.715 1.00 0.00 O ATOM 94 N PRO A 14 7.310 -5.193 24.591 1.00 0.00 N ATOM 95 CA PRO A 14 5.846 -5.238 24.577 1.00 0.00 C ATOM 96 C PRO A 14 5.280 -6.316 25.499 1.00 0.00 C ATOM 97 CB PRO A 14 5.517 -5.544 23.113 1.00 0.00 C ATOM 98 O PRO A 14 4.127 -6.222 25.929 1.00 0.00 O ATOM 99 CG PRO A 14 6.757 -6.177 22.568 1.00 0.00 C ATOM 100 CD PRO A 14 7.941 -5.617 23.303 1.00 0.00 C ATOM 101 N CYS A 15 6.076 -7.229 25.793 1.00 0.00 N ATOM 102 CA CYS A 15 5.597 -8.339 26.610 1.00 0.00 C ATOM 103 C CYS A 15 6.142 -8.245 28.030 1.00 0.00 C ATOM 104 CB CYS A 15 5.999 -9.676 25.987 1.00 0.00 C ATOM 105 O CYS A 15 6.205 -9.249 28.743 1.00 0.00 O ATOM 106 SG CYS A 15 7.766 -9.813 25.636 1.00 0.00 S ATOM 107 N TYR A 16 6.510 -6.994 28.366 1.00 0.00 N ATOM 108 CA TYR A 16 7.076 -6.735 29.685 1.00 0.00 C ATOM 109 C TYR A 16 5.978 -6.589 30.731 1.00 0.00 C ATOM 110 CB TYR A 16 7.944 -5.473 29.659 1.00 0.00 C ATOM 111 O TYR A 16 5.053 -5.791 30.563 1.00 0.00 O ATOM 112 CG TYR A 16 8.545 -5.122 30.998 1.00 0.00 C ATOM 113 CD1 TYR A 16 8.126 -3.993 31.698 1.00 0.00 C ATOM 114 CD2 TYR A 16 9.534 -5.918 31.566 1.00 0.00 C ATOM 115 CE1 TYR A 16 8.678 -3.665 32.932 1.00 0.00 C ATOM 116 CE2 TYR A 16 10.093 -5.600 32.799 1.00 0.00 C ATOM 117 OH TYR A 16 10.210 -4.153 34.695 1.00 0.00 O ATOM 118 CZ TYR A 16 9.660 -4.473 33.474 1.00 0.00 C ATOM 119 N HIS A 17 5.834 -7.548 31.703 1.00 0.00 N ATOM 120 CA HIS A 17 4.846 -7.504 32.775 1.00 0.00 C ATOM 121 C HIS A 17 5.518 -7.493 34.143 1.00 0.00 C ATOM 122 CB HIS A 17 3.888 -8.692 32.669 1.00 0.00 C ATOM 123 O HIS A 17 6.482 -8.228 34.372 1.00 0.00 O ATOM 124 CG HIS A 17 2.782 -8.661 33.675 1.00 0.00 C ATOM 125 CD2 HIS A 17 2.548 -9.432 34.764 1.00 0.00 C ATOM 126 ND1 HIS A 17 1.748 -7.752 33.617 1.00 0.00 N ATOM 127 CE1 HIS A 17 0.924 -7.965 34.630 1.00 0.00 C ATOM 128 NE2 HIS A 17 1.387 -8.979 35.341 1.00 0.00 N ATOM 129 N CYS A 18 5.067 -6.579 34.995 1.00 0.00 N ATOM 130 CA CYS A 18 5.599 -6.487 36.350 1.00 0.00 C ATOM 131 C CYS A 18 4.501 -6.711 37.383 1.00 0.00 C ATOM 132 CB CYS A 18 6.255 -5.126 36.577 1.00 0.00 C ATOM 133 O CYS A 18 3.325 -6.465 37.109 1.00 0.00 O ATOM 134 SG CYS A 18 7.757 -4.870 35.607 1.00 0.00 S ATOM 135 N ASP A 19 4.791 -7.344 38.476 1.00 0.00 N ATOM 136 CA ASP A 19 3.829 -7.460 39.568 1.00 0.00 C ATOM 137 C ASP A 19 3.430 -6.084 40.096 1.00 0.00 C ATOM 138 CB ASP A 19 4.403 -8.313 40.701 1.00 0.00 C ATOM 139 O ASP A 19 3.960 -5.064 39.651 1.00 0.00 O ATOM 140 CG ASP A 19 5.572 -7.650 41.408 1.00 0.00 C ATOM 141 OD1 ASP A 19 6.325 -8.345 42.124 1.00 0.00 O ATOM 142 OD2 ASP A 19 5.741 -6.422 41.250 1.00 0.00 O ATOM 143 N ALA A 20 2.383 -5.908 40.933 1.00 0.00 N ATOM 144 CA ALA A 20 1.776 -4.676 41.429 1.00 0.00 C ATOM 145 C ALA A 20 2.806 -3.807 42.144 1.00 0.00 C ATOM 146 CB ALA A 20 0.612 -4.995 42.363 1.00 0.00 C ATOM 147 O ALA A 20 2.714 -2.577 42.119 1.00 0.00 O ATOM 148 N ASN A 21 3.841 -4.457 42.638 1.00 0.00 N ATOM 149 CA ASN A 21 4.863 -3.719 43.373 1.00 0.00 C ATOM 150 C ASN A 21 6.048 -3.362 42.480 1.00 0.00 C ATOM 151 CB ASN A 21 5.335 -4.521 44.588 1.00 0.00 C ATOM 152 O ASN A 21 6.980 -2.686 42.919 1.00 0.00 O ATOM 153 CG ASN A 21 4.246 -4.704 45.626 1.00 0.00 C ATOM 154 ND2 ASN A 21 4.183 -5.892 46.216 1.00 0.00 N ATOM 155 OD1 ASN A 21 3.467 -3.786 45.895 1.00 0.00 O ATOM 156 N GLY A 22 5.989 -3.893 41.230 1.00 0.00 N ATOM 157 CA GLY A 22 7.093 -3.614 40.325 1.00 0.00 C ATOM 158 C GLY A 22 8.376 -4.324 40.712 1.00 0.00 C ATOM 159 O GLY A 22 9.456 -3.972 40.234 1.00 0.00 O ATOM 160 N GLU A 23 8.305 -5.221 41.664 1.00 0.00 N ATOM 161 CA GLU A 23 9.501 -5.877 42.183 1.00 0.00 C ATOM 162 C GLU A 23 9.861 -7.105 41.352 1.00 0.00 C ATOM 163 CB GLU A 23 9.306 -6.272 43.649 1.00 0.00 C ATOM 164 O GLU A 23 11.038 -7.361 41.089 1.00 0.00 O ATOM 165 CG GLU A 23 9.200 -5.085 44.596 1.00 0.00 C ATOM 166 CD GLU A 23 9.074 -5.493 46.055 1.00 0.00 C ATOM 167 OE1 GLU A 23 9.075 -6.710 46.348 1.00 0.00 O ATOM 168 OE2 GLU A 23 8.972 -4.587 46.913 1.00 0.00 O ATOM 169 N ASN A 24 8.853 -7.853 40.844 1.00 0.00 N ATOM 170 CA ASN A 24 9.050 -9.077 40.075 1.00 0.00 C ATOM 171 C ASN A 24 8.522 -8.936 38.651 1.00 0.00 C ATOM 172 CB ASN A 24 8.381 -10.263 40.774 1.00 0.00 C ATOM 173 O ASN A 24 7.317 -9.045 38.417 1.00 0.00 O ATOM 174 CG ASN A 24 8.973 -10.546 42.140 1.00 0.00 C ATOM 175 ND2 ASN A 24 8.125 -10.569 43.162 1.00 0.00 N ATOM 176 OD1 ASN A 24 10.184 -10.741 42.277 1.00 0.00 O ATOM 177 N CYS A 25 9.371 -8.554 37.764 1.00 0.00 N ATOM 178 CA CYS A 25 8.978 -8.390 36.369 1.00 0.00 C ATOM 179 C CYS A 25 9.448 -9.572 35.529 1.00 0.00 C ATOM 180 CB CYS A 25 9.548 -7.091 35.800 1.00 0.00 C ATOM 181 O CYS A 25 10.486 -10.171 35.816 1.00 0.00 O ATOM 182 SG CYS A 25 8.933 -5.605 36.623 1.00 0.00 S ATOM 183 N SER A 26 8.561 -10.102 34.701 1.00 0.00 N ATOM 184 CA SER A 26 8.921 -11.145 33.746 1.00 0.00 C ATOM 185 C SER A 26 8.422 -10.808 32.345 1.00 0.00 C ATOM 186 CB SER A 26 8.353 -12.495 34.187 1.00 0.00 C ATOM 187 O SER A 26 7.563 -9.940 32.178 1.00 0.00 O ATOM 188 OG SER A 26 6.936 -12.470 34.186 1.00 0.00 O ATOM 189 N CYS A 27 9.208 -11.265 31.277 1.00 0.00 N ATOM 190 CA CYS A 27 8.779 -11.211 29.884 1.00 0.00 C ATOM 191 C CYS A 27 7.948 -12.436 29.521 1.00 0.00 C ATOM 192 CB CYS A 27 9.988 -11.110 28.954 1.00 0.00 C ATOM 193 O CYS A 27 8.470 -13.551 29.464 1.00 0.00 O ATOM 194 SG CYS A 27 10.970 -9.614 29.197 1.00 0.00 S ATOM 195 N ASN A 28 6.768 -12.360 29.728 1.00 0.00 N ATOM 196 CA ASN A 28 5.905 -13.476 29.355 1.00 0.00 C ATOM 197 C ASN A 28 5.123 -13.178 28.079 1.00 0.00 C ATOM 198 CB ASN A 28 4.946 -13.817 30.498 1.00 0.00 C ATOM 199 O ASN A 28 4.074 -12.532 28.125 1.00 0.00 O ATOM 200 CG ASN A 28 4.239 -15.142 30.291 1.00 0.00 C ATOM 201 ND2 ASN A 28 3.472 -15.568 31.288 1.00 0.00 N ATOM 202 OD1 ASN A 28 4.381 -15.779 29.243 1.00 0.00 O ATOM 203 N CYS A 29 5.741 -13.488 26.787 1.00 0.00 N ATOM 204 CA CYS A 29 5.086 -13.282 25.500 1.00 0.00 C ATOM 205 C CYS A 29 3.880 -14.201 25.348 1.00 0.00 C ATOM 206 CB CYS A 29 6.070 -13.522 24.355 1.00 0.00 C ATOM 207 O CYS A 29 3.011 -13.958 24.510 1.00 0.00 O ATOM 208 SG CYS A 29 7.446 -12.353 24.319 1.00 0.00 S ATOM 209 N GLU A 30 3.849 -15.077 26.140 1.00 0.00 N ATOM 210 CA GLU A 30 2.725 -16.005 26.063 1.00 0.00 C ATOM 211 C GLU A 30 1.452 -15.379 26.627 1.00 0.00 C ATOM 212 CB GLU A 30 3.047 -17.303 26.808 1.00 0.00 C ATOM 213 O GLU A 30 0.344 -15.770 26.255 1.00 0.00 O ATOM 214 CG GLU A 30 4.161 -18.119 26.169 1.00 0.00 C ATOM 215 CD GLU A 30 4.469 -19.405 26.919 1.00 0.00 C ATOM 216 OE1 GLU A 30 3.822 -19.672 27.957 1.00 0.00 O ATOM 217 OE2 GLU A 30 5.366 -20.150 26.466 1.00 0.00 O ATOM 218 N LEU A 31 1.743 -14.305 27.387 1.00 0.00 N ATOM 219 CA LEU A 31 0.622 -13.672 28.074 1.00 0.00 C ATOM 220 C LEU A 31 0.044 -12.536 27.237 1.00 0.00 C ATOM 221 CB LEU A 31 1.061 -13.142 29.441 1.00 0.00 C ATOM 222 O LEU A 31 -0.996 -11.971 27.584 1.00 0.00 O ATOM 223 CG LEU A 31 1.437 -14.194 30.487 1.00 0.00 C ATOM 224 CD1 LEU A 31 1.920 -13.520 31.766 1.00 0.00 C ATOM 225 CD2 LEU A 31 0.252 -15.110 30.774 1.00 0.00 C ATOM 226 N PHE A 32 0.769 -12.166 26.008 1.00 0.00 N ATOM 227 CA PHE A 32 0.157 -11.063 25.278 1.00 0.00 C ATOM 228 C PHE A 32 -1.020 -11.553 24.443 1.00 0.00 C ATOM 229 CB PHE A 32 1.188 -10.374 24.378 1.00 0.00 C ATOM 230 O PHE A 32 -0.898 -12.531 23.702 1.00 0.00 O ATOM 231 CG PHE A 32 2.115 -9.447 25.117 1.00 0.00 C ATOM 232 CD1 PHE A 32 3.383 -9.869 25.499 1.00 0.00 C ATOM 233 CD2 PHE A 32 1.719 -8.153 25.429 1.00 0.00 C ATOM 234 CE1 PHE A 32 4.243 -9.014 26.183 1.00 0.00 C ATOM 235 CE2 PHE A 32 2.574 -7.293 26.112 1.00 0.00 C ATOM 236 CZ PHE A 32 3.835 -7.725 26.489 1.00 0.00 C ATOM 237 N ASP A 33 -2.070 -11.361 25.097 1.00 0.00 N ATOM 238 CA ASP A 33 -3.364 -11.602 24.466 1.00 0.00 C ATOM 239 C ASP A 33 -3.423 -10.975 23.075 1.00 0.00 C ATOM 240 CB ASP A 33 -4.496 -11.055 25.339 1.00 0.00 C ATOM 241 O ASP A 33 -3.225 -9.767 22.924 1.00 0.00 O ATOM 242 CG ASP A 33 -5.861 -11.590 24.943 1.00 0.00 C ATOM 243 OD1 ASP A 33 -6.769 -11.638 25.800 1.00 0.00 O ATOM 244 OD2 ASP A 33 -6.029 -11.969 23.764 1.00 0.00 O ATOM 245 N CYS A 34 -3.021 -11.756 22.063 1.00 0.00 N ATOM 246 CA CYS A 34 -3.371 -11.337 20.711 1.00 0.00 C ATOM 247 C CYS A 34 -4.691 -10.576 20.700 1.00 0.00 C ATOM 248 CB CYS A 34 -3.461 -12.547 19.781 1.00 0.00 C ATOM 249 O CYS A 34 -4.986 -9.851 19.748 1.00 0.00 O ATOM 250 SG CYS A 34 -1.909 -13.455 19.615 1.00 0.00 S ATOM 251 N GLU A 35 -5.284 -10.672 21.987 1.00 0.00 N ATOM 252 CA GLU A 35 -6.617 -10.086 22.085 1.00 0.00 C ATOM 253 C GLU A 35 -6.556 -8.667 22.644 1.00 0.00 C ATOM 254 CB GLU A 35 -7.525 -10.956 22.958 1.00 0.00 C ATOM 255 O GLU A 35 -7.592 -8.032 22.853 1.00 0.00 O ATOM 256 CG GLU A 35 -7.790 -12.339 22.381 1.00 0.00 C ATOM 257 CD GLU A 35 -8.779 -13.152 23.202 1.00 0.00 C ATOM 258 OE1 GLU A 35 -9.290 -12.636 24.222 1.00 0.00 O ATOM 259 OE2 GLU A 35 -9.046 -14.314 22.821 1.00 0.00 O ATOM 260 N ALA A 36 -5.315 -8.202 22.860 1.00 0.00 N ATOM 261 CA ALA A 36 -5.282 -6.884 23.489 1.00 0.00 C ATOM 262 C ALA A 36 -5.714 -5.797 22.509 1.00 0.00 C ATOM 263 CB ALA A 36 -3.884 -6.586 24.027 1.00 0.00 C ATOM 264 O ALA A 36 -5.299 -5.799 21.348 1.00 0.00 O ATOM 265 N LYS A 37 -6.942 -5.271 22.819 1.00 0.00 N ATOM 266 CA LYS A 37 -7.519 -4.143 22.094 1.00 0.00 C ATOM 267 C LYS A 37 -6.974 -2.817 22.617 1.00 0.00 C ATOM 268 CB LYS A 37 -9.045 -4.160 22.200 1.00 0.00 C ATOM 269 O LYS A 37 -6.897 -2.606 23.829 1.00 0.00 O ATOM 270 CG LYS A 37 -9.701 -5.341 21.499 1.00 0.00 C ATOM 271 CD LYS A 37 -11.220 -5.239 21.536 1.00 0.00 C ATOM 272 CE LYS A 37 -11.877 -6.385 20.778 1.00 0.00 C ATOM 273 NZ LYS A 37 -13.353 -6.194 20.656 1.00 0.00 N ATOM 274 N LYS A 38 -6.207 -2.111 21.604 1.00 0.00 N ATOM 275 CA LYS A 38 -5.876 -0.745 21.998 1.00 0.00 C ATOM 276 C LYS A 38 -7.131 0.118 22.100 1.00 0.00 C ATOM 277 CB LYS A 38 -4.892 -0.123 21.007 1.00 0.00 C ATOM 278 O LYS A 38 -8.188 -0.253 21.585 1.00 0.00 O ATOM 279 CG LYS A 38 -3.518 -0.776 21.006 1.00 0.00 C ATOM 280 CD LYS A 38 -2.564 -0.072 20.049 1.00 0.00 C ATOM 281 CE LYS A 38 -1.196 -0.740 20.029 1.00 0.00 C ATOM 282 NZ LYS A 38 -0.234 -0.007 19.153 1.00 0.00 N ATOM 283 N PRO A 39 -7.175 1.097 22.994 1.00 0.00 N ATOM 284 CA PRO A 39 -8.319 2.000 23.133 1.00 0.00 C ATOM 285 C PRO A 39 -8.863 2.474 21.787 1.00 0.00 C ATOM 286 CB PRO A 39 -7.748 3.173 23.934 1.00 0.00 C ATOM 287 O PRO A 39 -10.057 2.762 21.666 1.00 0.00 O ATOM 288 CG PRO A 39 -6.594 2.594 24.688 1.00 0.00 C ATOM 289 CD PRO A 39 -6.004 1.478 23.874 1.00 0.00 C ATOM 290 N ASP A 40 -8.068 2.468 20.731 1.00 0.00 N ATOM 291 CA ASP A 40 -8.452 2.969 19.415 1.00 0.00 C ATOM 292 C ASP A 40 -9.034 1.852 18.551 1.00 0.00 C ATOM 293 CB ASP A 40 -7.252 3.607 18.712 1.00 0.00 C ATOM 294 O ASP A 40 -9.337 2.064 17.375 1.00 0.00 O ATOM 295 CG ASP A 40 -6.113 2.630 18.480 1.00 0.00 C ATOM 296 OD1 ASP A 40 -5.040 3.049 17.994 1.00 0.00 O ATOM 297 OD2 ASP A 40 -6.290 1.431 18.784 1.00 0.00 O ATOM 298 N GLY A 41 -9.199 0.638 19.013 1.00 0.00 N ATOM 299 CA GLY A 41 -9.761 -0.484 18.279 1.00 0.00 C ATOM 300 C GLY A 41 -8.723 -1.268 17.500 1.00 0.00 C ATOM 301 O GLY A 41 -9.019 -2.338 16.963 1.00 0.00 O ATOM 302 N SER A 42 -7.510 -0.651 17.403 1.00 0.00 N ATOM 303 CA SER A 42 -6.433 -1.355 16.714 1.00 0.00 C ATOM 304 C SER A 42 -5.824 -2.436 17.601 1.00 0.00 C ATOM 305 CB SER A 42 -5.346 -0.373 16.274 1.00 0.00 C ATOM 306 O SER A 42 -6.031 -2.440 18.816 1.00 0.00 O ATOM 307 OG SER A 42 -4.758 0.262 17.396 1.00 0.00 O ATOM 308 N TYR A 43 -5.412 -3.575 16.938 1.00 0.00 N ATOM 309 CA TYR A 43 -4.705 -4.628 17.660 1.00 0.00 C ATOM 310 C TYR A 43 -3.244 -4.254 17.877 1.00 0.00 C ATOM 311 CB TYR A 43 -4.798 -5.955 16.901 1.00 0.00 C ATOM 312 O TYR A 43 -2.651 -3.542 17.063 1.00 0.00 O ATOM 313 CG TYR A 43 -6.184 -6.551 16.887 1.00 0.00 C ATOM 314 CD1 TYR A 43 -7.022 -6.388 15.786 1.00 0.00 C ATOM 315 CD2 TYR A 43 -6.659 -7.277 17.974 1.00 0.00 C ATOM 316 CE1 TYR A 43 -8.302 -6.934 15.769 1.00 0.00 C ATOM 317 CE2 TYR A 43 -7.937 -7.827 17.968 1.00 0.00 C ATOM 318 OH TYR A 43 -10.015 -8.194 16.852 1.00 0.00 O ATOM 319 CZ TYR A 43 -8.749 -7.651 16.863 1.00 0.00 C ATOM 320 N ALA A 44 -3.024 -4.415 19.155 1.00 0.00 N ATOM 321 CA ALA A 44 -1.659 -4.137 19.595 1.00 0.00 C ATOM 322 C ALA A 44 -0.642 -4.865 18.721 1.00 0.00 C ATOM 323 CB ALA A 44 -1.480 -4.536 21.058 1.00 0.00 C ATOM 324 O ALA A 44 0.477 -4.383 18.527 1.00 0.00 O ATOM 325 N HIS A 45 -1.081 -5.938 17.989 1.00 0.00 N ATOM 326 CA HIS A 45 -0.065 -6.665 17.236 1.00 0.00 C ATOM 327 C HIS A 45 -0.455 -6.795 15.768 1.00 0.00 C ATOM 328 CB HIS A 45 0.163 -8.051 17.843 1.00 0.00 C ATOM 329 O HIS A 45 -1.558 -7.246 15.452 1.00 0.00 O ATOM 330 CG HIS A 45 1.501 -8.634 17.520 1.00 0.00 C ATOM 331 CD2 HIS A 45 2.577 -8.880 18.304 1.00 0.00 C ATOM 332 ND1 HIS A 45 1.850 -9.037 16.249 1.00 0.00 N ATOM 333 CE1 HIS A 45 3.086 -9.508 16.266 1.00 0.00 C ATOM 334 NE2 HIS A 45 3.550 -9.423 17.502 1.00 0.00 N ATOM 335 N PRO A 46 0.267 -6.191 14.776 1.00 0.00 N ATOM 336 CA PRO A 46 0.007 -6.193 13.334 1.00 0.00 C ATOM 337 C PRO A 46 -0.224 -7.596 12.778 1.00 0.00 C ATOM 338 CB PRO A 46 1.278 -5.574 12.747 1.00 0.00 C ATOM 339 O PRO A 46 -0.835 -7.750 11.717 1.00 0.00 O ATOM 340 CG PRO A 46 2.320 -5.770 13.800 1.00 0.00 C ATOM 341 CD PRO A 46 1.648 -5.768 15.143 1.00 0.00 C ATOM 342 N CYS A 47 0.238 -8.592 13.354 1.00 0.00 N ATOM 343 CA CYS A 47 0.115 -9.950 12.835 1.00 0.00 C ATOM 344 C CYS A 47 -1.253 -10.537 13.163 1.00 0.00 C ATOM 345 CB CYS A 47 1.214 -10.844 13.408 1.00 0.00 C ATOM 346 O CYS A 47 -1.515 -11.707 12.880 1.00 0.00 O ATOM 347 SG CYS A 47 1.222 -10.923 15.212 1.00 0.00 S ATOM 348 N ARG A 48 -2.155 -9.724 13.452 1.00 0.00 N ATOM 349 CA ARG A 48 -3.422 -10.192 14.005 1.00 0.00 C ATOM 350 C ARG A 48 -4.542 -10.086 12.974 1.00 0.00 C ATOM 351 CB ARG A 48 -3.788 -9.396 15.260 1.00 0.00 C ATOM 352 O ARG A 48 -4.649 -9.082 12.268 1.00 0.00 O ATOM 353 CG ARG A 48 -5.032 -9.905 15.970 1.00 0.00 C ATOM 354 CD ARG A 48 -5.909 -8.761 16.460 1.00 0.00 C ATOM 355 NE ARG A 48 -6.344 -7.906 15.359 1.00 0.00 N ATOM 356 NH1 ARG A 48 -6.885 -6.103 16.700 1.00 0.00 N ATOM 357 NH2 ARG A 48 -7.167 -5.974 14.429 1.00 0.00 N ATOM 358 CZ ARG A 48 -6.798 -6.663 15.499 1.00 0.00 C ATOM 359 N ARG A 49 -5.146 -11.174 12.527 1.00 0.00 N ATOM 360 CA ARG A 49 -6.391 -11.158 11.765 1.00 0.00 C ATOM 361 C ARG A 49 -7.546 -11.713 12.593 1.00 0.00 C ATOM 362 CB ARG A 49 -6.241 -11.962 10.472 1.00 0.00 C ATOM 363 O ARG A 49 -7.402 -12.739 13.261 1.00 0.00 O ATOM 364 CG ARG A 49 -5.303 -11.327 9.458 1.00 0.00 C ATOM 365 CD ARG A 49 -5.887 -10.048 8.873 1.00 0.00 C ATOM 366 NE ARG A 49 -5.349 -9.769 7.544 1.00 0.00 N ATOM 367 NH1 ARG A 49 -6.902 -8.137 7.033 1.00 0.00 N ATOM 368 NH2 ARG A 49 -5.276 -8.694 5.516 1.00 0.00 N ATOM 369 CZ ARG A 49 -5.843 -8.867 6.701 1.00 0.00 C ATOM 370 N CYS A 50 -8.427 -10.800 12.832 1.00 0.00 N ATOM 371 CA CYS A 50 -9.591 -11.226 13.601 1.00 0.00 C ATOM 372 C CYS A 50 -10.795 -11.442 12.692 1.00 0.00 C ATOM 373 CB CYS A 50 -9.931 -10.193 14.675 1.00 0.00 C ATOM 374 O CYS A 50 -11.034 -10.657 11.773 1.00 0.00 O ATOM 375 SG CYS A 50 -8.684 -10.057 15.975 1.00 0.00 S ATOM 376 N ASP A 51 -11.409 -12.618 12.691 1.00 0.00 N ATOM 377 CA ASP A 51 -12.641 -12.851 11.943 1.00 0.00 C ATOM 378 C ASP A 51 -13.818 -12.115 12.580 1.00 0.00 C ATOM 379 CB ASP A 51 -12.942 -14.349 11.858 1.00 0.00 C ATOM 380 O ASP A 51 -13.640 -11.361 13.539 1.00 0.00 O ATOM 381 CG ASP A 51 -13.232 -14.974 13.211 1.00 0.00 C ATOM 382 OD1 ASP A 51 -13.125 -16.212 13.347 1.00 0.00 O ATOM 383 OD2 ASP A 51 -13.573 -14.221 14.150 1.00 0.00 O ATOM 384 N ALA A 52 -15.076 -12.051 11.991 1.00 0.00 N ATOM 385 CA ALA A 52 -16.275 -11.314 12.381 1.00 0.00 C ATOM 386 C ALA A 52 -16.730 -11.710 13.783 1.00 0.00 C ATOM 387 CB ALA A 52 -17.397 -11.550 11.374 1.00 0.00 C ATOM 388 O ALA A 52 -17.439 -10.952 14.450 1.00 0.00 O ATOM 389 N ASN A 53 -16.263 -12.790 14.290 1.00 0.00 N ATOM 390 CA ASN A 53 -16.638 -13.257 15.620 1.00 0.00 C ATOM 391 C ASN A 53 -15.557 -12.943 16.650 1.00 0.00 C ATOM 392 CB ASN A 53 -16.930 -14.759 15.599 1.00 0.00 C ATOM 393 O ASN A 53 -15.602 -13.442 17.776 1.00 0.00 O ATOM 394 CG ASN A 53 -18.169 -15.101 14.795 1.00 0.00 C ATOM 395 ND2 ASN A 53 -18.098 -16.183 14.029 1.00 0.00 N ATOM 396 OD1 ASN A 53 -19.181 -14.399 14.862 1.00 0.00 O ATOM 397 N ASN A 54 -14.551 -12.153 16.191 1.00 0.00 N ATOM 398 CA ASN A 54 -13.470 -11.666 17.041 1.00 0.00 C ATOM 399 C ASN A 54 -12.543 -12.798 17.474 1.00 0.00 C ATOM 400 CB ASN A 54 -14.034 -10.943 18.266 1.00 0.00 C ATOM 401 O ASN A 54 -11.968 -12.753 18.563 1.00 0.00 O ATOM 402 CG ASN A 54 -14.752 -9.657 17.906 1.00 0.00 C ATOM 403 ND2 ASN A 54 -15.894 -9.418 18.540 1.00 0.00 N ATOM 404 OD1 ASN A 54 -14.285 -8.885 17.065 1.00 0.00 O ATOM 405 N ILE A 55 -12.428 -13.839 16.751 1.00 0.00 N ATOM 406 CA ILE A 55 -11.423 -14.875 16.963 1.00 0.00 C ATOM 407 C ILE A 55 -10.158 -14.536 16.179 1.00 0.00 C ATOM 408 CB ILE A 55 -11.952 -16.268 16.552 1.00 0.00 C ATOM 409 O ILE A 55 -10.162 -14.552 14.946 1.00 0.00 O ATOM 410 CG1 ILE A 55 -13.233 -16.602 17.325 1.00 0.00 C ATOM 411 CG2 ILE A 55 -10.881 -17.340 16.777 1.00 0.00 C ATOM 412 CD1 ILE A 55 -13.942 -17.857 16.834 1.00 0.00 C ATOM 413 N CYS A 56 -9.197 -14.050 16.887 1.00 0.00 N ATOM 414 CA CYS A 56 -7.960 -13.587 16.266 1.00 0.00 C ATOM 415 C CYS A 56 -6.914 -14.694 16.244 1.00 0.00 C ATOM 416 CB CYS A 56 -7.411 -12.369 17.009 1.00 0.00 C ATOM 417 O CYS A 56 -6.807 -15.473 17.192 1.00 0.00 O ATOM 418 SG CYS A 56 -8.495 -10.925 16.941 1.00 0.00 S ATOM 419 N LYS A 57 -6.417 -14.976 15.112 1.00 0.00 N ATOM 420 CA LYS A 57 -5.263 -15.861 14.977 1.00 0.00 C ATOM 421 C LYS A 57 -4.007 -15.075 14.612 1.00 0.00 C ATOM 422 CB LYS A 57 -5.532 -16.937 13.924 1.00 0.00 C ATOM 423 O LYS A 57 -4.077 -14.092 13.873 1.00 0.00 O ATOM 424 CG LYS A 57 -6.672 -17.880 14.280 1.00 0.00 C ATOM 425 CD LYS A 57 -6.811 -19.000 13.257 1.00 0.00 C ATOM 426 CE LYS A 57 -7.903 -19.986 13.651 1.00 0.00 C ATOM 427 NZ LYS A 57 -7.947 -21.161 12.730 1.00 0.00 N ATOM 428 N CYS A 58 -2.976 -15.105 15.608 1.00 0.00 N ATOM 429 CA CYS A 58 -1.644 -14.583 15.328 1.00 0.00 C ATOM 430 C CYS A 58 -0.938 -15.425 14.272 1.00 0.00 C ATOM 431 CB CYS A 58 -0.804 -14.543 16.605 1.00 0.00 C ATOM 432 O CYS A 58 -0.662 -16.605 14.495 1.00 0.00 O ATOM 433 SG CYS A 58 -1.471 -13.452 17.881 1.00 0.00 S ATOM 434 N SER A 59 -1.100 -15.266 13.105 1.00 0.00 N ATOM 435 CA SER A 59 -0.317 -16.194 12.296 1.00 0.00 C ATOM 436 C SER A 59 0.363 -15.475 11.135 1.00 0.00 C ATOM 437 CB SER A 59 -1.204 -17.319 11.760 1.00 0.00 C ATOM 438 O SER A 59 -0.281 -15.151 10.135 1.00 0.00 O ATOM 439 OG SER A 59 -0.425 -18.302 11.100 1.00 0.00 O ATOM 440 N CYS A 60 1.699 -14.861 11.329 1.00 0.00 N ATOM 441 CA CYS A 60 2.405 -14.577 10.084 1.00 0.00 C ATOM 442 C CYS A 60 2.585 -15.845 9.258 1.00 0.00 C ATOM 443 CB CYS A 60 3.768 -13.947 10.372 1.00 0.00 C ATOM 444 O CYS A 60 2.717 -15.781 8.035 1.00 0.00 O ATOM 445 SG CYS A 60 4.863 -14.997 11.352 1.00 0.00 S ATOM 446 N THR A 61 2.370 -16.747 10.083 1.00 0.00 N ATOM 447 CA THR A 61 2.549 -18.025 9.403 1.00 0.00 C ATOM 448 C THR A 61 1.237 -18.493 8.779 1.00 0.00 C ATOM 449 CB THR A 61 3.075 -19.103 10.369 1.00 0.00 C ATOM 450 O THR A 61 1.241 -19.301 7.848 1.00 0.00 O ATOM 451 CG2 THR A 61 4.474 -18.758 10.869 1.00 0.00 C ATOM 452 OG1 THR A 61 2.190 -19.204 11.491 1.00 0.00 O ATOM 453 N ALA A 62 0.127 -17.759 9.279 1.00 0.00 N ATOM 454 CA ALA A 62 -1.157 -18.259 8.792 1.00 0.00 C ATOM 455 C ALA A 62 -1.490 -17.673 7.423 1.00 0.00 C ATOM 456 CB ALA A 62 -2.266 -17.936 9.790 1.00 0.00 C ATOM 457 O ALA A 62 -2.183 -18.305 6.623 1.00 0.00 O ATOM 458 N ILE A 63 -0.953 -16.508 7.207 1.00 0.00 N ATOM 459 CA ILE A 63 -1.310 -15.966 5.900 1.00 0.00 C ATOM 460 C ILE A 63 -0.123 -16.091 4.948 1.00 0.00 C ATOM 461 CB ILE A 63 -1.761 -14.492 6.004 1.00 0.00 C ATOM 462 O ILE A 63 0.973 -15.611 5.246 1.00 0.00 O ATOM 463 CG1 ILE A 63 -2.978 -14.369 6.929 1.00 0.00 C ATOM 464 CG2 ILE A 63 -2.068 -13.922 4.616 1.00 0.00 C ATOM 465 CD1 ILE A 63 -3.430 -12.936 7.171 1.00 0.00 C ATOM 466 N PRO A 64 -0.261 -17.160 4.081 1.00 0.00 N ATOM 467 CA PRO A 64 0.812 -17.254 3.088 1.00 0.00 C ATOM 468 C PRO A 64 1.182 -15.899 2.489 1.00 0.00 C ATOM 469 CB PRO A 64 0.224 -18.181 2.021 1.00 0.00 C ATOM 470 O PRO A 64 0.304 -15.069 2.242 1.00 0.00 O ATOM 471 CG PRO A 64 -1.257 -18.050 2.175 1.00 0.00 C ATOM 472 CD PRO A 64 -1.560 -17.707 3.605 1.00 0.00 C ATOM 473 N CYS A 65 2.470 -15.492 2.721 1.00 0.00 N ATOM 474 CA CYS A 65 2.970 -14.283 2.076 1.00 0.00 C ATOM 475 C CYS A 65 2.884 -14.399 0.559 1.00 0.00 C ATOM 476 CB CYS A 65 4.415 -14.011 2.494 1.00 0.00 C ATOM 477 O CYS A 65 3.627 -15.170 -0.052 1.00 0.00 O ATOM 478 SG CYS A 65 4.983 -12.341 2.107 1.00 0.00 S ATOM 479 N ASN A 66 1.810 -14.008 0.034 1.00 0.00 N ATOM 480 CA ASN A 66 1.657 -13.952 -1.416 1.00 0.00 C ATOM 481 C ASN A 66 1.636 -12.512 -1.922 1.00 0.00 C ATOM 482 CB ASN A 66 0.388 -14.686 -1.851 1.00 0.00 C ATOM 483 O ASN A 66 1.843 -11.575 -1.149 1.00 0.00 O ATOM 484 CG ASN A 66 -0.864 -14.121 -1.209 1.00 0.00 C ATOM 485 ND2 ASN A 66 -1.787 -14.999 -0.835 1.00 0.00 N ATOM 486 OD1 ASN A 66 -0.999 -12.905 -1.050 1.00 0.00 O ATOM 487 N GLU A 67 1.630 -12.346 -3.214 1.00 0.00 N ATOM 488 CA GLU A 67 1.700 -11.038 -3.857 1.00 0.00 C ATOM 489 C GLU A 67 0.657 -10.083 -3.284 1.00 0.00 C ATOM 490 CB GLU A 67 1.515 -11.172 -5.371 1.00 0.00 C ATOM 491 O GLU A 67 0.820 -8.863 -3.353 1.00 0.00 O ATOM 492 CG GLU A 67 0.220 -11.863 -5.773 1.00 0.00 C ATOM 493 CD GLU A 67 0.104 -12.095 -7.271 1.00 0.00 C ATOM 494 OE1 GLU A 67 -1.026 -12.040 -7.808 1.00 0.00 O ATOM 495 OE2 GLU A 67 1.151 -12.333 -7.914 1.00 0.00 O ATOM 496 N ASP A 68 -0.317 -10.492 -2.553 1.00 0.00 N ATOM 497 CA ASP A 68 -1.388 -9.666 -2.004 1.00 0.00 C ATOM 498 C ASP A 68 -1.103 -9.292 -0.551 1.00 0.00 C ATOM 499 CB ASP A 68 -2.731 -10.391 -2.108 1.00 0.00 C ATOM 500 O ASP A 68 -1.847 -8.517 0.053 1.00 0.00 O ATOM 501 CG ASP A 68 -3.195 -10.578 -3.541 1.00 0.00 C ATOM 502 OD1 ASP A 68 -3.828 -11.611 -3.848 1.00 0.00 O ATOM 503 OD2 ASP A 68 -2.923 -9.685 -4.373 1.00 0.00 O ATOM 504 N HIS A 69 -0.167 -9.956 0.090 1.00 0.00 N ATOM 505 CA HIS A 69 0.211 -9.683 1.472 1.00 0.00 C ATOM 506 C HIS A 69 1.044 -8.410 1.574 1.00 0.00 C ATOM 507 CB HIS A 69 0.985 -10.865 2.059 1.00 0.00 C ATOM 508 O HIS A 69 2.031 -8.249 0.852 1.00 0.00 O ATOM 509 CG HIS A 69 1.021 -10.875 3.555 1.00 0.00 C ATOM 510 CD2 HIS A 69 0.448 -11.711 4.452 1.00 0.00 C ATOM 511 ND1 HIS A 69 1.712 -9.936 4.288 1.00 0.00 N ATOM 512 CE1 HIS A 69 1.562 -10.195 5.577 1.00 0.00 C ATOM 513 NE2 HIS A 69 0.800 -11.267 5.703 1.00 0.00 N ATOM 514 N PRO A 70 0.701 -7.489 2.427 1.00 0.00 N ATOM 515 CA PRO A 70 1.384 -6.197 2.516 1.00 0.00 C ATOM 516 C PRO A 70 2.882 -6.337 2.776 1.00 0.00 C ATOM 517 CB PRO A 70 0.687 -5.510 3.693 1.00 0.00 C ATOM 518 O PRO A 70 3.663 -5.461 2.397 1.00 0.00 O ATOM 519 CG PRO A 70 -0.046 -6.606 4.396 1.00 0.00 C ATOM 520 CD PRO A 70 -0.242 -7.742 3.433 1.00 0.00 C ATOM 521 N CYS A 71 3.295 -7.400 3.302 1.00 0.00 N ATOM 522 CA CYS A 71 4.698 -7.619 3.633 1.00 0.00 C ATOM 523 C CYS A 71 5.402 -8.407 2.534 1.00 0.00 C ATOM 524 CB CYS A 71 4.825 -8.359 4.965 1.00 0.00 C ATOM 525 O CYS A 71 6.576 -8.754 2.669 1.00 0.00 O ATOM 526 SG CYS A 71 4.149 -7.448 6.371 1.00 0.00 S ATOM 527 N HIS A 72 4.559 -8.757 1.576 1.00 0.00 N ATOM 528 CA HIS A 72 5.119 -9.541 0.482 1.00 0.00 C ATOM 529 C HIS A 72 6.010 -8.684 -0.411 1.00 0.00 C ATOM 530 CB HIS A 72 4.003 -10.179 -0.347 1.00 0.00 C ATOM 531 O HIS A 72 5.596 -7.614 -0.864 1.00 0.00 O ATOM 532 CG HIS A 72 4.498 -10.942 -1.534 1.00 0.00 C ATOM 533 CD2 HIS A 72 4.508 -10.627 -2.851 1.00 0.00 C ATOM 534 ND1 HIS A 72 5.064 -12.194 -1.431 1.00 0.00 N ATOM 535 CE1 HIS A 72 5.402 -12.618 -2.638 1.00 0.00 C ATOM 536 NE2 HIS A 72 5.076 -11.686 -3.517 1.00 0.00 N ATOM 537 N HIS A 73 7.276 -9.193 -0.608 1.00 0.00 N ATOM 538 CA HIS A 73 8.219 -8.528 -1.500 1.00 0.00 C ATOM 539 C HIS A 73 8.888 -9.527 -2.439 1.00 0.00 C ATOM 540 CB HIS A 73 9.278 -7.774 -0.695 1.00 0.00 C ATOM 541 O HIS A 73 9.246 -10.632 -2.024 1.00 0.00 O ATOM 542 CG HIS A 73 8.715 -6.693 0.172 1.00 0.00 C ATOM 543 CD2 HIS A 73 8.550 -6.625 1.514 1.00 0.00 C ATOM 544 ND1 HIS A 73 8.240 -5.504 -0.336 1.00 0.00 N ATOM 545 CE1 HIS A 73 7.806 -4.749 0.660 1.00 0.00 C ATOM 546 NE2 HIS A 73 7.983 -5.406 1.793 1.00 0.00 N ATOM 547 N CYS A 74 8.907 -9.137 -3.729 1.00 0.00 N ATOM 548 CA CYS A 74 9.582 -9.976 -4.713 1.00 0.00 C ATOM 549 C CYS A 74 10.677 -9.199 -5.433 1.00 0.00 C ATOM 550 CB CYS A 74 8.580 -10.523 -5.729 1.00 0.00 C ATOM 551 O CYS A 74 10.529 -8.003 -5.689 1.00 0.00 O ATOM 552 SG CYS A 74 7.391 -11.686 -5.025 1.00 0.00 S ATOM 553 N HIS A 75 11.715 -9.738 -5.575 1.00 0.00 N ATOM 554 CA HIS A 75 12.772 -9.115 -6.364 1.00 0.00 C ATOM 555 C HIS A 75 13.308 -10.074 -7.422 1.00 0.00 C ATOM 556 CB HIS A 75 13.910 -8.643 -5.458 1.00 0.00 C ATOM 557 O HIS A 75 13.275 -11.292 -7.235 1.00 0.00 O ATOM 558 CG HIS A 75 14.605 -9.755 -4.740 1.00 0.00 C ATOM 559 CD2 HIS A 75 15.789 -10.366 -4.981 1.00 0.00 C ATOM 560 ND1 HIS A 75 14.075 -10.368 -3.625 1.00 0.00 N ATOM 561 CE1 HIS A 75 14.905 -11.310 -3.211 1.00 0.00 C ATOM 562 NE2 HIS A 75 15.954 -11.330 -4.016 1.00 0.00 N ATOM 563 N GLU A 76 13.647 -9.546 -8.538 1.00 0.00 N ATOM 564 CA GLU A 76 14.228 -10.322 -9.630 1.00 0.00 C ATOM 565 C GLU A 76 15.753 -10.283 -9.585 1.00 0.00 C ATOM 566 CB GLU A 76 13.727 -9.806 -10.981 1.00 0.00 C ATOM 567 O GLU A 76 16.350 -9.205 -9.546 1.00 0.00 O ATOM 568 CG GLU A 76 14.060 -10.722 -12.150 1.00 0.00 C ATOM 569 CD GLU A 76 13.399 -10.297 -13.452 1.00 0.00 C ATOM 570 OE1 GLU A 76 12.554 -9.373 -13.430 1.00 0.00 O ATOM 571 OE2 GLU A 76 13.727 -10.894 -14.501 1.00 0.00 O ATOM 572 N GLU A 77 16.313 -11.414 -9.551 1.00 0.00 N ATOM 573 CA GLU A 77 17.769 -11.510 -9.570 1.00 0.00 C ATOM 574 C GLU A 77 18.310 -11.423 -10.994 1.00 0.00 C ATOM 575 CB GLU A 77 18.231 -12.812 -8.911 1.00 0.00 C ATOM 576 O GLU A 77 17.548 -11.510 -11.959 1.00 0.00 O ATOM 577 CG GLU A 77 17.844 -12.929 -7.444 1.00 0.00 C ATOM 578 CD GLU A 77 18.639 -12.003 -6.537 1.00 0.00 C ATOM 579 OE1 GLU A 77 19.776 -11.626 -6.901 1.00 0.00 O ATOM 580 OE2 GLU A 77 18.120 -11.651 -5.454 1.00 0.00 O ATOM 581 N ASP A 78 19.573 -11.066 -11.091 1.00 0.00 N ATOM 582 CA ASP A 78 20.266 -10.915 -12.367 1.00 0.00 C ATOM 583 C ASP A 78 20.084 -12.153 -13.241 1.00 0.00 C ATOM 584 CB ASP A 78 21.755 -10.645 -12.140 1.00 0.00 C ATOM 585 O ASP A 78 20.095 -12.059 -14.470 1.00 0.00 O ATOM 586 CG ASP A 78 22.029 -9.254 -11.597 1.00 0.00 C ATOM 587 OD1 ASP A 78 23.114 -9.028 -11.018 1.00 0.00 O ATOM 588 OD2 ASP A 78 21.152 -8.376 -11.747 1.00 0.00 O ATOM 589 N ASP A 79 19.875 -13.279 -12.572 1.00 0.00 N ATOM 590 CA ASP A 79 19.730 -14.515 -13.335 1.00 0.00 C ATOM 591 C ASP A 79 18.288 -14.708 -13.799 1.00 0.00 C ATOM 592 CB ASP A 79 20.180 -15.716 -12.501 1.00 0.00 C ATOM 593 O ASP A 79 17.946 -15.750 -14.363 1.00 0.00 O ATOM 594 CG ASP A 79 19.357 -15.903 -11.238 1.00 0.00 C ATOM 595 OD1 ASP A 79 19.656 -16.822 -10.446 1.00 0.00 O ATOM 596 OD2 ASP A 79 18.399 -15.127 -11.036 1.00 0.00 O ATOM 597 N GLY A 80 17.414 -13.715 -13.581 1.00 0.00 N ATOM 598 CA GLY A 80 16.044 -13.776 -14.063 1.00 0.00 C ATOM 599 C GLY A 80 15.095 -14.439 -13.081 1.00 0.00 C ATOM 600 O GLY A 80 13.881 -14.444 -13.291 1.00 0.00 O ATOM 601 N ASP A 81 15.662 -15.063 -12.040 1.00 0.00 N ATOM 602 CA ASP A 81 14.823 -15.721 -11.043 1.00 0.00 C ATOM 603 C ASP A 81 14.161 -14.699 -10.121 1.00 0.00 C ATOM 604 CB ASP A 81 15.646 -16.715 -10.221 1.00 0.00 C ATOM 605 O ASP A 81 14.715 -13.625 -9.878 1.00 0.00 O ATOM 606 CG ASP A 81 16.113 -17.911 -11.031 1.00 0.00 C ATOM 607 OD1 ASP A 81 17.118 -18.550 -10.652 1.00 0.00 O ATOM 608 OD2 ASP A 81 15.472 -18.216 -12.060 1.00 0.00 O ATOM 609 N THR A 82 12.968 -14.929 -9.764 1.00 0.00 N ATOM 610 CA THR A 82 12.231 -14.082 -8.832 1.00 0.00 C ATOM 611 C THR A 82 12.233 -14.689 -7.432 1.00 0.00 C ATOM 612 CB THR A 82 10.780 -13.868 -9.299 1.00 0.00 C ATOM 613 O THR A 82 11.931 -15.872 -7.262 1.00 0.00 O ATOM 614 CG2 THR A 82 10.028 -12.938 -8.352 1.00 0.00 C ATOM 615 OG1 THR A 82 10.786 -13.291 -10.611 1.00 0.00 O ATOM 616 N HIS A 83 12.679 -13.936 -6.510 1.00 0.00 N ATOM 617 CA HIS A 83 12.653 -14.347 -5.110 1.00 0.00 C ATOM 618 C HIS A 83 11.661 -13.511 -4.309 1.00 0.00 C ATOM 619 CB HIS A 83 14.049 -14.239 -4.494 1.00 0.00 C ATOM 620 O HIS A 83 11.675 -12.280 -4.387 1.00 0.00 O ATOM 621 CG HIS A 83 15.047 -15.170 -5.104 1.00 0.00 C ATOM 622 CD2 HIS A 83 15.925 -14.991 -6.119 1.00 0.00 C ATOM 623 ND1 HIS A 83 15.219 -16.466 -4.669 1.00 0.00 N ATOM 624 CE1 HIS A 83 16.163 -17.046 -5.391 1.00 0.00 C ATOM 625 NE2 HIS A 83 16.608 -16.172 -6.279 1.00 0.00 N ATOM 626 N CYS A 84 10.791 -14.185 -3.722 1.00 0.00 N ATOM 627 CA CYS A 84 9.793 -13.514 -2.896 1.00 0.00 C ATOM 628 C CYS A 84 10.017 -13.813 -1.419 1.00 0.00 C ATOM 629 CB CYS A 84 8.384 -13.942 -3.305 1.00 0.00 C ATOM 630 O CYS A 84 10.408 -14.924 -1.059 1.00 0.00 O ATOM 631 SG CYS A 84 7.968 -13.539 -5.016 1.00 0.00 S ATOM 632 N HIS A 85 9.909 -12.859 -0.708 1.00 0.00 N ATOM 633 CA HIS A 85 9.975 -13.070 0.733 1.00 0.00 C ATOM 634 C HIS A 85 8.927 -12.236 1.461 1.00 0.00 C ATOM 635 CB HIS A 85 11.372 -12.734 1.260 1.00 0.00 C ATOM 636 O HIS A 85 8.377 -11.289 0.894 1.00 0.00 O ATOM 637 CG HIS A 85 11.748 -11.296 1.089 1.00 0.00 C ATOM 638 CD2 HIS A 85 11.777 -10.273 1.975 1.00 0.00 C ATOM 639 ND1 HIS A 85 12.152 -10.772 -0.120 1.00 0.00 N ATOM 640 CE1 HIS A 85 12.415 -9.485 0.031 1.00 0.00 C ATOM 641 NE2 HIS A 85 12.196 -9.157 1.293 1.00 0.00 N ATOM 642 N CYS A 86 8.500 -12.728 2.583 1.00 0.00 N ATOM 643 CA CYS A 86 7.596 -12.021 3.484 1.00 0.00 C ATOM 644 C CYS A 86 8.373 -11.290 4.572 1.00 0.00 C ATOM 645 CB CYS A 86 6.603 -12.993 4.119 1.00 0.00 C ATOM 646 O CYS A 86 8.939 -11.920 5.467 1.00 0.00 O ATOM 647 SG CYS A 86 5.473 -13.757 2.934 1.00 0.00 S ATOM 648 N SER A 87 8.541 -10.143 4.355 1.00 0.00 N ATOM 649 CA SER A 87 9.296 -9.406 5.363 1.00 0.00 C ATOM 650 C SER A 87 8.570 -8.129 5.774 1.00 0.00 C ATOM 651 CB SER A 87 10.692 -9.064 4.843 1.00 0.00 C ATOM 652 O SER A 87 8.018 -7.424 4.927 1.00 0.00 O ATOM 653 OG SER A 87 11.410 -8.297 5.794 1.00 0.00 O ATOM 654 N CYS A 88 8.324 -8.020 6.956 1.00 0.00 N ATOM 655 CA CYS A 88 7.764 -6.786 7.497 1.00 0.00 C ATOM 656 C CYS A 88 8.869 -5.829 7.928 1.00 0.00 C ATOM 657 CB CYS A 88 6.847 -7.088 8.681 1.00 0.00 C ATOM 658 O CYS A 88 8.600 -4.816 8.576 1.00 0.00 O ATOM 659 SG CYS A 88 5.414 -8.102 8.253 1.00 0.00 S ATOM 660 N GLU A 89 9.941 -6.277 7.427 1.00 0.00 N ATOM 661 CA GLU A 89 11.079 -5.417 7.736 1.00 0.00 C ATOM 662 C GLU A 89 11.164 -4.244 6.763 1.00 0.00 C ATOM 663 CB GLU A 89 12.382 -6.219 7.709 1.00 0.00 C ATOM 664 O GLU A 89 10.884 -4.397 5.572 1.00 0.00 O ATOM 665 CG GLU A 89 12.497 -7.244 8.828 1.00 0.00 C ATOM 666 CD GLU A 89 12.821 -6.626 10.178 1.00 0.00 C ATOM 667 OE1 GLU A 89 13.318 -5.477 10.216 1.00 0.00 O ATOM 668 OE2 GLU A 89 12.577 -7.295 11.207 1.00 0.00 O ATOM 669 N HIS A 90 10.877 -2.882 7.151 1.00 0.00 N ATOM 670 CA HIS A 90 11.037 -1.634 6.414 1.00 0.00 C ATOM 671 C HIS A 90 12.477 -1.452 5.945 1.00 0.00 C ATOM 672 CB HIS A 90 10.611 -0.444 7.276 1.00 0.00 C ATOM 673 O HIS A 90 13.291 -0.847 6.647 1.00 0.00 O ATOM 674 CG HIS A 90 9.172 -0.482 7.682 1.00 0.00 C ATOM 675 CD2 HIS A 90 8.592 -0.729 8.880 1.00 0.00 C ATOM 676 ND1 HIS A 90 8.143 -0.249 6.795 1.00 0.00 N ATOM 677 CE1 HIS A 90 6.989 -0.350 7.434 1.00 0.00 C ATOM 678 NE2 HIS A 90 7.234 -0.641 8.700 1.00 0.00 N ATOM 679 N SER A 91 13.113 -2.415 5.257 1.00 0.00 N ATOM 680 CA SER A 91 14.468 -1.999 4.909 1.00 0.00 C ATOM 681 C SER A 91 14.482 -1.180 3.623 1.00 0.00 C ATOM 682 CB SER A 91 15.380 -3.217 4.758 1.00 0.00 C ATOM 683 O SER A 91 13.868 -1.568 2.627 1.00 0.00 O ATOM 684 OG SER A 91 15.023 -3.974 3.614 1.00 0.00 O ATOM 685 N HIS A 92 14.296 0.148 3.642 1.00 0.00 N ATOM 686 CA HIS A 92 14.603 1.170 2.647 1.00 0.00 C ATOM 687 C HIS A 92 15.930 0.882 1.953 1.00 0.00 C ATOM 688 CB HIS A 92 14.638 2.555 3.295 1.00 0.00 C ATOM 689 O HIS A 92 16.284 1.551 0.979 1.00 0.00 O ATOM 690 CG HIS A 92 13.324 2.984 3.866 1.00 0.00 C ATOM 691 CD2 HIS A 92 12.943 3.213 5.145 1.00 0.00 C ATOM 692 ND1 HIS A 92 12.216 3.224 3.084 1.00 0.00 N ATOM 693 CE1 HIS A 92 11.207 3.584 3.859 1.00 0.00 C ATOM 694 NE2 HIS A 92 11.621 3.585 5.114 1.00 0.00 N ATOM 695 N ASP A 93 16.676 -0.193 2.168 1.00 0.00 N ATOM 696 CA ASP A 93 18.015 -0.132 1.589 1.00 0.00 C ATOM 697 C ASP A 93 18.097 -0.954 0.305 1.00 0.00 C ATOM 698 CB ASP A 93 19.058 -0.622 2.596 1.00 0.00 C ATOM 699 O ASP A 93 19.179 -1.132 -0.256 1.00 0.00 O ATOM 700 CG ASP A 93 19.487 0.454 3.577 1.00 0.00 C ATOM 701 OD1 ASP A 93 20.370 0.192 4.423 1.00 0.00 O ATOM 702 OD2 ASP A 93 18.935 1.573 3.507 1.00 0.00 O ATOM 703 N HIS A 94 17.467 -0.634 -0.758 1.00 0.00 N ATOM 704 CA HIS A 94 18.140 -1.057 -1.982 1.00 0.00 C ATOM 705 C HIS A 94 17.627 -0.280 -3.189 1.00 0.00 C ATOM 706 CB HIS A 94 17.951 -2.559 -2.205 1.00 0.00 C ATOM 707 O HIS A 94 16.419 -0.075 -3.334 1.00 0.00 O ATOM 708 CG HIS A 94 18.800 -3.409 -1.315 1.00 0.00 C ATOM 709 CD2 HIS A 94 18.467 -4.255 -0.312 1.00 0.00 C ATOM 710 ND1 HIS A 94 20.175 -3.442 -1.407 1.00 0.00 N ATOM 711 CE1 HIS A 94 20.651 -4.276 -0.497 1.00 0.00 C ATOM 712 NE2 HIS A 94 19.635 -4.782 0.181 1.00 0.00 N ATOM 713 N HIS A 95 18.249 0.957 -3.481 1.00 0.00 N ATOM 714 CA HIS A 95 18.496 1.578 -4.778 1.00 0.00 C ATOM 715 C HIS A 95 18.041 0.672 -5.918 1.00 0.00 C ATOM 716 CB HIS A 95 19.979 1.916 -4.936 1.00 0.00 C ATOM 717 O HIS A 95 18.521 0.799 -7.046 1.00 0.00 O ATOM 718 CG HIS A 95 20.458 2.973 -3.992 1.00 0.00 C ATOM 719 CD2 HIS A 95 21.388 2.932 -3.010 1.00 0.00 C ATOM 720 ND1 HIS A 95 19.959 4.258 -3.999 1.00 0.00 N ATOM 721 CE1 HIS A 95 20.565 4.963 -3.059 1.00 0.00 C ATOM 722 NE2 HIS A 95 21.437 4.182 -2.444 1.00 0.00 N ATOM 723 N ASP A 96 16.923 0.136 -5.980 1.00 0.00 N ATOM 724 CA ASP A 96 16.554 -0.218 -7.347 1.00 0.00 C ATOM 725 C ASP A 96 15.459 0.705 -7.877 1.00 0.00 C ATOM 726 CB ASP A 96 16.093 -1.676 -7.418 1.00 0.00 C ATOM 727 O ASP A 96 14.655 1.230 -7.104 1.00 0.00 O ATOM 728 CG ASP A 96 17.246 -2.663 -7.414 1.00 0.00 C ATOM 729 OD1 ASP A 96 17.024 -3.859 -7.125 1.00 0.00 O ATOM 730 OD2 ASP A 96 18.388 -2.242 -7.699 1.00 0.00 O ATOM 731 N ASP A 97 15.890 1.837 -8.509 1.00 0.00 N ATOM 732 CA ASP A 97 15.081 2.551 -9.491 1.00 0.00 C ATOM 733 C ASP A 97 13.874 1.718 -9.918 1.00 0.00 C ATOM 734 CB ASP A 97 15.923 2.923 -10.713 1.00 0.00 C ATOM 735 O ASP A 97 13.369 1.874 -11.032 1.00 0.00 O ATOM 736 CG ASP A 97 16.981 3.969 -10.409 1.00 0.00 C ATOM 737 OD1 ASP A 97 18.049 3.963 -11.058 1.00 0.00 O ATOM 738 OD2 ASP A 97 16.746 4.804 -9.509 1.00 0.00 O ATOM 739 N ASP A 98 13.468 0.802 -9.181 1.00 0.00 N ATOM 740 CA ASP A 98 12.224 0.241 -9.699 1.00 0.00 C ATOM 741 C ASP A 98 11.093 1.266 -9.639 1.00 0.00 C ATOM 742 CB ASP A 98 11.837 -1.017 -8.920 1.00 0.00 C ATOM 743 O ASP A 98 10.974 2.010 -8.663 1.00 0.00 O ATOM 744 CG ASP A 98 12.688 -2.222 -9.278 1.00 0.00 C ATOM 745 OD1 ASP A 98 12.775 -3.170 -8.468 1.00 0.00 O ATOM 746 OD2 ASP A 98 13.280 -2.223 -10.379 1.00 0.00 O ATOM 747 N THR A 99 11.132 2.146 -10.695 1.00 0.00 N ATOM 748 CA THR A 99 9.998 2.959 -11.120 1.00 0.00 C ATOM 749 C THR A 99 8.685 2.355 -10.628 1.00 0.00 C ATOM 750 CB THR A 99 9.957 3.102 -12.653 1.00 0.00 C ATOM 751 O THR A 99 7.730 2.223 -11.396 1.00 0.00 O ATOM 752 CG2 THR A 99 11.214 3.791 -13.174 1.00 0.00 C ATOM 753 OG1 THR A 99 9.857 1.802 -13.246 1.00 0.00 O ATOM 754 N HIS A 100 8.653 1.675 -9.540 1.00 0.00 N ATOM 755 CA HIS A 100 7.234 1.548 -9.228 1.00 0.00 C ATOM 756 C HIS A 100 6.625 2.899 -8.870 1.00 0.00 C ATOM 757 CB HIS A 100 7.024 0.557 -8.082 1.00 0.00 C ATOM 758 O HIS A 100 7.154 3.617 -8.019 1.00 0.00 O ATOM 759 CG HIS A 100 7.437 -0.842 -8.414 1.00 0.00 C ATOM 760 CD2 HIS A 100 8.446 -1.607 -7.937 1.00 0.00 C ATOM 761 ND1 HIS A 100 6.777 -1.610 -9.349 1.00 0.00 N ATOM 762 CE1 HIS A 100 7.365 -2.793 -9.431 1.00 0.00 C ATOM 763 NE2 HIS A 100 8.380 -2.816 -8.585 1.00 0.00 N ATOM 764 N GLY A 101 6.381 3.654 -9.900 1.00 0.00 N ATOM 765 CA GLY A 101 5.487 4.753 -9.574 1.00 0.00 C ATOM 766 C GLY A 101 4.744 4.550 -8.267 1.00 0.00 C ATOM 767 O GLY A 101 3.522 4.386 -8.261 1.00 0.00 O ATOM 768 N GLU A 102 5.430 3.707 -7.432 1.00 0.00 N ATOM 769 CA GLU A 102 4.594 3.693 -6.235 1.00 0.00 C ATOM 770 C GLU A 102 4.478 5.087 -5.627 1.00 0.00 C ATOM 771 CB GLU A 102 5.153 2.712 -5.201 1.00 0.00 C ATOM 772 O GLU A 102 5.392 5.905 -5.757 1.00 0.00 O ATOM 773 CG GLU A 102 5.195 1.269 -5.681 1.00 0.00 C ATOM 774 CD GLU A 102 3.815 0.668 -5.897 1.00 0.00 C ATOM 775 OE1 GLU A 102 2.810 1.292 -5.486 1.00 0.00 O ATOM 776 OE2 GLU A 102 3.738 -0.436 -6.481 1.00 0.00 O ATOM 777 N CYS A 103 3.304 5.585 -5.881 1.00 0.00 N ATOM 778 CA CYS A 103 2.937 6.733 -5.061 1.00 0.00 C ATOM 779 C CYS A 103 3.767 6.778 -3.783 1.00 0.00 C ATOM 780 CB CYS A 103 1.449 6.690 -4.712 1.00 0.00 C ATOM 781 O CYS A 103 3.803 5.806 -3.027 1.00 0.00 O ATOM 782 SG CYS A 103 0.362 6.999 -6.121 1.00 0.00 S ATOM 783 N THR A 104 4.856 7.423 -3.910 1.00 0.00 N ATOM 784 CA THR A 104 5.617 7.650 -2.686 1.00 0.00 C ATOM 785 C THR A 104 5.025 8.808 -1.888 1.00 0.00 C ATOM 786 CB THR A 104 7.098 7.939 -2.995 1.00 0.00 C ATOM 787 O THR A 104 4.142 9.517 -2.375 1.00 0.00 O ATOM 788 CG2 THR A 104 7.686 6.875 -3.916 1.00 0.00 C ATOM 789 OG1 THR A 104 7.206 9.219 -3.631 1.00 0.00 O ATOM 790 N LYS A 105 5.301 8.726 -0.683 1.00 0.00 N ATOM 791 CA LYS A 105 4.870 9.830 0.169 1.00 0.00 C ATOM 792 C LYS A 105 5.196 11.178 -0.469 1.00 0.00 C ATOM 793 CB LYS A 105 5.523 9.731 1.548 1.00 0.00 C ATOM 794 O LYS A 105 4.534 12.179 -0.190 1.00 0.00 O ATOM 795 CG LYS A 105 4.955 8.625 2.425 1.00 0.00 C ATOM 796 CD LYS A 105 5.514 8.690 3.840 1.00 0.00 C ATOM 797 CE LYS A 105 4.894 7.627 4.736 1.00 0.00 C ATOM 798 NZ LYS A 105 5.487 7.643 6.107 1.00 0.00 N ATOM 799 N LYS A 106 6.132 11.170 -1.417 1.00 0.00 N ATOM 800 CA LYS A 106 6.565 12.408 -2.059 1.00 0.00 C ATOM 801 C LYS A 106 5.727 12.707 -3.298 1.00 0.00 C ATOM 802 CB LYS A 106 8.046 12.329 -2.434 1.00 0.00 C ATOM 803 O LYS A 106 5.794 13.808 -3.849 1.00 0.00 O ATOM 804 CG LYS A 106 8.986 12.274 -1.239 1.00 0.00 C ATOM 805 CD LYS A 106 10.445 12.262 -1.676 1.00 0.00 C ATOM 806 CE LYS A 106 11.387 12.222 -0.480 1.00 0.00 C ATOM 807 NZ LYS A 106 12.817 12.151 -0.903 1.00 0.00 N ATOM 808 N ALA A 107 5.009 11.655 -3.672 1.00 0.00 N ATOM 809 CA ALA A 107 4.208 11.854 -4.877 1.00 0.00 C ATOM 810 C ALA A 107 3.004 12.748 -4.594 1.00 0.00 C ATOM 811 CB ALA A 107 3.749 10.511 -5.439 1.00 0.00 C ATOM 812 O ALA A 107 2.358 12.618 -3.552 1.00 0.00 O ATOM 813 N PRO A 108 2.750 13.735 -5.350 1.00 0.00 N ATOM 814 CA PRO A 108 1.593 14.609 -5.140 1.00 0.00 C ATOM 815 C PRO A 108 0.271 13.845 -5.124 1.00 0.00 C ATOM 816 CB PRO A 108 1.656 15.568 -6.331 1.00 0.00 C ATOM 817 O PRO A 108 -0.730 14.348 -4.607 1.00 0.00 O ATOM 818 CG PRO A 108 2.473 14.851 -7.356 1.00 0.00 C ATOM 819 CD PRO A 108 3.398 13.901 -6.650 1.00 0.00 C ATOM 820 N CYS A 109 0.245 12.652 -5.681 1.00 0.00 N ATOM 821 CA CYS A 109 -1.009 11.911 -5.770 1.00 0.00 C ATOM 822 C CYS A 109 -1.162 10.954 -4.594 1.00 0.00 C ATOM 823 CB CYS A 109 -1.079 11.134 -7.084 1.00 0.00 C ATOM 824 O CYS A 109 -2.174 10.261 -4.480 1.00 0.00 O ATOM 825 SG CYS A 109 0.290 9.980 -7.322 1.00 0.00 S ATOM 826 N TRP A 110 -0.068 10.925 -3.822 1.00 0.00 N ATOM 827 CA TRP A 110 -0.125 10.100 -2.621 1.00 0.00 C ATOM 828 C TRP A 110 -1.071 10.704 -1.589 1.00 0.00 C ATOM 829 CB TRP A 110 1.272 9.934 -2.016 1.00 0.00 C ATOM 830 O TRP A 110 -0.962 11.887 -1.255 1.00 0.00 O ATOM 831 CG TRP A 110 1.322 8.997 -0.846 1.00 0.00 C ATOM 832 CD1 TRP A 110 1.696 7.682 -0.859 1.00 0.00 C ATOM 833 CD2 TRP A 110 0.980 9.304 0.509 1.00 0.00 C ATOM 834 CE2 TRP A 110 1.172 8.127 1.266 1.00 0.00 C ATOM 835 CE3 TRP A 110 0.531 10.462 1.158 1.00 0.00 C ATOM 836 NE1 TRP A 110 1.608 7.153 0.408 1.00 0.00 N ATOM 837 CH2 TRP A 110 0.491 9.222 3.250 1.00 0.00 C ATOM 838 CZ2 TRP A 110 0.929 8.075 2.640 1.00 0.00 C ATOM 839 CZ3 TRP A 110 0.290 10.409 2.526 1.00 0.00 C ATOM 840 N ARG A 111 -2.102 9.880 -1.162 1.00 0.00 N ATOM 841 CA ARG A 111 -3.086 10.357 -0.197 1.00 0.00 C ATOM 842 C ARG A 111 -3.345 9.313 0.884 1.00 0.00 C ATOM 843 CB ARG A 111 -4.397 10.720 -0.899 1.00 0.00 C ATOM 844 O ARG A 111 -3.329 8.111 0.610 1.00 0.00 O ATOM 845 CG ARG A 111 -5.466 11.263 0.034 1.00 0.00 C ATOM 846 CD ARG A 111 -5.180 12.701 0.443 1.00 0.00 C ATOM 847 NE ARG A 111 -6.289 13.277 1.200 1.00 0.00 N ATOM 848 NH1 ARG A 111 -5.313 15.357 1.444 1.00 0.00 N ATOM 849 NH2 ARG A 111 -7.384 14.946 2.335 1.00 0.00 N ATOM 850 CZ ARG A 111 -6.326 14.525 1.658 1.00 0.00 C ATOM 851 N CYS A 112 -3.365 9.888 2.033 1.00 0.00 N ATOM 852 CA CYS A 112 -3.705 9.030 3.162 1.00 0.00 C ATOM 853 C CYS A 112 -5.019 9.463 3.801 1.00 0.00 C ATOM 854 CB CYS A 112 -2.589 9.051 4.206 1.00 0.00 C ATOM 855 O CYS A 112 -5.318 10.657 3.866 1.00 0.00 O ATOM 856 SG CYS A 112 -1.031 8.349 3.621 1.00 0.00 S ATOM 857 N GLU A 113 -5.830 8.580 3.951 1.00 0.00 N ATOM 858 CA GLU A 113 -7.053 8.822 4.710 1.00 0.00 C ATOM 859 C GLU A 113 -7.031 8.080 6.044 1.00 0.00 C ATOM 860 CB GLU A 113 -8.282 8.407 3.897 1.00 0.00 C ATOM 861 O GLU A 113 -6.553 6.947 6.122 1.00 0.00 O ATOM 862 CG GLU A 113 -8.500 9.241 2.643 1.00 0.00 C ATOM 863 CD GLU A 113 -9.731 8.826 1.853 1.00 0.00 C ATOM 864 OE1 GLU A 113 -10.458 7.909 2.299 1.00 0.00 O ATOM 865 OE2 GLU A 113 -9.971 9.422 0.780 1.00 0.00 O ATOM 866 N TYR A 114 -7.305 8.869 7.059 1.00 0.00 N ATOM 867 CA TYR A 114 -7.411 8.262 8.381 1.00 0.00 C ATOM 868 C TYR A 114 -8.671 7.412 8.491 1.00 0.00 C ATOM 869 CB TYR A 114 -7.412 9.340 9.469 1.00 0.00 C ATOM 870 O TYR A 114 -9.775 7.889 8.219 1.00 0.00 O ATOM 871 CG TYR A 114 -7.392 8.785 10.872 1.00 0.00 C ATOM 872 CD1 TYR A 114 -8.527 8.834 11.678 1.00 0.00 C ATOM 873 CD2 TYR A 114 -6.238 8.213 11.396 1.00 0.00 C ATOM 874 CE1 TYR A 114 -8.513 8.326 12.973 1.00 0.00 C ATOM 875 CE2 TYR A 114 -6.212 7.702 12.690 1.00 0.00 C ATOM 876 OH TYR A 114 -7.333 7.258 14.750 1.00 0.00 O ATOM 877 CZ TYR A 114 -7.353 7.762 13.469 1.00 0.00 C ATOM 878 N ASN A 115 -8.439 6.137 8.704 1.00 0.00 N ATOM 879 CA ASN A 115 -9.527 5.202 8.972 1.00 0.00 C ATOM 880 C ASN A 115 -9.770 5.039 10.469 1.00 0.00 C ATOM 881 CB ASN A 115 -9.238 3.844 8.330 1.00 0.00 C ATOM 882 O ASN A 115 -8.953 4.443 11.174 1.00 0.00 O ATOM 883 CG ASN A 115 -10.442 2.922 8.345 1.00 0.00 C ATOM 884 ND2 ASN A 115 -10.511 2.021 7.373 1.00 0.00 N ATOM 885 OD1 ASN A 115 -11.302 3.020 9.224 1.00 0.00 O ATOM 886 N ALA A 116 -10.796 5.699 10.920 1.00 0.00 N ATOM 887 CA ALA A 116 -11.108 5.723 12.347 1.00 0.00 C ATOM 888 C ALA A 116 -11.283 4.310 12.894 1.00 0.00 C ATOM 889 CB ALA A 116 -12.366 6.549 12.603 1.00 0.00 C ATOM 890 O ALA A 116 -10.898 4.025 14.031 1.00 0.00 O ATOM 891 N ASP A 117 -11.725 3.414 12.007 1.00 0.00 N ATOM 892 CA ASP A 117 -11.929 2.033 12.433 1.00 0.00 C ATOM 893 C ASP A 117 -10.595 1.313 12.619 1.00 0.00 C ATOM 894 CB ASP A 117 -12.796 1.281 11.421 1.00 0.00 C ATOM 895 O ASP A 117 -10.432 0.529 13.557 1.00 0.00 O ATOM 896 CG ASP A 117 -14.225 1.793 11.369 1.00 0.00 C ATOM 897 OD1 ASP A 117 -14.898 1.618 10.331 1.00 0.00 O ATOM 898 OD2 ASP A 117 -14.681 2.378 12.375 1.00 0.00 O ATOM 899 N LEU A 118 -9.664 1.666 11.738 1.00 0.00 N ATOM 900 CA LEU A 118 -8.349 1.035 11.785 1.00 0.00 C ATOM 901 C LEU A 118 -7.364 1.891 12.575 1.00 0.00 C ATOM 902 CB LEU A 118 -7.816 0.800 10.369 1.00 0.00 C ATOM 903 O LEU A 118 -6.231 1.472 12.822 1.00 0.00 O ATOM 904 CG LEU A 118 -8.639 -0.135 9.481 1.00 0.00 C ATOM 905 CD1 LEU A 118 -8.022 -0.225 8.090 1.00 0.00 C ATOM 906 CD2 LEU A 118 -8.746 -1.518 10.115 1.00 0.00 C ATOM 907 N LYS A 119 -7.828 3.091 12.895 1.00 0.00 N ATOM 908 CA LYS A 119 -6.988 4.069 13.580 1.00 0.00 C ATOM 909 C LYS A 119 -5.640 4.222 12.882 1.00 0.00 C ATOM 910 CB LYS A 119 -6.780 3.668 15.041 1.00 0.00 C ATOM 911 O LYS A 119 -4.596 4.257 13.537 1.00 0.00 O ATOM 912 CG LYS A 119 -8.064 3.604 15.855 1.00 0.00 C ATOM 913 CD LYS A 119 -7.786 3.255 17.311 1.00 0.00 C ATOM 914 CE LYS A 119 -9.062 3.263 18.143 1.00 0.00 C ATOM 915 NZ LYS A 119 -8.786 2.979 19.583 1.00 0.00 N ATOM 916 N HIS A 120 -5.544 4.099 11.731 1.00 0.00 N ATOM 917 CA HIS A 120 -4.341 4.353 10.946 1.00 0.00 C ATOM 918 C HIS A 120 -4.690 4.898 9.565 1.00 0.00 C ATOM 919 CB HIS A 120 -3.510 3.075 10.811 1.00 0.00 C ATOM 920 O HIS A 120 -5.853 4.869 9.156 1.00 0.00 O ATOM 921 CG HIS A 120 -4.217 1.973 10.089 1.00 0.00 C ATOM 922 CD2 HIS A 120 -4.107 1.532 8.813 1.00 0.00 C ATOM 923 ND1 HIS A 120 -5.174 1.183 10.689 1.00 0.00 N ATOM 924 CE1 HIS A 120 -5.622 0.301 9.811 1.00 0.00 C ATOM 925 NE2 HIS A 120 -4.990 0.491 8.666 1.00 0.00 N ATOM 926 N ASP A 121 -3.704 5.475 9.017 1.00 0.00 N ATOM 927 CA ASP A 121 -3.873 6.009 7.669 1.00 0.00 C ATOM 928 C ASP A 121 -3.838 4.892 6.628 1.00 0.00 C ATOM 929 CB ASP A 121 -2.792 7.047 7.363 1.00 0.00 C ATOM 930 O ASP A 121 -3.053 3.949 6.747 1.00 0.00 O ATOM 931 CG ASP A 121 -2.917 8.301 8.210 1.00 0.00 C ATOM 932 OD1 ASP A 121 -1.936 9.069 8.312 1.00 0.00 O ATOM 933 OD2 ASP A 121 -4.006 8.521 8.784 1.00 0.00 O ATOM 934 N VAL A 122 -4.829 4.935 5.875 1.00 0.00 N ATOM 935 CA VAL A 122 -4.775 4.123 4.663 1.00 0.00 C ATOM 936 C VAL A 122 -4.276 4.971 3.495 1.00 0.00 C ATOM 937 CB VAL A 122 -6.154 3.511 4.328 1.00 0.00 C ATOM 938 O VAL A 122 -4.857 6.013 3.184 1.00 0.00 O ATOM 939 CG1 VAL A 122 -6.063 2.625 3.087 1.00 0.00 C ATOM 940 CG2 VAL A 122 -6.688 2.717 5.518 1.00 0.00 C ATOM 941 N CYS A 123 -3.142 4.531 3.102 1.00 0.00 N ATOM 942 CA CYS A 123 -2.472 5.318 2.073 1.00 0.00 C ATOM 943 C CYS A 123 -2.628 4.669 0.702 1.00 0.00 C ATOM 944 CB CYS A 123 -0.988 5.481 2.403 1.00 0.00 C ATOM 945 O CYS A 123 -2.671 3.443 0.593 1.00 0.00 O ATOM 946 SG CYS A 123 -0.681 6.285 3.991 1.00 0.00 S ATOM 947 N GLY A 124 -2.924 5.462 -0.260 1.00 0.00 N ATOM 948 CA GLY A 124 -2.940 5.028 -1.648 1.00 0.00 C ATOM 949 C GLY A 124 -2.699 6.159 -2.630 1.00 0.00 C ATOM 950 O GLY A 124 -2.463 7.299 -2.225 1.00 0.00 O ATOM 951 N CYS A 125 -2.378 5.820 -3.813 1.00 0.00 N ATOM 952 CA CYS A 125 -2.283 6.770 -4.916 1.00 0.00 C ATOM 953 C CYS A 125 -3.667 7.160 -5.421 1.00 0.00 C ATOM 954 CB CYS A 125 -1.458 6.183 -6.061 1.00 0.00 C ATOM 955 O CYS A 125 -4.425 6.307 -5.886 1.00 0.00 O ATOM 956 SG CYS A 125 0.275 5.900 -5.639 1.00 0.00 S ATOM 957 N GLU A 126 -4.004 8.323 -5.203 1.00 0.00 N ATOM 958 CA GLU A 126 -5.332 8.779 -5.604 1.00 0.00 C ATOM 959 C GLU A 126 -5.243 9.988 -6.530 1.00 0.00 C ATOM 960 CB GLU A 126 -6.177 9.119 -4.374 1.00 0.00 C ATOM 961 O GLU A 126 -5.752 11.064 -6.206 1.00 0.00 O ATOM 962 CG GLU A 126 -6.467 7.924 -3.478 1.00 0.00 C ATOM 963 CD GLU A 126 -7.488 6.964 -4.068 1.00 0.00 C ATOM 964 OE1 GLU A 126 -8.228 7.361 -4.997 1.00 0.00 O ATOM 965 OE2 GLU A 126 -7.550 5.807 -3.597 1.00 0.00 O ATOM 966 N CYS A 127 -4.822 9.841 -7.699 1.00 0.00 N ATOM 967 CA CYS A 127 -4.615 10.948 -8.626 1.00 0.00 C ATOM 968 C CYS A 127 -5.940 11.598 -9.005 1.00 0.00 C ATOM 969 CB CYS A 127 -3.895 10.466 -9.885 1.00 0.00 C ATOM 970 O CYS A 127 -5.987 12.790 -9.312 1.00 0.00 O ATOM 971 SG CYS A 127 -2.217 9.868 -9.581 1.00 0.00 S ATOM 972 N SER A 128 -6.846 10.833 -8.955 1.00 0.00 N ATOM 973 CA SER A 128 -8.150 11.305 -9.408 1.00 0.00 C ATOM 974 C SER A 128 -8.755 12.293 -8.417 1.00 0.00 C ATOM 975 CB SER A 128 -9.104 10.128 -9.616 1.00 0.00 C ATOM 976 O SER A 128 -9.642 13.073 -8.772 1.00 0.00 O ATOM 977 OG SER A 128 -9.249 9.381 -8.420 1.00 0.00 O ATOM 978 N LYS A 129 -8.286 12.254 -7.213 1.00 0.00 N ATOM 979 CA LYS A 129 -8.887 13.076 -6.166 1.00 0.00 C ATOM 980 C LYS A 129 -8.020 14.294 -5.859 1.00 0.00 C ATOM 981 CB LYS A 129 -9.104 12.253 -4.896 1.00 0.00 C ATOM 982 O LYS A 129 -8.420 15.169 -5.089 1.00 0.00 O ATOM 983 CG LYS A 129 -10.151 11.158 -5.039 1.00 0.00 C ATOM 984 CD LYS A 129 -10.395 10.441 -3.717 1.00 0.00 C ATOM 985 CE LYS A 129 -11.490 9.392 -3.843 1.00 0.00 C ATOM 986 NZ LYS A 129 -11.820 8.774 -2.524 1.00 0.00 N ATOM 987 N LEU A 130 -6.820 14.391 -6.394 1.00 0.00 N ATOM 988 CA LEU A 130 -5.922 15.506 -6.110 1.00 0.00 C ATOM 989 C LEU A 130 -6.255 16.708 -6.987 1.00 0.00 C ATOM 990 CB LEU A 130 -4.465 15.089 -6.326 1.00 0.00 C ATOM 991 O LEU A 130 -6.713 16.548 -8.120 1.00 0.00 O ATOM 992 CG LEU A 130 -3.879 14.117 -5.300 1.00 0.00 C ATOM 993 CD1 LEU A 130 -2.476 13.689 -5.718 1.00 0.00 C ATOM 994 CD2 LEU A 130 -3.859 14.751 -3.913 1.00 0.00 C ATOM 995 N PRO A 131 -6.218 17.878 -6.321 1.00 0.00 N ATOM 996 CA PRO A 131 -6.403 19.088 -7.125 1.00 0.00 C ATOM 997 C PRO A 131 -5.423 19.176 -8.293 1.00 0.00 C ATOM 998 CB PRO A 131 -6.159 20.219 -6.123 1.00 0.00 C ATOM 999 O PRO A 131 -4.287 18.706 -8.188 1.00 0.00 O ATOM 1000 CG PRO A 131 -5.279 19.617 -5.075 1.00 0.00 C ATOM 1001 CD PRO A 131 -5.586 18.150 -4.979 1.00 0.00 C ATOM 1002 N CYS A 132 -5.915 19.530 -9.527 1.00 0.00 N ATOM 1003 CA CYS A 132 -5.087 19.711 -10.714 1.00 0.00 C ATOM 1004 C CYS A 132 -4.132 20.886 -10.540 1.00 0.00 C ATOM 1005 CB CYS A 132 -5.960 19.930 -11.949 1.00 0.00 C ATOM 1006 O CYS A 132 -4.531 22.042 -10.690 1.00 0.00 O ATOM 1007 SG CYS A 132 -6.896 18.468 -12.448 1.00 0.00 S ATOM 1008 N ASN A 133 -3.080 20.705 -9.927 1.00 0.00 N ATOM 1009 CA ASN A 133 -2.027 21.708 -9.810 1.00 0.00 C ATOM 1010 C ASN A 133 -0.764 21.283 -10.553 1.00 0.00 C ATOM 1011 CB ASN A 133 -1.710 21.986 -8.339 1.00 0.00 C ATOM 1012 O ASN A 133 -0.740 20.230 -11.194 1.00 0.00 O ATOM 1013 CG ASN A 133 -1.260 20.744 -7.595 1.00 0.00 C ATOM 1014 ND2 ASN A 133 -1.758 20.570 -6.376 1.00 0.00 N ATOM 1015 OD1 ASN A 133 -0.470 19.949 -8.110 1.00 0.00 O ATOM 1016 N ASP A 134 0.201 22.148 -10.651 1.00 0.00 N ATOM 1017 CA ASP A 134 1.408 21.962 -11.451 1.00 0.00 C ATOM 1018 C ASP A 134 2.162 20.705 -11.023 1.00 0.00 C ATOM 1019 CB ASP A 134 2.320 23.185 -11.338 1.00 0.00 C ATOM 1020 O ASP A 134 2.999 20.192 -11.768 1.00 0.00 O ATOM 1021 CG ASP A 134 1.789 24.392 -12.091 1.00 0.00 C ATOM 1022 OD1 ASP A 134 2.250 25.525 -11.832 1.00 0.00 O ATOM 1023 OD2 ASP A 134 0.898 24.210 -12.950 1.00 0.00 O ATOM 1024 N GLU A 135 1.732 20.132 -9.899 1.00 0.00 N ATOM 1025 CA GLU A 135 2.429 18.946 -9.410 1.00 0.00 C ATOM 1026 C GLU A 135 1.714 17.669 -9.840 1.00 0.00 C ATOM 1027 CB GLU A 135 2.559 18.988 -7.885 1.00 0.00 C ATOM 1028 O GLU A 135 2.282 16.577 -9.766 1.00 0.00 O ATOM 1029 CG GLU A 135 3.439 20.120 -7.374 1.00 0.00 C ATOM 1030 CD GLU A 135 3.561 20.146 -5.859 1.00 0.00 C ATOM 1031 OE1 GLU A 135 2.885 19.340 -5.181 1.00 0.00 O ATOM 1032 OE2 GLU A 135 4.339 20.981 -5.346 1.00 0.00 O ATOM 1033 N HIS A 136 0.480 17.885 -10.293 1.00 0.00 N ATOM 1034 CA HIS A 136 -0.314 16.733 -10.704 1.00 0.00 C ATOM 1035 C HIS A 136 0.053 16.287 -12.116 1.00 0.00 C ATOM 1036 CB HIS A 136 -1.807 17.057 -10.628 1.00 0.00 C ATOM 1037 O HIS A 136 0.114 17.107 -13.035 1.00 0.00 O ATOM 1038 CG HIS A 136 -2.685 15.846 -10.645 1.00 0.00 C ATOM 1039 CD2 HIS A 136 -3.469 15.303 -9.684 1.00 0.00 C ATOM 1040 ND1 HIS A 136 -2.822 15.042 -11.756 1.00 0.00 N ATOM 1041 CE1 HIS A 136 -3.655 14.054 -11.476 1.00 0.00 C ATOM 1042 NE2 HIS A 136 -4.062 14.189 -10.225 1.00 0.00 N ATOM 1043 N PRO A 137 0.226 15.184 -12.322 1.00 0.00 N ATOM 1044 CA PRO A 137 0.690 14.688 -13.619 1.00 0.00 C ATOM 1045 C PRO A 137 -0.331 14.908 -14.734 1.00 0.00 C ATOM 1046 CB PRO A 137 0.910 13.194 -13.368 1.00 0.00 C ATOM 1047 O PRO A 137 0.032 14.929 -15.913 1.00 0.00 O ATOM 1048 CG PRO A 137 0.170 12.907 -12.101 1.00 0.00 C ATOM 1049 CD PRO A 137 0.003 14.193 -11.344 1.00 0.00 C ATOM 1050 N CYS A 138 -1.650 15.096 -14.399 1.00 0.00 N ATOM 1051 CA CYS A 138 -2.702 15.293 -15.390 1.00 0.00 C ATOM 1052 C CYS A 138 -2.947 16.776 -15.639 1.00 0.00 C ATOM 1053 CB CYS A 138 -3.998 14.621 -14.937 1.00 0.00 C ATOM 1054 O CYS A 138 -3.870 17.144 -16.368 1.00 0.00 O ATOM 1055 SG CYS A 138 -3.887 12.822 -14.830 1.00 0.00 S ATOM 1056 N TYR A 139 -2.050 17.530 -14.923 1.00 0.00 N ATOM 1057 CA TYR A 139 -2.147 18.977 -15.082 1.00 0.00 C ATOM 1058 C TYR A 139 -1.580 19.417 -16.427 1.00 0.00 C ATOM 1059 CB TYR A 139 -1.411 19.693 -13.946 1.00 0.00 C ATOM 1060 O TYR A 139 -0.470 19.029 -16.796 1.00 0.00 O ATOM 1061 CG TYR A 139 -1.400 21.197 -14.083 1.00 0.00 C ATOM 1062 CD1 TYR A 139 -0.320 21.854 -14.668 1.00 0.00 C ATOM 1063 CD2 TYR A 139 -2.468 21.962 -13.627 1.00 0.00 C ATOM 1064 CE1 TYR A 139 -0.305 23.239 -14.795 1.00 0.00 C ATOM 1065 CE2 TYR A 139 -2.463 23.348 -13.748 1.00 0.00 C ATOM 1066 OH TYR A 139 -1.369 25.348 -14.456 1.00 0.00 O ATOM 1067 CZ TYR A 139 -1.379 23.976 -14.333 1.00 0.00 C ATOM 1068 N ARG A 140 -2.489 20.100 -17.284 1.00 0.00 N ATOM 1069 CA ARG A 140 -2.036 20.668 -18.550 1.00 0.00 C ATOM 1070 C ARG A 140 -2.355 22.157 -18.626 1.00 0.00 C ATOM 1071 CB ARG A 140 -2.678 19.934 -19.729 1.00 0.00 C ATOM 1072 O ARG A 140 -3.435 22.589 -18.217 1.00 0.00 O ATOM 1073 CG ARG A 140 -2.260 18.477 -19.849 1.00 0.00 C ATOM 1074 CD ARG A 140 -2.856 17.819 -21.086 1.00 0.00 C ATOM 1075 NE ARG A 140 -2.303 16.486 -21.307 1.00 0.00 N ATOM 1076 NH1 ARG A 140 -1.510 16.942 -23.429 1.00 0.00 N ATOM 1077 NH2 ARG A 140 -1.212 14.863 -22.510 1.00 0.00 N ATOM 1078 CZ ARG A 140 -1.676 16.100 -22.415 1.00 0.00 C ATOM 1079 N LYS A 141 -1.270 22.911 -18.875 1.00 0.00 N ATOM 1080 CA LYS A 141 -1.432 24.343 -19.105 1.00 0.00 C ATOM 1081 C LYS A 141 -1.210 24.693 -20.574 1.00 0.00 C ATOM 1082 CB LYS A 141 -0.468 25.141 -18.226 1.00 0.00 C ATOM 1083 O LYS A 141 -0.111 24.513 -21.101 1.00 0.00 O ATOM 1084 CG LYS A 141 -0.749 26.636 -18.196 1.00 0.00 C ATOM 1085 CD LYS A 141 0.167 27.359 -17.217 1.00 0.00 C ATOM 1086 CE LYS A 141 -0.124 28.853 -17.175 1.00 0.00 C ATOM 1087 NZ LYS A 141 0.783 29.568 -16.230 1.00 0.00 N ATOM 1088 N GLU A 142 -2.285 24.849 -21.311 1.00 0.00 N ATOM 1089 CA GLU A 142 -2.217 25.247 -22.713 1.00 0.00 C ATOM 1090 C GLU A 142 -2.920 26.583 -22.942 1.00 0.00 C ATOM 1091 CB GLU A 142 -2.832 24.169 -23.609 1.00 0.00 C ATOM 1092 O GLU A 142 -4.113 26.718 -22.665 1.00 0.00 O ATOM 1093 CG GLU A 142 -2.588 24.391 -25.095 1.00 0.00 C ATOM 1094 CD GLU A 142 -3.160 23.287 -25.969 1.00 0.00 C ATOM 1095 OE1 GLU A 142 -3.890 22.415 -25.445 1.00 0.00 O ATOM 1096 OE2 GLU A 142 -2.875 23.292 -27.187 1.00 0.00 O ATOM 1097 N GLY A 143 -2.182 27.579 -23.469 1.00 0.00 N ATOM 1098 CA GLY A 143 -2.758 28.882 -23.764 1.00 0.00 C ATOM 1099 C GLY A 143 -3.342 29.566 -22.543 1.00 0.00 C ATOM 1100 O GLY A 143 -4.385 30.217 -22.629 1.00 0.00 O ATOM 1101 N GLY A 144 -2.777 29.290 -21.354 1.00 0.00 N ATOM 1102 CA GLY A 144 -3.245 29.947 -20.144 1.00 0.00 C ATOM 1103 C GLY A 144 -4.395 29.217 -19.476 1.00 0.00 C ATOM 1104 O GLY A 144 -4.892 29.651 -18.435 1.00 0.00 O ATOM 1105 N VAL A 145 -4.936 28.140 -20.164 1.00 0.00 N ATOM 1106 CA VAL A 145 -6.039 27.365 -19.605 1.00 0.00 C ATOM 1107 C VAL A 145 -5.504 26.079 -18.980 1.00 0.00 C ATOM 1108 CB VAL A 145 -7.101 27.035 -20.678 1.00 0.00 C ATOM 1109 O VAL A 145 -4.666 25.395 -19.573 1.00 0.00 O ATOM 1110 CG1 VAL A 145 -8.253 26.236 -20.071 1.00 0.00 C ATOM 1111 CG2 VAL A 145 -7.619 28.316 -21.328 1.00 0.00 C ATOM 1112 N VAL A 146 -5.959 25.837 -17.763 1.00 0.00 N ATOM 1113 CA VAL A 146 -5.574 24.626 -17.045 1.00 0.00 C ATOM 1114 C VAL A 146 -6.593 23.521 -17.311 1.00 0.00 C ATOM 1115 CB VAL A 146 -5.450 24.882 -15.526 1.00 0.00 C ATOM 1116 O VAL A 146 -7.803 23.758 -17.264 1.00 0.00 O ATOM 1117 CG1 VAL A 146 -5.098 23.592 -14.788 1.00 0.00 C ATOM 1118 CG2 VAL A 146 -4.405 25.962 -15.251 1.00 0.00 C ATOM 1119 N SER A 147 -6.150 22.494 -17.818 1.00 0.00 N ATOM 1120 CA SER A 147 -7.007 21.324 -17.979 1.00 0.00 C ATOM 1121 C SER A 147 -6.522 20.161 -17.121 1.00 0.00 C ATOM 1122 CB SER A 147 -7.062 20.898 -19.447 1.00 0.00 C ATOM 1123 O SER A 147 -5.316 19.946 -16.982 1.00 0.00 O ATOM 1124 OG SER A 147 -7.912 19.776 -19.614 1.00 0.00 O ATOM 1125 N CYS A 148 -7.409 19.637 -16.271 1.00 0.00 N ATOM 1126 CA CYS A 148 -7.135 18.448 -15.471 1.00 0.00 C ATOM 1127 C CYS A 148 -7.876 17.237 -16.024 1.00 0.00 C ATOM 1128 CB CYS A 148 -7.534 18.680 -14.014 1.00 0.00 C ATOM 1129 O CYS A 148 -8.941 16.873 -15.523 1.00 0.00 O ATOM 1130 SG CYS A 148 -6.884 17.438 -12.875 1.00 0.00 S ATOM 1131 N ASP A 149 -7.699 16.869 -17.159 1.00 0.00 N ATOM 1132 CA ASP A 149 -8.393 15.760 -17.806 1.00 0.00 C ATOM 1133 C ASP A 149 -7.445 14.590 -18.056 1.00 0.00 C ATOM 1134 CB ASP A 149 -9.023 16.217 -19.124 1.00 0.00 C ATOM 1135 O ASP A 149 -6.548 14.679 -18.896 1.00 0.00 O ATOM 1136 CG ASP A 149 -9.976 15.192 -19.713 1.00 0.00 C ATOM 1137 OD1 ASP A 149 -10.762 15.540 -20.620 1.00 0.00 O ATOM 1138 OD2 ASP A 149 -9.941 14.025 -19.265 1.00 0.00 O ATOM 1139 N CYS A 150 -7.567 13.519 -17.222 1.00 0.00 N ATOM 1140 CA CYS A 150 -6.727 12.334 -17.354 1.00 0.00 C ATOM 1141 C CYS A 150 -7.054 11.573 -18.634 1.00 0.00 C ATOM 1142 CB CYS A 150 -6.900 11.416 -16.145 1.00 0.00 C ATOM 1143 O CYS A 150 -6.244 10.777 -19.112 1.00 0.00 O ATOM 1144 SG CYS A 150 -6.406 12.171 -14.581 1.00 0.00 S ATOM 1145 N LYS A 151 -8.188 11.835 -19.161 1.00 0.00 N ATOM 1146 CA LYS A 151 -8.679 11.063 -20.298 1.00 0.00 C ATOM 1147 C LYS A 151 -8.050 11.543 -21.603 1.00 0.00 C ATOM 1148 CB LYS A 151 -10.204 11.151 -20.388 1.00 0.00 C ATOM 1149 O LYS A 151 -7.990 10.796 -22.581 1.00 0.00 O ATOM 1150 CG LYS A 151 -10.931 10.505 -19.219 1.00 0.00 C ATOM 1151 CD LYS A 151 -12.443 10.620 -19.368 1.00 0.00 C ATOM 1152 CE LYS A 151 -13.172 9.972 -18.199 1.00 0.00 C ATOM 1153 NZ LYS A 151 -14.653 10.132 -18.313 1.00 0.00 N ATOM 1154 N THR A 152 -7.674 12.782 -21.597 1.00 0.00 N ATOM 1155 CA THR A 152 -7.207 13.367 -22.850 1.00 0.00 C ATOM 1156 C THR A 152 -5.688 13.279 -22.954 1.00 0.00 C ATOM 1157 CB THR A 152 -7.649 14.836 -22.979 1.00 0.00 C ATOM 1158 O THR A 152 -5.115 13.562 -24.008 1.00 0.00 O ATOM 1159 CG2 THR A 152 -9.168 14.950 -23.052 1.00 0.00 C ATOM 1160 OG1 THR A 152 -7.180 15.572 -21.843 1.00 0.00 O ATOM 1161 N ILE A 153 -5.064 12.924 -21.810 1.00 0.00 N ATOM 1162 CA ILE A 153 -3.608 12.834 -21.820 1.00 0.00 C ATOM 1163 C ILE A 153 -3.181 11.435 -22.259 1.00 0.00 C ATOM 1164 CB ILE A 153 -3.011 13.167 -20.435 1.00 0.00 C ATOM 1165 O ILE A 153 -3.826 10.444 -21.909 1.00 0.00 O ATOM 1166 CG1 ILE A 153 -3.390 14.593 -20.018 1.00 0.00 C ATOM 1167 CG2 ILE A 153 -1.490 12.986 -20.444 1.00 0.00 C ATOM 1168 CD1 ILE A 153 -2.744 15.679 -20.868 1.00 0.00 C ATOM 1169 N THR A 154 -2.270 11.363 -23.110 1.00 0.00 N ATOM 1170 CA THR A 154 -1.713 10.090 -23.553 1.00 0.00 C ATOM 1171 C THR A 154 -1.160 9.301 -22.370 1.00 0.00 C ATOM 1172 CB THR A 154 -0.603 10.299 -24.599 1.00 0.00 C ATOM 1173 O THR A 154 -0.336 9.812 -21.607 1.00 0.00 O ATOM 1174 CG2 THR A 154 -0.102 8.965 -25.144 1.00 0.00 C ATOM 1175 OG1 THR A 154 -1.117 11.082 -25.683 1.00 0.00 O ATOM 1176 N CYS A 155 -1.859 8.148 -22.092 1.00 0.00 N ATOM 1177 CA CYS A 155 -1.409 7.282 -21.008 1.00 0.00 C ATOM 1178 C CYS A 155 -0.060 6.653 -21.338 1.00 0.00 C ATOM 1179 CB CYS A 155 -2.439 6.187 -20.734 1.00 0.00 C ATOM 1180 O CYS A 155 0.086 5.991 -22.367 1.00 0.00 O ATOM 1181 SG CYS A 155 -4.010 6.809 -20.095 1.00 0.00 S ATOM 1182 N ASN A 156 0.893 7.176 -20.743 1.00 0.00 N ATOM 1183 CA ASN A 156 2.201 6.536 -20.836 1.00 0.00 C ATOM 1184 C ASN A 156 2.611 5.904 -19.509 1.00 0.00 C ATOM 1185 CB ASN A 156 3.259 7.541 -21.294 1.00 0.00 C ATOM 1186 O ASN A 156 1.841 5.916 -18.546 1.00 0.00 O ATOM 1187 CG ASN A 156 3.393 8.721 -20.351 1.00 0.00 C ATOM 1188 ND2 ASN A 156 3.554 9.913 -20.912 1.00 0.00 N ATOM 1189 OD1 ASN A 156 3.352 8.561 -19.128 1.00 0.00 O ATOM 1190 N GLU A 157 3.624 5.165 -19.538 1.00 0.00 N ATOM 1191 CA GLU A 157 4.078 4.402 -18.379 1.00 0.00 C ATOM 1192 C GLU A 157 4.196 5.291 -17.145 1.00 0.00 C ATOM 1193 CB GLU A 157 5.421 3.727 -18.672 1.00 0.00 C ATOM 1194 O GLU A 157 4.169 4.799 -16.014 1.00 0.00 O ATOM 1195 CG GLU A 157 5.336 2.611 -19.703 1.00 0.00 C ATOM 1196 CD GLU A 157 6.670 1.925 -19.955 1.00 0.00 C ATOM 1197 OE1 GLU A 157 7.660 2.250 -19.261 1.00 0.00 O ATOM 1198 OE2 GLU A 157 6.725 1.058 -20.855 1.00 0.00 O ATOM 1199 N ASP A 158 4.203 6.614 -17.357 1.00 0.00 N ATOM 1200 CA ASP A 158 4.344 7.540 -16.237 1.00 0.00 C ATOM 1201 C ASP A 158 2.979 8.001 -15.731 1.00 0.00 C ATOM 1202 CB ASP A 158 5.190 8.748 -16.643 1.00 0.00 C ATOM 1203 O ASP A 158 2.882 8.629 -14.675 1.00 0.00 O ATOM 1204 CG ASP A 158 6.638 8.390 -16.927 1.00 0.00 C ATOM 1205 OD1 ASP A 158 7.251 8.999 -17.830 1.00 0.00 O ATOM 1206 OD2 ASP A 158 7.169 7.487 -16.244 1.00 0.00 O ATOM 1207 N HIS A 159 2.048 7.688 -16.589 1.00 0.00 N ATOM 1208 CA HIS A 159 0.697 8.104 -16.230 1.00 0.00 C ATOM 1209 C HIS A 159 0.098 7.180 -15.176 1.00 0.00 C ATOM 1210 CB HIS A 159 -0.199 8.139 -17.469 1.00 0.00 C ATOM 1211 O HIS A 159 0.148 5.956 -15.317 1.00 0.00 O ATOM 1212 CG HIS A 159 -1.463 8.914 -17.273 1.00 0.00 C ATOM 1213 CD2 HIS A 159 -1.859 10.110 -17.769 1.00 0.00 C ATOM 1214 ND1 HIS A 159 -2.495 8.466 -16.477 1.00 0.00 N ATOM 1215 CE1 HIS A 159 -3.474 9.356 -16.493 1.00 0.00 C ATOM 1216 NE2 HIS A 159 -3.113 10.363 -17.270 1.00 0.00 N ATOM 1217 N PRO A 160 -0.393 7.607 -14.171 1.00 0.00 N ATOM 1218 CA PRO A 160 -0.882 6.789 -13.059 1.00 0.00 C ATOM 1219 C PRO A 160 -2.041 5.880 -13.461 1.00 0.00 C ATOM 1220 CB PRO A 160 -1.334 7.828 -12.030 1.00 0.00 C ATOM 1221 O PRO A 160 -2.326 4.896 -12.773 1.00 0.00 O ATOM 1222 CG PRO A 160 -1.619 9.058 -12.828 1.00 0.00 C ATOM 1223 CD PRO A 160 -0.678 9.096 -13.998 1.00 0.00 C ATOM 1224 N CYS A 161 -2.737 6.193 -14.475 1.00 0.00 N ATOM 1225 CA CYS A 161 -3.885 5.408 -14.913 1.00 0.00 C ATOM 1226 C CYS A 161 -3.470 4.357 -15.936 1.00 0.00 C ATOM 1227 CB CYS A 161 -4.960 6.317 -15.509 1.00 0.00 C ATOM 1228 O CYS A 161 -4.312 3.621 -16.453 1.00 0.00 O ATOM 1229 SG CYS A 161 -5.656 7.493 -14.328 1.00 0.00 S ATOM 1230 N TYR A 162 -2.132 4.465 -16.183 1.00 0.00 N ATOM 1231 CA TYR A 162 -1.573 3.516 -17.140 1.00 0.00 C ATOM 1232 C TYR A 162 -1.452 2.127 -16.525 1.00 0.00 C ATOM 1233 CB TYR A 162 -0.201 3.992 -17.629 1.00 0.00 C ATOM 1234 O TYR A 162 -0.908 1.972 -15.429 1.00 0.00 O ATOM 1235 CG TYR A 162 0.469 3.033 -18.583 1.00 0.00 C ATOM 1236 CD1 TYR A 162 1.424 2.124 -18.131 1.00 0.00 C ATOM 1237 CD2 TYR A 162 0.151 3.035 -19.936 1.00 0.00 C ATOM 1238 CE1 TYR A 162 2.046 1.240 -19.007 1.00 0.00 C ATOM 1239 CE2 TYR A 162 0.766 2.155 -20.821 1.00 0.00 C ATOM 1240 OH TYR A 162 2.323 0.390 -21.219 1.00 0.00 O ATOM 1241 CZ TYR A 162 1.710 1.263 -20.348 1.00 0.00 C ATOM 1242 N HIS A 163 -2.235 1.147 -17.118 1.00 0.00 N ATOM 1243 CA HIS A 163 -2.129 -0.243 -16.689 1.00 0.00 C ATOM 1244 C HIS A 163 -1.553 -1.119 -17.797 1.00 0.00 C ATOM 1245 CB HIS A 163 -3.496 -0.776 -16.256 1.00 0.00 C ATOM 1246 O HIS A 163 -1.953 -1.002 -18.957 1.00 0.00 O ATOM 1247 CG HIS A 163 -4.058 -0.081 -15.057 1.00 0.00 C ATOM 1248 CD2 HIS A 163 -5.018 0.867 -14.948 1.00 0.00 C ATOM 1249 ND1 HIS A 163 -3.625 -0.342 -13.775 1.00 0.00 N ATOM 1250 CE1 HIS A 163 -4.297 0.419 -12.926 1.00 0.00 C ATOM 1251 NE2 HIS A 163 -5.148 1.162 -13.613 1.00 0.00 N ATOM 1252 N SER A 164 -0.416 -1.652 -17.433 1.00 0.00 N ATOM 1253 CA SER A 164 0.122 -2.646 -18.356 1.00 0.00 C ATOM 1254 C SER A 164 -0.175 -4.063 -17.877 1.00 0.00 C ATOM 1255 CB SER A 164 1.630 -2.462 -18.523 1.00 0.00 C ATOM 1256 O SER A 164 -0.055 -4.360 -16.687 1.00 0.00 O ATOM 1257 OG SER A 164 2.304 -2.686 -17.297 1.00 0.00 O ATOM 1258 N TYR A 165 -0.841 -4.799 -18.656 1.00 0.00 N ATOM 1259 CA TYR A 165 -1.123 -6.182 -18.287 1.00 0.00 C ATOM 1260 C TYR A 165 -0.783 -7.132 -19.429 1.00 0.00 C ATOM 1261 CB TYR A 165 -2.594 -6.345 -17.894 1.00 0.00 C ATOM 1262 O TYR A 165 -0.643 -6.705 -20.578 1.00 0.00 O ATOM 1263 CG TYR A 165 -3.559 -6.039 -19.013 1.00 0.00 C ATOM 1264 CD1 TYR A 165 -3.953 -4.730 -19.282 1.00 0.00 C ATOM 1265 CD2 TYR A 165 -4.080 -7.058 -19.804 1.00 0.00 C ATOM 1266 CE1 TYR A 165 -4.843 -4.444 -20.312 1.00 0.00 C ATOM 1267 CE2 TYR A 165 -4.971 -6.783 -20.836 1.00 0.00 C ATOM 1268 OH TYR A 165 -6.228 -5.197 -22.103 1.00 0.00 O ATOM 1269 CZ TYR A 165 -5.346 -5.475 -21.082 1.00 0.00 C ATOM 1270 N GLU A 166 -0.437 -8.271 -19.075 1.00 0.00 N ATOM 1271 CA GLU A 166 -0.092 -9.311 -20.039 1.00 0.00 C ATOM 1272 C GLU A 166 -1.292 -10.203 -20.342 1.00 0.00 C ATOM 1273 CB GLU A 166 1.075 -10.158 -19.523 1.00 0.00 C ATOM 1274 O GLU A 166 -1.951 -10.699 -19.426 1.00 0.00 O ATOM 1275 CG GLU A 166 1.667 -11.091 -20.569 1.00 0.00 C ATOM 1276 CD GLU A 166 2.944 -11.776 -20.108 1.00 0.00 C ATOM 1277 OE1 GLU A 166 3.581 -11.289 -19.146 1.00 0.00 O ATOM 1278 OE2 GLU A 166 3.310 -12.808 -20.713 1.00 0.00 O ATOM 1279 N GLU A 167 -1.701 -10.268 -21.599 1.00 0.00 N ATOM 1280 CA GLU A 167 -2.770 -11.135 -22.087 1.00 0.00 C ATOM 1281 C GLU A 167 -2.310 -11.956 -23.288 1.00 0.00 C ATOM 1282 CB GLU A 167 -4.006 -10.310 -22.455 1.00 0.00 C ATOM 1283 O GLU A 167 -1.837 -11.400 -24.282 1.00 0.00 O ATOM 1284 CG GLU A 167 -5.232 -11.150 -22.780 1.00 0.00 C ATOM 1285 CD GLU A 167 -6.476 -10.318 -23.048 1.00 0.00 C ATOM 1286 OE1 GLU A 167 -6.367 -9.075 -23.139 1.00 0.00 O ATOM 1287 OE2 GLU A 167 -7.570 -10.915 -23.165 1.00 0.00 O ATOM 1288 N ASP A 168 -2.308 -13.235 -23.226 1.00 0.00 N ATOM 1289 CA ASP A 168 -1.919 -14.168 -24.278 1.00 0.00 C ATOM 1290 C ASP A 168 -0.472 -13.938 -24.708 1.00 0.00 C ATOM 1291 CB ASP A 168 -2.852 -14.039 -25.483 1.00 0.00 C ATOM 1292 O ASP A 168 -0.162 -13.963 -25.901 1.00 0.00 O ATOM 1293 CG ASP A 168 -4.284 -14.437 -25.170 1.00 0.00 C ATOM 1294 OD1 ASP A 168 -5.222 -13.831 -25.730 1.00 0.00 O ATOM 1295 OD2 ASP A 168 -4.475 -15.363 -24.352 1.00 0.00 O ATOM 1296 N GLY A 169 0.378 -13.615 -23.661 1.00 0.00 N ATOM 1297 CA GLY A 169 1.802 -13.483 -23.928 1.00 0.00 C ATOM 1298 C GLY A 169 2.181 -12.123 -24.482 1.00 0.00 C ATOM 1299 O GLY A 169 3.340 -11.889 -24.830 1.00 0.00 O ATOM 1300 N VAL A 170 1.173 -11.220 -24.645 1.00 0.00 N ATOM 1301 CA VAL A 170 1.451 -9.891 -25.180 1.00 0.00 C ATOM 1302 C VAL A 170 1.131 -8.832 -24.128 1.00 0.00 C ATOM 1303 CB VAL A 170 0.648 -9.620 -26.472 1.00 0.00 C ATOM 1304 O VAL A 170 0.124 -8.932 -23.423 1.00 0.00 O ATOM 1305 CG1 VAL A 170 0.954 -8.226 -27.016 1.00 0.00 C ATOM 1306 CG2 VAL A 170 0.952 -10.686 -27.523 1.00 0.00 C ATOM 1307 N THR A 171 2.053 -7.976 -23.977 1.00 0.00 N ATOM 1308 CA THR A 171 1.846 -6.867 -23.053 1.00 0.00 C ATOM 1309 C THR A 171 0.857 -5.859 -23.631 1.00 0.00 C ATOM 1310 CB THR A 171 3.173 -6.158 -22.725 1.00 0.00 C ATOM 1311 O THR A 171 1.042 -5.370 -24.747 1.00 0.00 O ATOM 1312 CG2 THR A 171 2.958 -5.020 -21.732 1.00 0.00 C ATOM 1313 OG1 THR A 171 4.087 -7.105 -22.158 1.00 0.00 O ATOM 1314 N LYS A 172 -0.220 -5.669 -22.883 1.00 0.00 N ATOM 1315 CA LYS A 172 -1.215 -4.669 -23.260 1.00 0.00 C ATOM 1316 C LYS A 172 -1.232 -3.510 -22.267 1.00 0.00 C ATOM 1317 CB LYS A 172 -2.604 -5.301 -23.351 1.00 0.00 C ATOM 1318 O LYS A 172 -0.846 -3.673 -21.107 1.00 0.00 O ATOM 1319 CG LYS A 172 -2.720 -6.393 -24.405 1.00 0.00 C ATOM 1320 CD LYS A 172 -4.154 -6.886 -24.543 1.00 0.00 C ATOM 1321 CE LYS A 172 -4.280 -7.941 -25.634 1.00 0.00 C ATOM 1322 NZ LYS A 172 -5.700 -8.358 -25.841 1.00 0.00 N ATOM 1323 N SER A 173 -1.325 -2.368 -22.806 1.00 0.00 N ATOM 1324 CA SER A 173 -1.442 -1.178 -21.969 1.00 0.00 C ATOM 1325 C SER A 173 -2.815 -0.530 -22.119 1.00 0.00 C ATOM 1326 CB SER A 173 -0.350 -0.167 -22.320 1.00 0.00 C ATOM 1327 O SER A 173 -3.418 -0.584 -23.193 1.00 0.00 O ATOM 1328 OG SER A 173 -0.430 0.207 -23.684 1.00 0.00 O ATOM 1329 N ASP A 174 -3.338 -0.380 -21.075 1.00 0.00 N ATOM 1330 CA ASP A 174 -4.630 0.300 -21.062 1.00 0.00 C ATOM 1331 C ASP A 174 -4.627 1.467 -20.077 1.00 0.00 C ATOM 1332 CB ASP A 174 -5.749 -0.682 -20.712 1.00 0.00 C ATOM 1333 O ASP A 174 -3.834 1.488 -19.134 1.00 0.00 O ATOM 1334 CG ASP A 174 -7.118 -0.209 -21.168 1.00 0.00 C ATOM 1335 OD1 ASP A 174 -8.137 -0.811 -20.767 1.00 0.00 O ATOM 1336 OD2 ASP A 174 -7.178 0.774 -21.938 1.00 0.00 O ATOM 1337 N CYS A 175 -5.254 2.474 -20.569 1.00 0.00 N ATOM 1338 CA CYS A 175 -5.511 3.614 -19.696 1.00 0.00 C ATOM 1339 C CYS A 175 -6.886 3.506 -19.049 1.00 0.00 C ATOM 1340 CB CYS A 175 -5.407 4.922 -20.479 1.00 0.00 C ATOM 1341 O CYS A 175 -7.906 3.530 -19.740 1.00 0.00 O ATOM 1342 SG CYS A 175 -5.469 6.399 -19.441 1.00 0.00 S ATOM 1343 N ASP A 176 -6.926 3.117 -17.897 1.00 0.00 N ATOM 1344 CA ASP A 176 -8.216 2.947 -17.236 1.00 0.00 C ATOM 1345 C ASP A 176 -8.579 4.181 -16.413 1.00 0.00 C ATOM 1346 CB ASP A 176 -8.202 1.705 -16.343 1.00 0.00 C ATOM 1347 O ASP A 176 -8.390 4.199 -15.195 1.00 0.00 O ATOM 1348 CG ASP A 176 -9.574 1.352 -15.795 1.00 0.00 C ATOM 1349 OD1 ASP A 176 -9.681 0.413 -14.978 1.00 0.00 O ATOM 1350 OD2 ASP A 176 -10.557 2.018 -16.187 1.00 0.00 O ATOM 1351 N CYS A 177 -8.999 5.207 -17.129 1.00 0.00 N ATOM 1352 CA CYS A 177 -9.425 6.426 -16.450 1.00 0.00 C ATOM 1353 C CYS A 177 -10.930 6.422 -16.214 1.00 0.00 C ATOM 1354 CB CYS A 177 -9.030 7.658 -17.264 1.00 0.00 C ATOM 1355 O CYS A 177 -11.489 7.406 -15.726 1.00 0.00 O ATOM 1356 SG CYS A 177 -7.251 7.814 -17.535 1.00 0.00 S ATOM 1357 N GLU A 178 -11.529 5.450 -16.815 1.00 0.00 N ATOM 1358 CA GLU A 178 -12.986 5.385 -16.754 1.00 0.00 C ATOM 1359 C GLU A 178 -13.473 5.263 -15.313 1.00 0.00 C ATOM 1360 CB GLU A 178 -13.508 4.211 -17.586 1.00 0.00 C ATOM 1361 O GLU A 178 -14.584 5.686 -14.990 1.00 0.00 O ATOM 1362 CG GLU A 178 -13.379 4.417 -19.089 1.00 0.00 C ATOM 1363 CD GLU A 178 -13.985 3.285 -19.903 1.00 0.00 C ATOM 1364 OE1 GLU A 178 -14.377 2.254 -19.312 1.00 0.00 O ATOM 1365 OE2 GLU A 178 -14.069 3.431 -21.143 1.00 0.00 O ATOM 1366 N HIS A 179 -12.602 4.539 -14.596 1.00 0.00 N ATOM 1367 CA HIS A 179 -13.083 4.370 -13.230 1.00 0.00 C ATOM 1368 C HIS A 179 -12.913 5.654 -12.423 1.00 0.00 C ATOM 1369 CB HIS A 179 -12.350 3.217 -12.542 1.00 0.00 C ATOM 1370 O HIS A 179 -13.259 5.699 -11.241 1.00 0.00 O ATOM 1371 CG HIS A 179 -12.672 1.874 -13.117 1.00 0.00 C ATOM 1372 CD2 HIS A 179 -11.913 1.007 -13.828 1.00 0.00 C ATOM 1373 ND1 HIS A 179 -13.911 1.286 -12.986 1.00 0.00 N ATOM 1374 CE1 HIS A 179 -13.900 0.111 -13.593 1.00 0.00 C ATOM 1375 NE2 HIS A 179 -12.700 -0.082 -14.113 1.00 0.00 N ATOM 1376 N SER A 180 -12.761 6.762 -13.153 1.00 0.00 N ATOM 1377 CA SER A 180 -12.625 8.074 -12.529 1.00 0.00 C ATOM 1378 C SER A 180 -13.967 8.797 -12.465 1.00 0.00 C ATOM 1379 CB SER A 180 -11.612 8.928 -13.291 1.00 0.00 C ATOM 1380 O SER A 180 -14.740 8.767 -13.424 1.00 0.00 O ATOM 1381 OG SER A 180 -12.114 9.284 -14.568 1.00 0.00 O ATOM 1382 N PRO A 181 -14.719 8.802 -11.393 1.00 0.00 N ATOM 1383 CA PRO A 181 -15.790 9.799 -11.316 1.00 0.00 C ATOM 1384 C PRO A 181 -15.334 11.190 -11.748 1.00 0.00 C ATOM 1385 CB PRO A 181 -16.178 9.786 -9.836 1.00 0.00 C ATOM 1386 O PRO A 181 -14.337 11.704 -11.233 1.00 0.00 O ATOM 1387 CG PRO A 181 -14.965 9.275 -9.127 1.00 0.00 C ATOM 1388 CD PRO A 181 -14.184 8.416 -10.079 1.00 0.00 C ATOM 1389 N GLY A 182 -15.240 11.453 -13.029 1.00 0.00 N ATOM 1390 CA GLY A 182 -15.037 12.822 -13.476 1.00 0.00 C ATOM 1391 C GLY A 182 -15.937 13.820 -12.770 1.00 0.00 C ATOM 1392 O GLY A 182 -16.871 13.431 -12.066 1.00 0.00 O ATOM 1393 N PRO A 183 -15.396 14.822 -12.165 1.00 0.00 N ATOM 1394 CA PRO A 183 -16.219 15.888 -11.589 1.00 0.00 C ATOM 1395 C PRO A 183 -17.636 15.913 -12.158 1.00 0.00 C ATOM 1396 CB PRO A 183 -15.458 17.162 -11.964 1.00 0.00 C ATOM 1397 O PRO A 183 -17.838 15.604 -13.335 1.00 0.00 O ATOM 1398 CG PRO A 183 -14.695 16.803 -13.198 1.00 0.00 C ATOM 1399 CD PRO A 183 -14.401 15.330 -13.164 1.00 0.00 C ATOM 1400 N SER A 184 -18.521 15.085 -11.531 1.00 0.00 N ATOM 1401 CA SER A 184 -19.918 15.360 -11.852 1.00 0.00 C ATOM 1402 C SER A 184 -20.093 16.779 -12.385 1.00 0.00 C ATOM 1403 CB SER A 184 -20.801 15.157 -10.620 1.00 0.00 C ATOM 1404 O SER A 184 -19.543 17.730 -11.826 1.00 0.00 O ATOM 1405 OG SER A 184 -20.375 15.985 -9.553 1.00 0.00 O ATOM 1406 N GLU A 185 -19.658 16.958 -13.662 1.00 0.00 N ATOM 1407 CA GLU A 185 -20.167 18.200 -14.237 1.00 0.00 C ATOM 1408 C GLU A 185 -21.492 18.603 -13.597 1.00 0.00 C ATOM 1409 CB GLU A 185 -20.336 18.061 -15.752 1.00 0.00 C ATOM 1410 O GLU A 185 -22.450 17.827 -13.598 1.00 0.00 O ATOM 1411 CG GLU A 185 -19.029 17.836 -16.499 1.00 0.00 C ATOM 1412 CD GLU A 185 -18.110 19.046 -16.478 1.00 0.00 C ATOM 1413 OE1 GLU A 185 -18.546 20.132 -16.032 1.00 0.00 O ATOM 1414 OE2 GLU A 185 -16.944 18.908 -16.911 1.00 0.00 O ATOM 1415 N HIS A 186 -21.419 18.961 -12.324 1.00 0.00 N ATOM 1416 CA HIS A 186 -22.672 19.612 -11.958 1.00 0.00 C ATOM 1417 C HIS A 186 -23.102 20.617 -13.022 1.00 0.00 C ATOM 1418 CB HIS A 186 -22.539 20.307 -10.602 1.00 0.00 C ATOM 1419 O HIS A 186 -22.311 21.471 -13.430 1.00 0.00 O ATOM 1420 CG HIS A 186 -22.402 19.359 -9.453 1.00 0.00 C ATOM 1421 CD2 HIS A 186 -21.354 19.097 -8.637 1.00 0.00 C ATOM 1422 ND1 HIS A 186 -23.431 18.543 -9.034 1.00 0.00 N ATOM 1423 CE1 HIS A 186 -23.020 17.819 -8.007 1.00 0.00 C ATOM 1424 NE2 HIS A 186 -21.763 18.136 -7.746 1.00 0.00 N ATOM 1425 N HIS A 187 -23.592 20.072 -14.139 1.00 0.00 N ATOM 1426 CA HIS A 187 -24.308 20.983 -15.025 1.00 0.00 C ATOM 1427 C HIS A 187 -24.996 22.092 -14.235 1.00 0.00 C ATOM 1428 CB HIS A 187 -25.335 20.219 -15.862 1.00 0.00 C ATOM 1429 O HIS A 187 -25.860 21.819 -13.399 1.00 0.00 O ATOM 1430 CG HIS A 187 -24.723 19.267 -16.840 1.00 0.00 C ATOM 1431 CD2 HIS A 187 -24.703 17.913 -16.868 1.00 0.00 C ATOM 1432 ND1 HIS A 187 -24.026 19.687 -17.952 1.00 0.00 N ATOM 1433 CE1 HIS A 187 -23.603 18.630 -18.624 1.00 0.00 C ATOM 1434 NE2 HIS A 187 -24.000 17.541 -17.988 1.00 0.00 N ATOM 1435 N HIS A 188 -24.187 22.915 -13.610 1.00 0.00 N ATOM 1436 CA HIS A 188 -24.905 24.094 -13.140 1.00 0.00 C ATOM 1437 C HIS A 188 -25.814 24.656 -14.228 1.00 0.00 C ATOM 1438 CB HIS A 188 -23.923 25.168 -12.669 1.00 0.00 C ATOM 1439 O HIS A 188 -25.380 24.849 -15.366 1.00 0.00 O ATOM 1440 CG HIS A 188 -23.207 24.814 -11.404 1.00 0.00 C ATOM 1441 CD2 HIS A 188 -21.913 24.489 -11.176 1.00 0.00 C ATOM 1442 ND1 HIS A 188 -23.839 24.765 -10.181 1.00 0.00 N ATOM 1443 CE1 HIS A 188 -22.961 24.425 -9.252 1.00 0.00 C ATOM 1444 NE2 HIS A 188 -21.785 24.251 -9.830 1.00 0.00 N ATOM 1445 N HIS A 189 -26.993 24.045 -14.412 1.00 0.00 N ATOM 1446 CA HIS A 189 -28.031 24.708 -15.193 1.00 0.00 C ATOM 1447 C HIS A 189 -28.031 26.213 -14.944 1.00 0.00 C ATOM 1448 CB HIS A 189 -29.406 24.122 -14.865 1.00 0.00 C ATOM 1449 O HIS A 189 -27.980 26.656 -13.795 1.00 0.00 O ATOM 1450 CG HIS A 189 -29.586 22.714 -15.335 1.00 0.00 C ATOM 1451 CD2 HIS A 189 -29.619 21.546 -14.652 1.00 0.00 C ATOM 1452 ND1 HIS A 189 -29.755 22.390 -16.664 1.00 0.00 N ATOM 1453 CE1 HIS A 189 -29.887 21.079 -16.778 1.00 0.00 C ATOM 1454 NE2 HIS A 189 -29.808 20.543 -15.572 1.00 0.00 N ATOM 1455 N HIS A 190 -27.150 26.911 -15.639 1.00 0.00 N ATOM 1456 CA HIS A 190 -27.271 28.363 -15.688 1.00 0.00 C ATOM 1457 C HIS A 190 -28.733 28.796 -15.667 1.00 0.00 C ATOM 1458 CB HIS A 190 -26.577 28.917 -16.934 1.00 0.00 C ATOM 1459 O HIS A 190 -29.546 28.288 -16.443 1.00 0.00 O ATOM 1460 CG HIS A 190 -25.087 28.794 -16.896 1.00 0.00 C ATOM 1461 CD2 HIS A 190 -24.243 27.997 -17.592 1.00 0.00 C ATOM 1462 ND1 HIS A 190 -24.299 29.553 -16.058 1.00 0.00 N ATOM 1463 CE1 HIS A 190 -23.030 29.227 -16.242 1.00 0.00 C ATOM 1464 NE2 HIS A 190 -22.969 28.285 -17.168 1.00 0.00 N ATOM 1465 N HIS A 191 -29.301 28.820 -14.496 1.00 0.00 N ATOM 1466 CA HIS A 191 -30.497 29.651 -14.423 1.00 0.00 C ATOM 1467 C HIS A 191 -30.240 31.039 -15.001 1.00 0.00 C ATOM 1468 CB HIS A 191 -30.981 29.766 -12.976 1.00 0.00 C ATOM 1469 O HIS A 191 -29.144 31.584 -14.855 1.00 0.00 O ATOM 1470 CG HIS A 191 -31.644 28.528 -12.465 1.00 0.00 C ATOM 1471 CD2 HIS A 191 -31.230 27.603 -11.566 1.00 0.00 C ATOM 1472 ND1 HIS A 191 -32.892 28.123 -12.888 1.00 0.00 N ATOM 1473 CE1 HIS A 191 -33.217 27.000 -12.270 1.00 0.00 C ATOM 1474 NE2 HIS A 191 -32.226 26.664 -11.462 1.00 0.00 N TER 1475 HIS A 191 ENDMDL END ================================================ FILE: alphafold/relax/testdata/with_violations.pdb ================================================ MODEL 0 ATOM 1 N SER A 1 23.291 1.505 0.613 1.00 6.08 N ATOM 2 CA SER A 1 22.518 0.883 -0.457 1.00 6.08 C ATOM 3 C SER A 1 21.020 1.015 -0.206 1.00 6.08 C ATOM 4 CB SER A 1 22.891 -0.593 -0.601 1.00 6.08 C ATOM 5 O SER A 1 20.593 1.246 0.928 1.00 6.08 O ATOM 6 OG SER A 1 22.364 -1.352 0.474 1.00 6.08 O ATOM 7 N PHE A 2 20.180 1.317 -1.280 1.00 6.08 N ATOM 8 CA PHE A 2 18.725 1.321 -1.187 1.00 6.08 C ATOM 9 C PHE A 2 18.244 0.288 -0.175 1.00 6.08 C ATOM 10 CB PHE A 2 18.097 1.046 -2.557 1.00 6.08 C ATOM 11 O PHE A 2 17.437 0.600 0.703 1.00 6.08 O ATOM 12 CG PHE A 2 16.601 0.880 -2.517 1.00 6.08 C ATOM 13 CD1 PHE A 2 15.765 1.989 -2.519 1.00 6.08 C ATOM 14 CD2 PHE A 2 16.033 -0.386 -2.478 1.00 6.08 C ATOM 15 CE1 PHE A 2 14.380 1.838 -2.482 1.00 6.08 C ATOM 16 CE2 PHE A 2 14.650 -0.545 -2.441 1.00 6.08 C ATOM 17 CZ PHE A 2 13.826 0.569 -2.442 1.00 6.08 C ATOM 18 N GLU A 3 18.695 -0.904 -0.178 1.00 6.08 N ATOM 19 CA GLU A 3 18.305 -2.028 0.668 1.00 6.08 C ATOM 20 C GLU A 3 18.535 -1.714 2.144 1.00 6.08 C ATOM 21 CB GLU A 3 19.073 -3.291 0.273 1.00 6.08 C ATOM 22 O GLU A 3 17.664 -1.961 2.980 1.00 6.08 O ATOM 23 CG GLU A 3 18.413 -4.088 -0.843 1.00 6.08 C ATOM 24 CD GLU A 3 19.408 -4.840 -1.713 1.00 6.08 C ATOM 25 OE1 GLU A 3 18.977 -5.585 -2.622 1.00 6.08 O ATOM 26 OE2 GLU A 3 20.628 -4.683 -1.482 1.00 6.08 O ATOM 27 N GLU A 4 19.823 -1.305 2.459 1.00 6.08 N ATOM 28 CA GLU A 4 20.190 -1.047 3.848 1.00 6.08 C ATOM 29 C GLU A 4 19.315 0.044 4.456 1.00 6.08 C ATOM 30 CB GLU A 4 21.666 -0.656 3.950 1.00 6.08 C ATOM 31 O GLU A 4 18.868 -0.076 5.599 1.00 6.08 O ATOM 32 CG GLU A 4 22.621 -1.841 3.913 1.00 6.08 C ATOM 33 CD GLU A 4 24.085 -1.434 3.973 1.00 6.08 C ATOM 34 OE1 GLU A 4 24.957 -2.324 4.094 1.00 6.08 O ATOM 35 OE2 GLU A 4 24.361 -0.216 3.899 1.00 6.08 O ATOM 36 N GLN A 5 19.061 1.102 3.590 1.00 6.08 N ATOM 37 CA GLN A 5 18.207 2.189 4.056 1.00 6.08 C ATOM 38 C GLN A 5 16.771 1.714 4.255 1.00 6.08 C ATOM 39 CB GLN A 5 18.241 3.359 3.071 1.00 6.08 C ATOM 40 O GLN A 5 16.113 2.097 5.225 1.00 6.08 O ATOM 41 CG GLN A 5 19.395 4.326 3.304 1.00 6.08 C ATOM 42 CD GLN A 5 19.384 5.496 2.338 1.00 6.08 C ATOM 43 NE2 GLN A 5 20.565 6.022 2.031 1.00 6.08 N ATOM 44 OE1 GLN A 5 18.323 5.922 1.871 1.00 6.08 O ATOM 45 N PHE A 6 16.354 0.831 3.208 1.00 5.36 N ATOM 46 CA PHE A 6 15.014 0.260 3.283 1.00 5.36 C ATOM 47 C PHE A 6 14.844 -0.555 4.559 1.00 5.36 C ATOM 48 CB PHE A 6 14.732 -0.616 2.059 1.00 5.36 C ATOM 49 O PHE A 6 13.859 -0.388 5.282 1.00 5.36 O ATOM 50 CG PHE A 6 13.331 -1.164 2.014 1.00 5.36 C ATOM 51 CD1 PHE A 6 12.278 -0.379 1.561 1.00 5.36 C ATOM 52 CD2 PHE A 6 13.068 -2.464 2.424 1.00 5.36 C ATOM 53 CE1 PHE A 6 10.980 -0.884 1.518 1.00 5.36 C ATOM 54 CE2 PHE A 6 11.774 -2.975 2.384 1.00 5.36 C ATOM 55 CZ PHE A 6 10.731 -2.183 1.932 1.00 5.36 C ATOM 56 N ILE A 7 15.772 -1.382 4.937 1.00 6.08 N ATOM 57 CA ILE A 7 15.726 -2.220 6.131 1.00 6.08 C ATOM 58 C ILE A 7 15.811 -1.345 7.379 1.00 6.08 C ATOM 59 CB ILE A 7 16.864 -3.266 6.130 1.00 6.08 C ATOM 60 O ILE A 7 15.052 -1.538 8.332 1.00 6.08 O ATOM 61 CG1 ILE A 7 16.652 -4.286 5.006 1.00 6.08 C ATOM 62 CG2 ILE A 7 16.957 -3.962 7.491 1.00 6.08 C ATOM 63 CD1 ILE A 7 17.837 -5.214 4.781 1.00 6.08 C ATOM 64 N LYS A 8 16.750 -0.406 7.403 1.00 6.08 N ATOM 65 CA LYS A 8 16.953 0.493 8.535 1.00 6.08 C ATOM 66 C LYS A 8 15.689 1.294 8.836 1.00 6.08 C ATOM 67 CB LYS A 8 18.122 1.442 8.265 1.00 6.08 C ATOM 68 O LYS A 8 15.304 1.443 9.997 1.00 6.08 O ATOM 69 CG LYS A 8 18.564 2.242 9.481 1.00 6.08 C ATOM 70 CD LYS A 8 19.735 3.159 9.151 1.00 6.08 C ATOM 71 CE LYS A 8 20.102 4.046 10.333 1.00 6.08 C ATOM 72 NZ LYS A 8 21.192 5.007 9.987 1.00 6.08 N ATOM 73 N ASN A 9 14.988 1.804 7.750 1.00 6.08 N ATOM 74 CA ASN A 9 13.799 2.629 7.937 1.00 6.08 C ATOM 75 C ASN A 9 12.593 1.788 8.349 1.00 6.08 C ATOM 76 CB ASN A 9 13.486 3.416 6.663 1.00 6.08 C ATOM 77 O ASN A 9 11.581 2.327 8.801 1.00 6.08 O ATOM 78 CG ASN A 9 14.404 4.608 6.473 1.00 6.08 C ATOM 79 ND2 ASN A 9 14.484 5.105 5.244 1.00 6.08 N ATOM 80 OD1 ASN A 9 15.036 5.078 7.423 1.00 6.08 O ATOM 81 N ASN A 10 12.800 0.438 8.337 1.00 6.08 N ATOM 82 CA ASN A 10 11.572 -0.311 8.581 1.00 6.08 C ATOM 83 C ASN A 10 11.753 -1.335 9.699 1.00 6.08 C ATOM 84 CB ASN A 10 11.100 -1.002 7.300 1.00 6.08 C ATOM 85 O ASN A 10 10.808 -2.039 10.060 1.00 6.08 O ATOM 86 CG ASN A 10 10.549 -0.025 6.280 1.00 6.08 C ATOM 87 ND2 ASN A 10 11.285 0.176 5.193 1.00 6.08 N ATOM 88 OD1 ASN A 10 9.471 0.545 6.467 1.00 6.08 O ATOM 89 N SER A 11 12.959 -1.512 10.211 1.00 6.08 N ATOM 90 CA SER A 11 13.197 -2.465 11.291 1.00 6.08 C ATOM 91 C SER A 11 12.666 -1.938 12.620 1.00 6.08 C ATOM 92 CB SER A 11 14.690 -2.772 11.415 1.00 6.08 C ATOM 93 O SER A 11 12.451 -2.709 13.557 1.00 6.08 O ATOM 94 OG SER A 11 15.435 -1.581 11.601 1.00 6.08 O ATOM 95 N ASP A 12 12.220 -0.675 12.710 1.00 6.08 N ATOM 96 CA ASP A 12 11.747 -0.267 14.029 1.00 6.08 C ATOM 97 C ASP A 12 10.304 -0.711 14.256 1.00 6.08 C ATOM 98 CB ASP A 12 11.864 1.249 14.196 1.00 6.08 C ATOM 99 O ASP A 12 9.847 -0.792 15.398 1.00 6.08 O ATOM 100 CG ASP A 12 13.206 1.682 14.760 1.00 6.08 C ATOM 101 OD1 ASP A 12 13.586 2.861 14.592 1.00 6.08 O ATOM 102 OD2 ASP A 12 13.890 0.837 15.376 1.00 6.08 O ATOM 103 N SER A 13 9.678 -1.277 13.274 1.00 6.08 N ATOM 104 CA SER A 13 8.274 -1.520 13.587 1.00 6.08 C ATOM 105 C SER A 13 8.041 -2.973 13.988 1.00 6.08 C ATOM 106 CB SER A 13 7.389 -1.164 12.393 1.00 6.08 C ATOM 107 O SER A 13 8.569 -3.889 13.355 1.00 6.08 O ATOM 108 OG SER A 13 7.871 -1.776 11.209 1.00 6.08 O ATOM 109 N ASN A 14 8.368 -3.385 15.178 1.00 6.08 N ATOM 110 CA ASN A 14 7.591 -4.466 15.775 1.00 6.08 C ATOM 111 C ASN A 14 6.843 -5.271 14.716 1.00 6.08 C ATOM 112 CB ASN A 14 6.610 -3.912 16.812 1.00 6.08 C ATOM 113 O ASN A 14 6.016 -6.122 15.047 1.00 6.08 O ATOM 114 CG ASN A 14 7.250 -3.709 18.171 1.00 6.08 C ATOM 115 ND2 ASN A 14 6.608 -2.910 19.015 1.00 6.08 N ATOM 116 OD1 ASN A 14 8.313 -4.265 18.460 1.00 6.08 O ATOM 117 N ILE A 15 7.204 -5.229 13.474 1.00 6.08 N ATOM 118 CA ILE A 15 6.430 -5.995 12.502 1.00 6.08 C ATOM 119 C ILE A 15 7.095 -7.349 12.265 1.00 6.08 C ATOM 120 CB ILE A 15 6.282 -5.229 11.168 1.00 6.08 C ATOM 121 O ILE A 15 8.306 -7.422 12.045 1.00 6.08 O ATOM 122 CG1 ILE A 15 5.583 -3.885 11.398 1.00 6.08 C ATOM 123 CG2 ILE A 15 5.520 -6.074 10.143 1.00 6.08 C ATOM 124 CD1 ILE A 15 5.473 -3.022 10.149 1.00 6.08 C ATOM 125 N LEU A 16 6.669 -8.397 13.068 1.00 6.08 N ATOM 126 CA LEU A 16 6.808 -9.846 12.972 1.00 6.08 C ATOM 127 C LEU A 16 6.967 -10.281 11.519 1.00 6.08 C ATOM 128 CB LEU A 16 5.597 -10.544 13.596 1.00 6.08 C ATOM 129 O LEU A 16 6.238 -9.812 10.643 1.00 6.08 O ATOM 130 CG LEU A 16 5.559 -10.598 15.125 1.00 6.08 C ATOM 131 CD1 LEU A 16 4.134 -10.839 15.611 1.00 6.08 C ATOM 132 CD2 LEU A 16 6.498 -11.682 15.644 1.00 6.08 C ATOM 133 N ALA A 17 8.248 -10.386 11.036 1.00 6.08 N ATOM 134 CA ALA A 17 8.700 -10.996 9.788 1.00 6.08 C ATOM 135 C ALA A 17 7.863 -12.224 9.444 1.00 6.08 C ATOM 136 CB ALA A 17 10.177 -11.372 9.884 1.00 6.08 C ATOM 137 O ALA A 17 7.473 -12.986 10.332 1.00 6.08 O ATOM 138 N PRO A 18 7.023 -12.218 8.206 1.00 6.08 N ATOM 139 CA PRO A 18 6.298 -13.437 7.841 1.00 6.08 C ATOM 140 C PRO A 18 7.204 -14.499 7.222 1.00 6.08 C ATOM 141 CB PRO A 18 5.264 -12.942 6.826 1.00 6.08 C ATOM 142 O PRO A 18 8.307 -14.186 6.767 1.00 6.08 O ATOM 143 CG PRO A 18 5.663 -11.532 6.531 1.00 6.08 C ATOM 144 CD PRO A 18 6.762 -11.140 7.476 1.00 6.08 C ATOM 145 N LYS A 19 6.910 -15.813 7.261 1.00 6.08 N ATOM 146 CA LYS A 19 7.401 -17.032 6.627 1.00 6.08 C ATOM 147 C LYS A 19 6.700 -17.279 5.294 1.00 6.08 C ATOM 148 CB LYS A 19 7.206 -18.235 7.552 1.00 6.08 C ATOM 149 O LYS A 19 5.494 -17.054 5.170 1.00 6.08 O ATOM 150 CG LYS A 19 8.289 -18.383 8.610 1.00 6.08 C ATOM 151 CD LYS A 19 8.149 -19.695 9.372 1.00 6.08 C ATOM 152 CE LYS A 19 9.213 -19.830 10.454 1.00 6.08 C ATOM 153 NZ LYS A 19 9.104 -21.132 11.178 1.00 6.08 N ATOM 154 N VAL A 20 7.272 -17.218 4.055 1.00 6.08 N ATOM 155 CA VAL A 20 6.741 -17.404 2.708 1.00 6.08 C ATOM 156 C VAL A 20 7.061 -18.814 2.217 1.00 6.08 C ATOM 157 CB VAL A 20 7.307 -16.355 1.725 1.00 6.08 C ATOM 158 O VAL A 20 8.148 -19.336 2.476 1.00 6.08 O ATOM 159 CG1 VAL A 20 6.686 -16.524 0.339 1.00 6.08 C ATOM 160 CG2 VAL A 20 7.064 -14.943 2.254 1.00 6.08 C ATOM 161 N SER A 21 6.082 -19.480 1.504 1.00 6.08 N ATOM 162 CA SER A 21 6.281 -20.787 0.888 1.00 6.08 C ATOM 163 C SER A 21 7.315 -20.720 -0.230 1.00 6.08 C ATOM 164 CB SER A 21 4.960 -21.329 0.340 1.00 6.08 C ATOM 165 O SER A 21 7.458 -19.688 -0.889 1.00 6.08 O ATOM 166 OG SER A 21 4.811 -20.999 -1.030 1.00 6.08 O ATOM 167 N GLN A 22 8.094 -21.778 -0.457 1.00 6.08 N ATOM 168 CA GLN A 22 9.146 -22.023 -1.437 1.00 6.08 C ATOM 169 C GLN A 22 8.608 -21.912 -2.861 1.00 6.08 C ATOM 170 CB GLN A 22 9.774 -23.400 -1.218 1.00 6.08 C ATOM 171 O GLN A 22 9.307 -21.436 -3.758 1.00 6.08 O ATOM 172 CG GLN A 22 11.028 -23.375 -0.356 1.00 6.08 C ATOM 173 CD GLN A 22 11.900 -24.601 -0.550 1.00 6.08 C ATOM 174 NE2 GLN A 22 13.017 -24.654 0.167 1.00 6.08 N ATOM 175 OE1 GLN A 22 11.570 -25.495 -1.337 1.00 6.08 O ATOM 176 N SER A 23 7.326 -22.350 -3.087 1.00 6.08 N ATOM 177 CA SER A 23 6.818 -22.344 -4.455 1.00 6.08 C ATOM 178 C SER A 23 6.627 -20.921 -4.968 1.00 6.08 C ATOM 179 CB SER A 23 5.494 -23.106 -4.539 1.00 6.08 C ATOM 180 O SER A 23 6.916 -20.631 -6.131 1.00 6.08 O ATOM 181 OG SER A 23 4.496 -22.467 -3.762 1.00 6.08 O ATOM 182 N VAL A 24 6.156 -19.987 -4.125 1.00 6.08 N ATOM 183 CA VAL A 24 5.987 -18.582 -4.483 1.00 6.08 C ATOM 184 C VAL A 24 7.353 -17.938 -4.708 1.00 6.08 C ATOM 185 CB VAL A 24 5.206 -17.809 -3.397 1.00 6.08 C ATOM 186 O VAL A 24 7.534 -17.165 -5.652 1.00 6.08 O ATOM 187 CG1 VAL A 24 5.211 -16.310 -3.691 1.00 6.08 C ATOM 188 CG2 VAL A 24 3.775 -18.332 -3.296 1.00 6.08 C ATOM 189 N ILE A 25 8.365 -18.356 -3.827 1.00 6.08 N ATOM 190 CA ILE A 25 9.724 -17.836 -3.937 1.00 6.08 C ATOM 191 C ILE A 25 10.325 -18.244 -5.280 1.00 6.08 C ATOM 192 CB ILE A 25 10.616 -18.332 -2.777 1.00 6.08 C ATOM 193 O ILE A 25 11.011 -17.450 -5.928 1.00 6.08 O ATOM 194 CG1 ILE A 25 10.127 -17.755 -1.444 1.00 6.08 C ATOM 195 CG2 ILE A 25 12.081 -17.966 -3.028 1.00 6.08 C ATOM 196 CD1 ILE A 25 10.848 -18.316 -0.226 1.00 6.08 C ATOM 197 N LYS A 26 9.942 -19.394 -5.728 1.00 6.08 N ATOM 198 CA LYS A 26 10.533 -19.885 -6.969 1.00 6.08 C ATOM 199 C LYS A 26 9.961 -19.150 -8.178 1.00 6.08 C ATOM 200 CB LYS A 26 10.303 -21.391 -7.115 1.00 6.08 C ATOM 201 O LYS A 26 10.615 -19.055 -9.219 1.00 6.08 O ATOM 202 CG LYS A 26 11.247 -22.244 -6.281 1.00 6.08 C ATOM 203 CD LYS A 26 11.022 -23.730 -6.527 1.00 6.08 C ATOM 204 CE LYS A 26 11.909 -24.587 -5.634 1.00 6.08 C ATOM 205 NZ LYS A 26 11.672 -26.045 -5.852 1.00 6.08 N ATOM 206 N SER A 27 8.716 -18.585 -8.016 1.00 6.08 N ATOM 207 CA SER A 27 8.115 -17.884 -9.146 1.00 6.08 C ATOM 208 C SER A 27 8.597 -16.439 -9.220 1.00 6.08 C ATOM 209 CB SER A 27 6.589 -17.917 -9.047 1.00 6.08 C ATOM 210 O SER A 27 8.389 -15.761 -10.229 1.00 6.08 O ATOM 211 OG SER A 27 6.145 -17.239 -7.885 1.00 6.08 O ATOM 212 N ILE A 28 9.326 -16.021 -8.127 1.00 6.08 N ATOM 213 CA ILE A 28 9.655 -14.600 -8.095 1.00 6.08 C ATOM 214 C ILE A 28 11.013 -14.370 -8.753 1.00 6.08 C ATOM 215 CB ILE A 28 9.660 -14.055 -6.649 1.00 6.08 C ATOM 216 O ILE A 28 12.005 -15.000 -8.381 1.00 6.08 O ATOM 217 CG1 ILE A 28 8.282 -14.238 -6.004 1.00 6.08 C ATOM 218 CG2 ILE A 28 10.082 -12.583 -6.629 1.00 6.08 C ATOM 219 CD1 ILE A 28 8.241 -13.892 -4.522 1.00 6.08 C ATOM 220 N LYS A 29 11.102 -13.748 -9.982 1.00 6.08 N ATOM 221 CA LYS A 29 12.253 -13.354 -10.790 1.00 6.08 C ATOM 222 C LYS A 29 12.954 -12.137 -10.192 1.00 6.08 C ATOM 223 CB LYS A 29 11.825 -13.058 -12.228 1.00 6.08 C ATOM 224 O LYS A 29 12.302 -11.156 -9.829 1.00 6.08 O ATOM 225 CG LYS A 29 11.657 -14.299 -13.092 1.00 6.08 C ATOM 226 CD LYS A 29 11.456 -13.937 -14.557 1.00 6.08 C ATOM 227 CE LYS A 29 11.272 -15.178 -15.421 1.00 6.08 C ATOM 228 NZ LYS A 29 11.145 -14.832 -16.868 1.00 6.08 N ATOM 229 N GLY A 30 13.888 -12.322 -9.217 1.00 6.08 N ATOM 230 CA GLY A 30 14.719 -11.185 -8.854 1.00 6.08 C ATOM 231 C GLY A 30 14.960 -11.074 -7.361 1.00 6.08 C ATOM 232 O GLY A 30 14.940 -9.975 -6.804 1.00 6.08 O ATOM 233 N ILE A 31 15.279 -12.138 -6.638 1.00 6.08 N ATOM 234 CA ILE A 31 15.591 -12.164 -5.214 1.00 6.08 C ATOM 235 C ILE A 31 16.885 -11.396 -4.954 1.00 6.08 C ATOM 236 CB ILE A 31 15.713 -13.612 -4.689 1.00 6.08 C ATOM 237 O ILE A 31 17.945 -11.761 -5.468 1.00 6.08 O ATOM 238 CG1 ILE A 31 14.396 -14.369 -4.897 1.00 6.08 C ATOM 239 CG2 ILE A 31 16.121 -13.619 -3.212 1.00 6.08 C ATOM 240 CD1 ILE A 31 14.475 -15.853 -4.565 1.00 6.08 C ATOM 241 N LYS A 32 16.933 -10.089 -4.574 1.00 6.08 N ATOM 242 CA LYS A 32 18.183 -9.378 -4.323 1.00 6.08 C ATOM 243 C LYS A 32 18.755 -9.738 -2.954 1.00 6.08 C ATOM 244 CB LYS A 32 17.970 -7.867 -4.420 1.00 6.08 C ATOM 245 O LYS A 32 19.969 -9.892 -2.804 1.00 6.08 O ATOM 246 CG LYS A 32 18.023 -7.324 -5.841 1.00 6.08 C ATOM 247 CD LYS A 32 18.626 -5.926 -5.883 1.00 6.08 C ATOM 248 CE LYS A 32 18.645 -5.367 -7.300 1.00 6.08 C ATOM 249 NZ LYS A 32 19.320 -4.036 -7.361 1.00 6.08 N ATOM 250 N SER A 33 17.909 -10.205 -1.893 1.00 6.08 N ATOM 251 CA SER A 33 18.320 -10.572 -0.542 1.00 6.08 C ATOM 252 C SER A 33 17.215 -11.331 0.185 1.00 6.08 C ATOM 253 CB SER A 33 18.707 -9.328 0.258 1.00 6.08 C ATOM 254 O SER A 33 16.099 -11.450 -0.324 1.00 6.08 O ATOM 255 OG SER A 33 17.560 -8.560 0.581 1.00 6.08 O ATOM 256 N LYS A 34 17.506 -12.068 1.188 1.00 6.08 N ATOM 257 CA LYS A 34 16.610 -12.918 1.967 1.00 6.08 C ATOM 258 C LYS A 34 15.403 -12.131 2.468 1.00 6.08 C ATOM 259 CB LYS A 34 17.356 -13.542 3.148 1.00 6.08 C ATOM 260 O LYS A 34 14.341 -12.706 2.718 1.00 6.08 O ATOM 261 CG LYS A 34 18.074 -14.840 2.810 1.00 6.08 C ATOM 262 CD LYS A 34 18.733 -15.451 4.040 1.00 6.08 C ATOM 263 CE LYS A 34 19.519 -16.707 3.689 1.00 6.08 C ATOM 264 NZ LYS A 34 20.155 -17.318 4.894 1.00 6.08 N ATOM 265 N HIS A 35 15.371 -10.863 2.266 1.00 5.36 N ATOM 266 CA HIS A 35 14.261 -10.259 2.994 1.00 5.36 C ATOM 267 C HIS A 35 13.500 -9.270 2.117 1.00 5.36 C ATOM 268 CB HIS A 35 14.765 -9.560 4.258 1.00 5.36 C ATOM 269 O HIS A 35 12.451 -8.760 2.515 1.00 5.36 O ATOM 270 CG HIS A 35 15.436 -10.482 5.225 1.00 5.36 C ATOM 271 CD2 HIS A 35 16.730 -10.574 5.614 1.00 5.36 C ATOM 272 ND1 HIS A 35 14.755 -11.461 5.916 1.00 5.36 N ATOM 273 CE1 HIS A 35 15.604 -12.116 6.691 1.00 5.36 C ATOM 274 NE2 HIS A 35 16.808 -11.597 6.526 1.00 5.36 N ATOM 275 N VAL A 36 14.059 -8.954 0.978 1.00 5.36 N ATOM 276 CA VAL A 36 13.407 -7.973 0.118 1.00 5.36 C ATOM 277 C VAL A 36 13.086 -8.603 -1.235 1.00 5.36 C ATOM 278 CB VAL A 36 14.284 -6.715 -0.074 1.00 5.36 C ATOM 279 O VAL A 36 13.962 -9.187 -1.878 1.00 5.36 O ATOM 280 CG1 VAL A 36 13.591 -5.709 -0.992 1.00 5.36 C ATOM 281 CG2 VAL A 36 14.605 -6.078 1.277 1.00 5.36 C ATOM 282 N PHE A 37 11.770 -8.603 -1.484 1.00 5.36 N ATOM 283 CA PHE A 37 11.361 -9.204 -2.749 1.00 5.36 C ATOM 284 C PHE A 37 10.980 -8.129 -3.760 1.00 5.36 C ATOM 285 CB PHE A 37 10.186 -10.163 -2.535 1.00 5.36 C ATOM 286 O PHE A 37 10.245 -7.195 -3.434 1.00 5.36 O ATOM 287 CG PHE A 37 10.500 -11.311 -1.614 1.00 5.36 C ATOM 288 CD1 PHE A 37 10.346 -11.180 -0.239 1.00 5.36 C ATOM 289 CD2 PHE A 37 10.949 -12.522 -2.124 1.00 5.36 C ATOM 290 CE1 PHE A 37 10.636 -12.242 0.616 1.00 5.36 C ATOM 291 CE2 PHE A 37 11.241 -13.587 -1.276 1.00 5.36 C ATOM 292 CZ PHE A 37 11.084 -13.445 0.093 1.00 5.36 C ATOM 293 N GLU A 38 11.560 -8.160 -4.884 1.00 5.36 N ATOM 294 CA GLU A 38 11.250 -7.279 -6.006 1.00 5.36 C ATOM 295 C GLU A 38 10.193 -7.897 -6.917 1.00 5.36 C ATOM 296 CB GLU A 38 12.516 -6.965 -6.808 1.00 5.36 C ATOM 297 O GLU A 38 10.363 -9.016 -7.405 1.00 5.36 O ATOM 298 CG GLU A 38 12.298 -5.965 -7.934 1.00 5.36 C ATOM 299 CD GLU A 38 13.552 -5.698 -8.751 1.00 5.36 C ATOM 300 OE1 GLU A 38 13.571 -6.025 -9.960 1.00 5.36 O ATOM 301 OE2 GLU A 38 14.525 -5.158 -8.178 1.00 5.36 O ATOM 302 N LEU A 39 9.040 -7.269 -6.940 1.00 5.36 N ATOM 303 CA LEU A 39 7.988 -7.741 -7.834 1.00 5.36 C ATOM 304 C LEU A 39 7.842 -6.816 -9.038 1.00 5.36 C ATOM 305 CB LEU A 39 6.655 -7.839 -7.087 1.00 5.36 C ATOM 306 O LEU A 39 7.250 -5.740 -8.931 1.00 5.36 O ATOM 307 CG LEU A 39 6.571 -8.896 -5.984 1.00 5.36 C ATOM 308 CD1 LEU A 39 5.425 -8.577 -5.030 1.00 5.36 C ATOM 309 CD2 LEU A 39 6.401 -10.286 -6.587 1.00 5.36 C ATOM 310 N PRO A 40 8.487 -7.251 -10.143 1.00 6.08 N ATOM 311 CA PRO A 40 8.346 -6.359 -11.296 1.00 6.08 C ATOM 312 C PRO A 40 6.896 -6.208 -11.751 1.00 6.08 C ATOM 313 CB PRO A 40 9.189 -7.043 -12.376 1.00 6.08 C ATOM 314 O PRO A 40 6.198 -7.207 -11.942 1.00 6.08 O ATOM 315 CG PRO A 40 9.550 -8.371 -11.794 1.00 6.08 C ATOM 316 CD PRO A 40 9.068 -8.416 -10.373 1.00 6.08 C ATOM 317 N ILE A 41 6.243 -4.982 -11.734 1.00 6.08 N ATOM 318 CA ILE A 41 4.884 -4.747 -12.210 1.00 6.08 C ATOM 319 C ILE A 41 4.900 -4.508 -13.718 1.00 6.08 C ATOM 320 CB ILE A 41 4.229 -3.551 -11.484 1.00 6.08 C ATOM 321 O ILE A 41 4.158 -5.153 -14.463 1.00 6.08 O ATOM 322 CG1 ILE A 41 4.176 -3.807 -9.974 1.00 6.08 C ATOM 323 CG2 ILE A 41 2.829 -3.280 -12.044 1.00 6.08 C ATOM 324 CD1 ILE A 41 3.647 -2.630 -9.165 1.00 6.08 C ATOM 325 N ASN A 42 5.810 -3.703 -14.250 1.00 6.08 N ATOM 326 CA ASN A 42 6.141 -3.456 -15.649 1.00 6.08 C ATOM 327 C ASN A 42 7.598 -3.034 -15.814 1.00 6.08 C ATOM 328 CB ASN A 42 5.210 -2.396 -16.242 1.00 6.08 C ATOM 329 O ASN A 42 8.396 -3.167 -14.885 1.00 6.08 O ATOM 330 CG ASN A 42 5.303 -1.067 -15.518 1.00 6.08 C ATOM 331 ND2 ASN A 42 4.156 -0.448 -15.267 1.00 6.08 N ATOM 332 OD1 ASN A 42 6.397 -0.600 -15.189 1.00 6.08 O ATOM 333 N ASP A 43 7.989 -2.622 -17.089 1.00 6.08 N ATOM 334 CA ASP A 43 9.387 -2.328 -17.387 1.00 6.08 C ATOM 335 C ASP A 43 9.898 -1.169 -16.534 1.00 6.08 C ATOM 336 CB ASP A 43 9.563 -2.005 -18.873 1.00 6.08 C ATOM 337 O ASP A 43 11.101 -1.051 -16.294 1.00 6.08 O ATOM 338 CG ASP A 43 9.350 -3.211 -19.771 1.00 6.08 C ATOM 339 OD1 ASP A 43 9.124 -3.033 -20.987 1.00 6.08 O ATOM 340 OD2 ASP A 43 9.406 -4.349 -19.257 1.00 6.08 O ATOM 341 N LYS A 44 8.964 -0.340 -16.036 1.00 6.08 N ATOM 342 CA LYS A 44 9.421 0.879 -15.374 1.00 6.08 C ATOM 343 C LYS A 44 9.078 0.858 -13.887 1.00 6.08 C ATOM 344 CB LYS A 44 8.806 2.113 -16.036 1.00 6.08 C ATOM 345 O LYS A 44 9.523 1.723 -13.130 1.00 6.08 O ATOM 346 CG LYS A 44 9.329 2.388 -17.438 1.00 6.08 C ATOM 347 CD LYS A 44 8.792 3.704 -17.986 1.00 6.08 C ATOM 348 CE LYS A 44 9.281 3.960 -19.405 1.00 6.08 C ATOM 349 NZ LYS A 44 8.775 5.260 -19.939 1.00 6.08 N ATOM 350 N THR A 45 8.261 -0.019 -13.522 1.00 6.08 N ATOM 351 CA THR A 45 7.740 0.030 -12.161 1.00 6.08 C ATOM 352 C THR A 45 8.037 -1.272 -11.421 1.00 6.08 C ATOM 353 CB THR A 45 6.223 0.293 -12.152 1.00 6.08 C ATOM 354 O THR A 45 7.755 -2.359 -11.929 1.00 6.08 O ATOM 355 CG2 THR A 45 5.716 0.544 -10.736 1.00 6.08 C ATOM 356 OG1 THR A 45 5.938 1.442 -12.960 1.00 6.08 O ATOM 357 N LYS A 46 8.731 -1.136 -10.322 1.00 5.36 N ATOM 358 CA LYS A 46 9.040 -2.324 -9.532 1.00 5.36 C ATOM 359 C LYS A 46 8.519 -2.186 -8.104 1.00 5.36 C ATOM 360 CB LYS A 46 10.548 -2.581 -9.517 1.00 5.36 C ATOM 361 O LYS A 46 8.374 -1.073 -7.595 1.00 5.36 O ATOM 362 CG LYS A 46 11.163 -2.738 -10.899 1.00 5.36 C ATOM 363 CD LYS A 46 12.677 -2.883 -10.824 1.00 5.36 C ATOM 364 CE LYS A 46 13.302 -2.960 -12.211 1.00 5.36 C ATOM 365 NZ LYS A 46 14.790 -2.843 -12.156 1.00 5.36 N ATOM 366 N ARG A 47 8.105 -3.267 -7.558 1.00 5.36 N ATOM 367 CA ARG A 47 7.620 -3.302 -6.182 1.00 5.36 C ATOM 368 C ARG A 47 8.642 -3.956 -5.258 1.00 5.36 C ATOM 369 CB ARG A 47 6.286 -4.047 -6.100 1.00 5.36 C ATOM 370 O ARG A 47 9.291 -4.934 -5.635 1.00 5.36 O ATOM 371 CG ARG A 47 5.588 -3.915 -4.756 1.00 5.36 C ATOM 372 CD ARG A 47 4.227 -4.596 -4.758 1.00 5.36 C ATOM 373 NE ARG A 47 3.162 -3.674 -4.374 1.00 5.36 N ATOM 374 NH1 ARG A 47 1.449 -5.188 -4.705 1.00 5.36 N ATOM 375 NH2 ARG A 47 0.983 -3.060 -3.991 1.00 5.36 N ATOM 376 CZ ARG A 47 1.867 -3.976 -4.358 1.00 5.36 C ATOM 377 N TYR A 48 8.748 -3.477 -3.978 1.00 5.36 N ATOM 378 CA TYR A 48 9.593 -4.175 -3.016 1.00 5.36 C ATOM 379 C TYR A 48 8.779 -4.649 -1.818 1.00 5.36 C ATOM 380 CB TYR A 48 10.734 -3.268 -2.546 1.00 5.36 C ATOM 381 O TYR A 48 7.943 -3.908 -1.295 1.00 5.36 O ATOM 382 CG TYR A 48 11.694 -2.881 -3.645 1.00 5.36 C ATOM 383 CD1 TYR A 48 11.441 -1.781 -4.462 1.00 5.36 C ATOM 384 CD2 TYR A 48 12.854 -3.613 -3.869 1.00 5.36 C ATOM 385 CE1 TYR A 48 12.321 -1.421 -5.477 1.00 5.36 C ATOM 386 CE2 TYR A 48 13.742 -3.263 -4.881 1.00 5.36 C ATOM 387 OH TYR A 48 14.342 -1.815 -6.682 1.00 5.36 O ATOM 388 CZ TYR A 48 13.467 -2.167 -5.678 1.00 5.36 C ATOM 389 N ILE A 49 8.717 -5.888 -1.613 1.00 5.36 N ATOM 390 CA ILE A 49 7.989 -6.430 -0.471 1.00 5.36 C ATOM 391 C ILE A 49 8.975 -6.856 0.614 1.00 5.36 C ATOM 392 CB ILE A 49 7.097 -7.622 -0.882 1.00 5.36 C ATOM 393 O ILE A 49 10.017 -7.445 0.318 1.00 5.36 O ATOM 394 CG1 ILE A 49 6.166 -7.220 -2.032 1.00 5.36 C ATOM 395 CG2 ILE A 49 6.296 -8.136 0.317 1.00 5.36 C ATOM 396 CD1 ILE A 49 5.367 -8.378 -2.615 1.00 5.36 C ATOM 397 N LEU A 50 8.862 -6.262 1.857 1.00 5.36 N ATOM 398 CA LEU A 50 9.614 -6.778 2.996 1.00 5.36 C ATOM 399 C LEU A 50 8.946 -8.023 3.570 1.00 5.36 C ATOM 400 CB LEU A 50 9.742 -5.707 4.083 1.00 5.36 C ATOM 401 O LEU A 50 7.743 -8.018 3.842 1.00 5.36 O ATOM 402 CG LEU A 50 11.100 -5.606 4.779 1.00 5.36 C ATOM 403 CD1 LEU A 50 11.885 -4.416 4.238 1.00 5.36 C ATOM 404 CD2 LEU A 50 10.920 -5.493 6.289 1.00 5.36 C ATOM 405 N GLY A 51 9.463 -9.224 3.543 1.00 5.36 N ATOM 406 CA GLY A 51 9.015 -10.310 4.400 1.00 5.36 C ATOM 407 C GLY A 51 7.865 -11.102 3.807 1.00 5.36 C ATOM 408 O GLY A 51 6.957 -10.529 3.200 1.00 5.36 O ATOM 409 N ALA A 52 8.049 -12.344 3.364 1.00 5.36 N ATOM 410 CA ALA A 52 6.949 -13.257 3.063 1.00 5.36 C ATOM 411 C ALA A 52 6.954 -14.454 4.009 1.00 5.36 C ATOM 412 CB ALA A 52 7.031 -13.728 1.613 1.00 5.36 C ATOM 413 O ALA A 52 8.016 -14.901 4.449 1.00 5.36 O ATOM 414 N THR A 53 5.741 -14.626 4.821 1.00 6.08 N ATOM 415 CA THR A 53 5.638 -15.818 5.655 1.00 6.08 C ATOM 416 C THR A 53 4.816 -16.898 4.956 1.00 6.08 C ATOM 417 CB THR A 53 5.005 -15.492 7.020 1.00 6.08 C ATOM 418 O THR A 53 4.163 -16.631 3.944 1.00 6.08 O ATOM 419 CG2 THR A 53 5.758 -14.364 7.719 1.00 6.08 C ATOM 420 OG1 THR A 53 3.643 -15.093 6.826 1.00 6.08 O ATOM 421 N GLU A 54 4.971 -18.204 5.377 1.00 6.08 N ATOM 422 CA GLU A 54 4.419 -19.510 5.031 1.00 6.08 C ATOM 423 C GLU A 54 2.894 -19.498 5.093 1.00 6.08 C ATOM 424 CB GLU A 54 4.974 -20.593 5.960 1.00 6.08 C ATOM 425 O GLU A 54 2.229 -20.148 4.283 1.00 6.08 O ATOM 426 CG GLU A 54 6.145 -21.367 5.371 1.00 6.08 C ATOM 427 CD GLU A 54 6.620 -22.505 6.261 1.00 6.08 C ATOM 428 OE1 GLU A 54 7.586 -23.207 5.885 1.00 6.08 O ATOM 429 OE2 GLU A 54 6.021 -22.696 7.343 1.00 6.08 O ATOM 430 N THR A 55 2.284 -18.768 6.100 1.00 6.08 N ATOM 431 CA THR A 55 0.931 -19.163 6.472 1.00 6.08 C ATOM 432 C THR A 55 -0.065 -18.051 6.153 1.00 6.08 C ATOM 433 CB THR A 55 0.844 -19.519 7.968 1.00 6.08 C ATOM 434 O THR A 55 -1.275 -18.282 6.132 1.00 6.08 O ATOM 435 CG2 THR A 55 1.686 -20.749 8.290 1.00 6.08 C ATOM 436 OG1 THR A 55 1.318 -18.412 8.745 1.00 6.08 O ATOM 437 N LYS A 56 0.188 -16.955 5.564 1.00 6.08 N ATOM 438 CA LYS A 56 -0.870 -15.980 5.311 1.00 6.08 C ATOM 439 C LYS A 56 -0.294 -14.671 4.777 1.00 6.08 C ATOM 440 CB LYS A 56 -1.676 -15.719 6.584 1.00 6.08 C ATOM 441 O LYS A 56 0.578 -14.069 5.406 1.00 6.08 O ATOM 442 CG LYS A 56 -2.640 -16.838 6.947 1.00 6.08 C ATOM 443 CD LYS A 56 -3.584 -16.421 8.067 1.00 6.08 C ATOM 444 CE LYS A 56 -4.524 -17.554 8.458 1.00 6.08 C ATOM 445 NZ LYS A 56 -5.505 -17.125 9.499 1.00 6.08 N ATOM 446 N GLU A 57 -0.274 -14.530 3.508 1.00 6.08 N ATOM 447 CA GLU A 57 -0.600 -13.449 2.582 1.00 6.08 C ATOM 448 C GLU A 57 -0.543 -12.092 3.276 1.00 6.08 C ATOM 449 CB GLU A 57 -1.984 -13.668 1.966 1.00 6.08 C ATOM 450 O GLU A 57 -0.932 -11.075 2.696 1.00 6.08 O ATOM 451 CG GLU A 57 -1.976 -14.563 0.735 1.00 6.08 C ATOM 452 CD GLU A 57 -3.338 -14.683 0.071 1.00 6.08 C ATOM 453 OE1 GLU A 57 -3.423 -15.253 -1.040 1.00 6.08 O ATOM 454 OE2 GLU A 57 -4.328 -14.203 0.667 1.00 6.08 O ATOM 455 N GLU A 58 0.126 -11.928 4.480 1.00 6.08 N ATOM 456 CA GLU A 58 -0.009 -10.492 4.706 1.00 6.08 C ATOM 457 C GLU A 58 1.168 -9.726 4.108 1.00 6.08 C ATOM 458 CB GLU A 58 -0.125 -10.192 6.203 1.00 6.08 C ATOM 459 O GLU A 58 2.323 -10.126 4.271 1.00 6.08 O ATOM 460 CG GLU A 58 -1.553 -9.953 6.673 1.00 6.08 C ATOM 461 CD GLU A 58 -1.648 -9.595 8.147 1.00 6.08 C ATOM 462 OE1 GLU A 58 -2.761 -9.279 8.625 1.00 6.08 O ATOM 463 OE2 GLU A 58 -0.600 -9.629 8.830 1.00 6.08 O ATOM 464 N VAL A 59 0.923 -8.970 3.115 1.00 5.36 N ATOM 465 CA VAL A 59 1.676 -8.056 2.262 1.00 5.36 C ATOM 466 C VAL A 59 1.616 -6.644 2.838 1.00 5.36 C ATOM 467 CB VAL A 59 1.141 -8.064 0.812 1.00 5.36 C ATOM 468 O VAL A 59 0.550 -6.026 2.875 1.00 5.36 O ATOM 469 CG1 VAL A 59 2.113 -7.351 -0.126 1.00 5.36 C ATOM 470 CG2 VAL A 59 0.894 -9.496 0.342 1.00 5.36 C ATOM 471 N LEU A 60 2.134 -6.382 4.062 1.00 5.36 N ATOM 472 CA LEU A 60 2.206 -4.926 4.093 1.00 5.36 C ATOM 473 C LEU A 60 3.467 -4.459 4.813 1.00 5.36 C ATOM 474 CB LEU A 60 0.968 -4.342 4.778 1.00 5.36 C ATOM 475 O LEU A 60 3.645 -4.732 6.002 1.00 5.36 O ATOM 476 CG LEU A 60 -0.362 -4.523 4.044 1.00 5.36 C ATOM 477 CD1 LEU A 60 -1.528 -4.217 4.977 1.00 5.36 C ATOM 478 CD2 LEU A 60 -0.414 -3.635 2.805 1.00 5.36 C ATOM 479 N PRO A 61 4.690 -3.899 4.294 1.00 5.36 N ATOM 480 CA PRO A 61 4.413 -2.559 3.771 1.00 5.36 C ATOM 481 C PRO A 61 4.305 -2.531 2.248 1.00 5.36 C ATOM 482 CB PRO A 61 5.614 -1.739 4.248 1.00 5.36 C ATOM 483 O PRO A 61 4.930 -3.348 1.566 1.00 5.36 O ATOM 484 CG PRO A 61 6.588 -2.750 4.760 1.00 5.36 C ATOM 485 CD PRO A 61 5.908 -4.089 4.803 1.00 5.36 C ATOM 486 N ASN A 62 3.352 -1.777 1.774 1.00 4.42 N ATOM 487 CA ASN A 62 2.773 -1.209 0.561 1.00 4.42 C ATOM 488 C ASN A 62 3.673 -0.134 -0.041 1.00 4.42 C ATOM 489 CB ASN A 62 1.382 -0.637 0.847 1.00 4.42 C ATOM 490 O ASN A 62 3.461 1.058 0.186 1.00 4.42 O ATOM 491 CG ASN A 62 0.321 -1.714 0.963 1.00 4.42 C ATOM 492 ND2 ASN A 62 -0.756 -1.410 1.679 1.00 4.42 N ATOM 493 OD1 ASN A 62 0.468 -2.809 0.415 1.00 4.42 O ATOM 494 N TYR A 63 4.982 -0.411 -0.311 1.00 4.42 N ATOM 495 CA TYR A 63 5.766 0.563 -1.062 1.00 4.42 C ATOM 496 C TYR A 63 5.569 0.381 -2.563 1.00 4.42 C ATOM 497 CB TYR A 63 7.252 0.442 -0.712 1.00 4.42 C ATOM 498 O TYR A 63 5.291 -0.726 -3.029 1.00 4.42 O ATOM 499 CG TYR A 63 7.556 0.705 0.743 1.00 4.42 C ATOM 500 CD1 TYR A 63 7.564 -0.333 1.672 1.00 4.42 C ATOM 501 CD2 TYR A 63 7.835 1.992 1.191 1.00 4.42 C ATOM 502 CE1 TYR A 63 7.842 -0.094 3.014 1.00 4.42 C ATOM 503 CE2 TYR A 63 8.114 2.242 2.531 1.00 4.42 C ATOM 504 OH TYR A 63 8.392 1.435 4.760 1.00 4.42 O ATOM 505 CZ TYR A 63 8.116 1.194 3.433 1.00 4.42 C ATOM 506 N VAL A 64 5.361 1.479 -3.257 1.00 4.42 N ATOM 507 CA VAL A 64 5.323 1.484 -4.716 1.00 4.42 C ATOM 508 C VAL A 64 6.456 2.350 -5.260 1.00 4.42 C ATOM 509 CB VAL A 64 3.963 1.991 -5.246 1.00 4.42 C ATOM 510 O VAL A 64 6.668 3.472 -4.794 1.00 4.42 O ATOM 511 CG1 VAL A 64 4.005 2.161 -6.764 1.00 4.42 C ATOM 512 CG2 VAL A 64 2.843 1.034 -4.844 1.00 4.42 C ATOM 513 N LYS A 65 7.501 1.678 -5.944 1.00 5.36 N ATOM 514 CA LYS A 65 8.535 2.445 -6.634 1.00 5.36 C ATOM 515 C LYS A 65 8.078 2.847 -8.033 1.00 5.36 C ATOM 516 CB LYS A 65 9.834 1.643 -6.717 1.00 5.36 C ATOM 517 O LYS A 65 7.631 2.004 -8.812 1.00 5.36 O ATOM 518 CG LYS A 65 11.017 2.434 -7.256 1.00 5.36 C ATOM 519 CD LYS A 65 12.295 1.605 -7.245 1.00 5.36 C ATOM 520 CE LYS A 65 13.479 2.395 -7.786 1.00 5.36 C ATOM 521 NZ LYS A 65 14.742 1.599 -7.745 1.00 5.36 N ATOM 522 N VAL A 66 8.093 4.091 -8.333 1.00 5.36 N ATOM 523 CA VAL A 66 7.778 4.641 -9.647 1.00 5.36 C ATOM 524 C VAL A 66 9.008 5.340 -10.223 1.00 5.36 C ATOM 525 CB VAL A 66 6.589 5.625 -9.580 1.00 5.36 C ATOM 526 O VAL A 66 9.375 6.430 -9.779 1.00 5.36 O ATOM 527 CG1 VAL A 66 6.222 6.125 -10.977 1.00 5.36 C ATOM 528 CG2 VAL A 66 5.385 4.962 -8.914 1.00 5.36 C ATOM 529 N GLY A 67 9.659 4.635 -11.193 1.00 5.36 N ATOM 530 CA GLY A 67 10.950 5.142 -11.630 1.00 5.36 C ATOM 531 C GLY A 67 12.012 5.081 -10.548 1.00 5.36 C ATOM 532 O GLY A 67 12.305 4.007 -10.019 1.00 5.36 O ATOM 533 N SER A 68 12.514 6.343 -10.271 1.00 5.36 N ATOM 534 CA SER A 68 13.526 6.411 -9.222 1.00 5.36 C ATOM 535 C SER A 68 12.902 6.759 -7.874 1.00 5.36 C ATOM 536 CB SER A 68 14.598 7.442 -9.577 1.00 5.36 C ATOM 537 O SER A 68 13.608 6.894 -6.873 1.00 5.36 O ATOM 538 OG SER A 68 14.006 8.654 -10.011 1.00 5.36 O ATOM 539 N ASP A 69 11.527 6.878 -7.937 1.00 5.36 N ATOM 540 CA ASP A 69 10.872 7.348 -6.720 1.00 5.36 C ATOM 541 C ASP A 69 10.208 6.193 -5.973 1.00 5.36 C ATOM 542 CB ASP A 69 9.837 8.425 -7.049 1.00 5.36 C ATOM 543 O ASP A 69 9.669 5.274 -6.594 1.00 5.36 O ATOM 544 CG ASP A 69 10.453 9.672 -7.660 1.00 5.36 C ATOM 545 OD1 ASP A 69 9.841 10.271 -8.571 1.00 5.36 O ATOM 546 OD2 ASP A 69 11.561 10.057 -7.229 1.00 5.36 O ATOM 547 N LEU A 70 10.310 6.167 -4.690 1.00 4.42 N ATOM 548 CA LEU A 70 9.712 5.170 -3.810 1.00 4.42 C ATOM 549 C LEU A 70 8.614 5.789 -2.952 1.00 4.42 C ATOM 550 CB LEU A 70 10.780 4.537 -2.914 1.00 4.42 C ATOM 551 O LEU A 70 8.810 6.853 -2.359 1.00 4.42 O ATOM 552 CG LEU A 70 10.378 3.255 -2.182 1.00 4.42 C ATOM 553 CD1 LEU A 70 10.240 2.102 -3.170 1.00 4.42 C ATOM 554 CD2 LEU A 70 11.395 2.918 -1.097 1.00 4.42 C ATOM 555 N TYR A 71 7.500 5.181 -2.953 1.00 4.42 N ATOM 556 CA TYR A 71 6.370 5.703 -2.192 1.00 4.42 C ATOM 557 C TYR A 71 5.940 4.719 -1.110 1.00 4.42 C ATOM 558 CB TYR A 71 5.190 6.006 -3.121 1.00 4.42 C ATOM 559 O TYR A 71 5.994 3.504 -1.311 1.00 4.42 O ATOM 560 CG TYR A 71 5.502 7.031 -4.184 1.00 4.42 C ATOM 561 CD1 TYR A 71 6.112 6.661 -5.380 1.00 4.42 C ATOM 562 CD2 TYR A 71 5.190 8.373 -3.993 1.00 4.42 C ATOM 563 CE1 TYR A 71 6.403 7.603 -6.361 1.00 4.42 C ATOM 564 CE2 TYR A 71 5.476 9.324 -4.967 1.00 4.42 C ATOM 565 OH TYR A 71 6.367 9.867 -7.114 1.00 4.42 O ATOM 566 CZ TYR A 71 6.081 8.930 -6.146 1.00 4.42 C ATOM 567 N ARG A 72 5.750 5.231 0.077 1.00 4.42 N ATOM 568 CA ARG A 72 5.102 4.470 1.140 1.00 4.42 C ATOM 569 C ARG A 72 3.588 4.648 1.097 1.00 4.42 C ATOM 570 CB ARG A 72 5.641 4.892 2.509 1.00 4.42 C ATOM 571 O ARG A 72 3.093 5.772 0.987 1.00 4.42 O ATOM 572 CG ARG A 72 5.185 4.000 3.652 1.00 4.42 C ATOM 573 CD ARG A 72 5.797 4.427 4.979 1.00 4.42 C ATOM 574 NE ARG A 72 5.284 3.630 6.090 1.00 4.42 N ATOM 575 NH1 ARG A 72 6.305 4.890 7.736 1.00 4.42 N ATOM 576 NH2 ARG A 72 5.019 3.079 8.304 1.00 4.42 N ATOM 577 CZ ARG A 72 5.538 3.868 7.374 1.00 4.42 C ATOM 578 N LEU A 73 2.852 3.545 1.039 1.00 3.21 N ATOM 579 CA LEU A 73 1.395 3.610 1.029 1.00 3.21 C ATOM 580 C LEU A 73 0.833 3.435 2.436 1.00 3.21 C ATOM 581 CB LEU A 73 0.816 2.541 0.099 1.00 3.21 C ATOM 582 O LEU A 73 1.261 2.544 3.173 1.00 3.21 O ATOM 583 CG LEU A 73 1.212 2.639 -1.375 1.00 3.21 C ATOM 584 CD1 LEU A 73 1.030 1.291 -2.064 1.00 3.21 C ATOM 585 CD2 LEU A 73 0.396 3.719 -2.078 1.00 3.21 C ATOM 586 N LYS A 74 0.064 4.404 2.921 1.00 4.42 N ATOM 587 CA LYS A 74 -0.627 4.299 4.203 1.00 4.42 C ATOM 588 C LYS A 74 -2.140 4.374 4.020 1.00 4.42 C ATOM 589 CB LYS A 74 -0.159 5.400 5.156 1.00 4.42 C ATOM 590 O LYS A 74 -2.643 5.256 3.320 1.00 4.42 O ATOM 591 CG LYS A 74 -0.498 5.139 6.617 1.00 4.42 C ATOM 592 CD LYS A 74 0.083 6.214 7.526 1.00 4.42 C ATOM 593 CE LYS A 74 -0.315 5.993 8.979 1.00 4.42 C ATOM 594 NZ LYS A 74 0.270 7.033 9.878 1.00 4.42 N ATOM 595 N ALA A 75 -2.781 3.329 4.523 1.00 4.42 N ATOM 596 CA ALA A 75 -4.241 3.343 4.479 1.00 4.42 C ATOM 597 C ALA A 75 -4.826 3.741 5.831 1.00 4.42 C ATOM 598 CB ALA A 75 -4.774 1.977 4.053 1.00 4.42 C ATOM 599 O ALA A 75 -4.275 3.396 6.879 1.00 4.42 O ATOM 600 N TYR A 76 -5.770 4.597 5.772 1.00 5.36 N ATOM 601 CA TYR A 76 -6.435 4.990 7.009 1.00 5.36 C ATOM 602 C TYR A 76 -7.924 5.215 6.781 1.00 5.36 C ATOM 603 CB TYR A 76 -5.797 6.259 7.583 1.00 5.36 C ATOM 604 O TYR A 76 -8.375 5.314 5.637 1.00 5.36 O ATOM 605 CG TYR A 76 -5.887 7.453 6.665 1.00 5.36 C ATOM 606 CD1 TYR A 76 -6.916 8.382 6.798 1.00 5.36 C ATOM 607 CD2 TYR A 76 -4.946 7.653 5.661 1.00 5.36 C ATOM 608 CE1 TYR A 76 -7.005 9.483 5.952 1.00 5.36 C ATOM 609 CE2 TYR A 76 -5.024 8.750 4.809 1.00 5.36 C ATOM 610 OH TYR A 76 -6.138 10.746 4.123 1.00 5.36 O ATOM 611 CZ TYR A 76 -6.055 9.659 4.963 1.00 5.36 C ATOM 612 N ARG A 77 -8.726 5.218 7.799 1.00 5.36 N ATOM 613 CA ARG A 77 -10.169 5.419 7.723 1.00 5.36 C ATOM 614 C ARG A 77 -10.570 6.753 8.344 1.00 5.36 C ATOM 615 CB ARG A 77 -10.909 4.274 8.418 1.00 5.36 C ATOM 616 O ARG A 77 -10.028 7.151 9.377 1.00 5.36 O ATOM 617 CG ARG A 77 -12.424 4.372 8.322 1.00 5.36 C ATOM 618 CD ARG A 77 -13.109 3.207 9.024 1.00 5.36 C ATOM 619 NE ARG A 77 -13.016 1.977 8.244 1.00 5.36 N ATOM 620 NH1 ARG A 77 -14.417 0.756 9.616 1.00 5.36 N ATOM 621 NH2 ARG A 77 -13.484 -0.219 7.763 1.00 5.36 N ATOM 622 CZ ARG A 77 -13.639 0.841 8.542 1.00 5.36 C ATOM 623 N GLU A 78 -11.384 7.464 7.705 1.00 5.36 N ATOM 624 CA GLU A 78 -12.045 8.659 8.221 1.00 5.36 C ATOM 625 C GLU A 78 -13.563 8.519 8.164 1.00 5.36 C ATOM 626 CB GLU A 78 -11.601 9.899 7.439 1.00 5.36 C ATOM 627 O GLU A 78 -14.081 7.514 7.673 1.00 5.36 O ATOM 628 CG GLU A 78 -10.154 10.298 7.690 1.00 5.36 C ATOM 629 CD GLU A 78 -9.792 11.648 7.092 1.00 5.36 C ATOM 630 OE1 GLU A 78 -8.647 12.113 7.291 1.00 5.36 O ATOM 631 OE2 GLU A 78 -10.661 12.247 6.420 1.00 5.36 O ATOM 632 N LYS A 79 -14.255 9.510 8.676 1.00 5.36 N ATOM 633 CA LYS A 79 -15.715 9.478 8.716 1.00 5.36 C ATOM 634 C LYS A 79 -16.297 9.210 7.332 1.00 5.36 C ATOM 635 CB LYS A 79 -16.265 10.793 9.271 1.00 5.36 C ATOM 636 O LYS A 79 -17.266 8.460 7.195 1.00 5.36 O ATOM 637 CG LYS A 79 -16.312 10.853 10.790 1.00 5.36 C ATOM 638 CD LYS A 79 -16.955 12.144 11.279 1.00 5.36 C ATOM 639 CE LYS A 79 -16.920 12.247 12.798 1.00 5.36 C ATOM 640 NZ LYS A 79 -17.524 13.525 13.281 1.00 5.36 N ATOM 641 N SER A 80 -15.615 9.685 6.280 1.00 5.36 N ATOM 642 CA SER A 80 -16.194 9.676 4.940 1.00 5.36 C ATOM 643 C SER A 80 -15.768 8.435 4.163 1.00 5.36 C ATOM 644 CB SER A 80 -15.787 10.934 4.171 1.00 5.36 C ATOM 645 O SER A 80 -16.312 8.148 3.094 1.00 5.36 O ATOM 646 OG SER A 80 -14.376 11.064 4.131 1.00 5.36 O ATOM 647 N GLY A 81 -14.790 7.696 4.700 1.00 5.36 N ATOM 648 CA GLY A 81 -14.368 6.508 3.975 1.00 5.36 C ATOM 649 C GLY A 81 -12.932 6.112 4.264 1.00 5.36 C ATOM 650 O GLY A 81 -12.367 6.508 5.285 1.00 5.36 O ATOM 651 N VAL A 82 -12.402 5.137 3.681 1.00 5.36 N ATOM 652 CA VAL A 82 -11.030 4.653 3.791 1.00 5.36 C ATOM 653 C VAL A 82 -10.148 5.364 2.767 1.00 5.36 C ATOM 654 CB VAL A 82 -10.951 3.123 3.591 1.00 5.36 C ATOM 655 O VAL A 82 -10.540 5.531 1.610 1.00 5.36 O ATOM 656 CG1 VAL A 82 -9.503 2.642 3.674 1.00 5.36 C ATOM 657 CG2 VAL A 82 -11.816 2.405 4.626 1.00 5.36 C ATOM 658 N TYR A 83 -9.046 5.835 3.278 1.00 5.36 N ATOM 659 CA TYR A 83 -8.137 6.587 2.421 1.00 5.36 C ATOM 660 C TYR A 83 -6.784 5.894 2.319 1.00 5.36 C ATOM 661 CB TYR A 83 -7.955 8.013 2.949 1.00 5.36 C ATOM 662 O TYR A 83 -6.401 5.132 3.211 1.00 5.36 O ATOM 663 CG TYR A 83 -9.240 8.802 3.021 1.00 5.36 C ATOM 664 CD1 TYR A 83 -10.101 8.671 4.108 1.00 5.36 C ATOM 665 CD2 TYR A 83 -9.595 9.680 2.003 1.00 5.36 C ATOM 666 CE1 TYR A 83 -11.287 9.395 4.177 1.00 5.36 C ATOM 667 CE2 TYR A 83 -10.778 10.409 2.062 1.00 5.36 C ATOM 668 OH TYR A 83 -12.789 10.979 3.215 1.00 5.36 O ATOM 669 CZ TYR A 83 -11.616 10.260 3.151 1.00 5.36 C ATOM 670 N VAL A 84 -6.217 5.977 1.159 1.00 4.42 N ATOM 671 CA VAL A 84 -4.820 5.583 1.013 1.00 4.42 C ATOM 672 C VAL A 84 -3.961 6.815 0.737 1.00 4.42 C ATOM 673 CB VAL A 84 -4.638 4.544 -0.116 1.00 4.42 C ATOM 674 O VAL A 84 -4.300 7.638 -0.117 1.00 4.42 O ATOM 675 CG1 VAL A 84 -3.161 4.207 -0.308 1.00 4.42 C ATOM 676 CG2 VAL A 84 -5.442 3.281 0.188 1.00 4.42 C ATOM 677 N ARG A 85 -3.015 6.909 1.573 1.00 4.42 N ATOM 678 CA ARG A 85 -2.052 8.001 1.472 1.00 4.42 C ATOM 679 C ARG A 85 -0.722 7.508 0.912 1.00 4.42 C ATOM 680 CB ARG A 85 -1.835 8.655 2.838 1.00 4.42 C ATOM 681 O ARG A 85 -0.256 6.423 1.268 1.00 4.42 O ATOM 682 CG ARG A 85 -1.113 9.992 2.773 1.00 4.42 C ATOM 683 CD ARG A 85 -0.941 10.607 4.154 1.00 4.42 C ATOM 684 NE ARG A 85 -2.049 11.496 4.491 1.00 4.42 N ATOM 685 NH1 ARG A 85 -1.423 11.780 6.696 1.00 4.42 N ATOM 686 NH2 ARG A 85 -3.293 12.829 5.887 1.00 4.42 N ATOM 687 CZ ARG A 85 -2.252 12.033 5.691 1.00 4.42 C ATOM 688 N THR A 86 -0.152 8.200 -0.153 1.00 4.42 N ATOM 689 CA THR A 86 1.170 7.866 -0.672 1.00 4.42 C ATOM 690 C THR A 86 2.192 8.924 -0.269 1.00 4.42 C ATOM 691 CB THR A 86 1.148 7.726 -2.205 1.00 4.42 C ATOM 692 O THR A 86 1.918 10.123 -0.351 1.00 4.42 O ATOM 693 CG2 THR A 86 0.290 6.542 -2.638 1.00 4.42 C ATOM 694 OG1 THR A 86 0.614 8.925 -2.781 1.00 4.42 O ATOM 695 N ASN A 87 3.286 8.434 0.354 1.00 5.36 N ATOM 696 CA ASN A 87 4.370 9.361 0.664 1.00 5.36 C ATOM 697 C ASN A 87 5.610 9.075 -0.179 1.00 5.36 C ATOM 698 CB ASN A 87 4.716 9.304 2.153 1.00 5.36 C ATOM 699 O ASN A 87 6.062 7.932 -0.258 1.00 5.36 O ATOM 700 CG ASN A 87 3.662 9.959 3.024 1.00 5.36 C ATOM 701 ND2 ASN A 87 3.845 9.882 4.336 1.00 5.36 N ATOM 702 OD1 ASN A 87 2.690 10.529 2.520 1.00 5.36 O ATOM 703 N LYS A 88 6.095 10.057 -0.960 1.00 5.36 N ATOM 704 CA LYS A 88 7.392 9.866 -1.603 1.00 5.36 C ATOM 705 C LYS A 88 8.509 9.764 -0.569 1.00 5.36 C ATOM 706 CB LYS A 88 7.682 11.009 -2.577 1.00 5.36 C ATOM 707 O LYS A 88 8.639 10.630 0.299 1.00 5.36 O ATOM 708 CG LYS A 88 8.904 10.780 -3.454 1.00 5.36 C ATOM 709 CD LYS A 88 9.096 11.914 -4.452 1.00 5.36 C ATOM 710 CE LYS A 88 10.325 11.692 -5.323 1.00 5.36 C ATOM 711 NZ LYS A 88 10.494 12.781 -6.331 1.00 5.36 N ATOM 712 N LEU A 89 9.164 8.645 -0.576 1.00 5.36 N ATOM 713 CA LEU A 89 10.225 8.484 0.412 1.00 5.36 C ATOM 714 C LEU A 89 11.425 9.361 0.069 1.00 5.36 C ATOM 715 CB LEU A 89 10.658 7.018 0.498 1.00 5.36 C ATOM 716 O LEU A 89 11.670 9.653 -1.104 1.00 5.36 O ATOM 717 CG LEU A 89 9.718 6.077 1.253 1.00 5.36 C ATOM 718 CD1 LEU A 89 10.100 4.624 0.990 1.00 5.36 C ATOM 719 CD2 LEU A 89 9.744 6.380 2.747 1.00 5.36 C ATOM 720 N GLY A 90 12.223 9.812 1.163 1.00 5.36 N ATOM 721 CA GLY A 90 13.408 10.650 1.084 1.00 5.36 C ATOM 722 C GLY A 90 13.092 12.133 1.100 1.00 5.36 C ATOM 723 O GLY A 90 13.993 12.967 0.984 1.00 5.36 O ATOM 724 N PHE A 91 11.852 12.465 1.066 1.00 6.08 N ATOM 725 CA PHE A 91 11.399 13.841 1.233 1.00 6.08 C ATOM 726 C PHE A 91 10.518 13.974 2.470 1.00 6.08 C ATOM 727 CB PHE A 91 10.634 14.312 -0.008 1.00 6.08 C ATOM 728 O PHE A 91 9.318 13.699 2.417 1.00 6.08 O ATOM 729 CG PHE A 91 11.519 14.611 -1.188 1.00 6.08 C ATOM 730 CD1 PHE A 91 11.797 13.630 -2.132 1.00 6.08 C ATOM 731 CD2 PHE A 91 12.073 15.874 -1.353 1.00 6.08 C ATOM 732 CE1 PHE A 91 12.615 13.904 -3.226 1.00 6.08 C ATOM 733 CE2 PHE A 91 12.891 16.155 -2.443 1.00 6.08 C ATOM 734 CZ PHE A 91 13.162 15.168 -3.378 1.00 6.08 C ATOM 735 N GLU A 92 11.137 13.459 3.617 1.00 6.08 N ATOM 736 CA GLU A 92 10.535 13.509 4.945 1.00 6.08 C ATOM 737 C GLU A 92 10.313 14.950 5.397 1.00 6.08 C ATOM 738 CB GLU A 92 11.409 12.768 5.960 1.00 6.08 C ATOM 739 O GLU A 92 11.270 15.664 5.704 1.00 6.08 O ATOM 740 CG GLU A 92 10.998 11.320 6.186 1.00 6.08 C ATOM 741 CD GLU A 92 11.819 10.623 7.259 1.00 6.08 C ATOM 742 OE1 GLU A 92 11.506 9.461 7.604 1.00 6.08 O ATOM 743 OE2 GLU A 92 12.783 11.245 7.759 1.00 6.08 O ATOM 744 N ASP A 93 9.620 15.891 4.677 1.00 6.08 N ATOM 745 CA ASP A 93 9.157 16.934 5.587 1.00 6.08 C ATOM 746 C ASP A 93 7.745 16.640 6.087 1.00 6.08 C ATOM 747 CB ASP A 93 9.199 18.302 4.902 1.00 6.08 C ATOM 748 O ASP A 93 6.797 16.602 5.299 1.00 6.08 O ATOM 749 CG ASP A 93 8.970 19.454 5.864 1.00 6.08 C ATOM 750 OD1 ASP A 93 9.176 20.624 5.475 1.00 6.08 O ATOM 751 OD2 ASP A 93 8.583 19.190 7.023 1.00 6.08 O ATOM 752 N PRO A 94 7.665 15.732 7.134 1.00 6.08 N ATOM 753 CA PRO A 94 6.298 15.546 7.627 1.00 6.08 C ATOM 754 C PRO A 94 5.438 16.798 7.468 1.00 6.08 C ATOM 755 CB PRO A 94 6.500 15.207 9.106 1.00 6.08 C ATOM 756 O PRO A 94 4.211 16.701 7.386 1.00 6.08 O ATOM 757 CG PRO A 94 7.963 15.397 9.346 1.00 6.08 C ATOM 758 CD PRO A 94 8.633 15.652 8.026 1.00 6.08 C ATOM 759 N LYS A 95 6.057 18.015 7.264 1.00 6.08 N ATOM 760 CA LYS A 95 5.244 19.214 7.077 1.00 6.08 C ATOM 761 C LYS A 95 5.046 19.517 5.595 1.00 6.08 C ATOM 762 CB LYS A 95 5.887 20.413 7.776 1.00 6.08 C ATOM 763 O LYS A 95 4.278 20.413 5.236 1.00 6.08 O ATOM 764 CG LYS A 95 5.879 20.321 9.295 1.00 6.08 C ATOM 765 CD LYS A 95 6.403 21.600 9.935 1.00 6.08 C ATOM 766 CE LYS A 95 6.462 21.483 11.452 1.00 6.08 C ATOM 767 NZ LYS A 95 6.972 22.736 12.085 1.00 6.08 N ATOM 768 N SER A 96 5.718 18.813 4.741 1.00 6.08 N ATOM 769 CA SER A 96 5.637 19.195 3.335 1.00 6.08 C ATOM 770 C SER A 96 4.505 18.459 2.626 1.00 6.08 C ATOM 771 CB SER A 96 6.963 18.912 2.626 1.00 6.08 C ATOM 772 O SER A 96 4.417 17.231 2.696 1.00 6.08 O ATOM 773 OG SER A 96 6.791 17.942 1.607 1.00 6.08 O ATOM 774 N PHE A 97 3.312 18.985 2.701 1.00 6.08 N ATOM 775 CA PHE A 97 2.069 18.645 2.019 1.00 6.08 C ATOM 776 C PHE A 97 2.310 18.435 0.529 1.00 6.08 C ATOM 777 CB PHE A 97 1.020 19.741 2.232 1.00 6.08 C ATOM 778 O PHE A 97 1.445 17.913 -0.178 1.00 6.08 O ATOM 779 CG PHE A 97 0.311 19.653 3.556 1.00 6.08 C ATOM 780 CD1 PHE A 97 0.741 20.404 4.643 1.00 6.08 C ATOM 781 CD2 PHE A 97 -0.787 18.817 3.714 1.00 6.08 C ATOM 782 CE1 PHE A 97 0.086 20.325 5.869 1.00 6.08 C ATOM 783 CE2 PHE A 97 -1.447 18.732 4.937 1.00 6.08 C ATOM 784 CZ PHE A 97 -1.008 19.486 6.014 1.00 6.08 C ATOM 785 N LEU A 98 3.513 18.640 0.039 1.00 6.08 N ATOM 786 CA LEU A 98 3.587 18.842 -1.404 1.00 6.08 C ATOM 787 C LEU A 98 3.826 17.520 -2.126 1.00 6.08 C ATOM 788 CB LEU A 98 4.699 19.835 -1.751 1.00 6.08 C ATOM 789 O LEU A 98 3.478 17.377 -3.300 1.00 6.08 O ATOM 790 CG LEU A 98 4.372 21.315 -1.552 1.00 6.08 C ATOM 791 CD1 LEU A 98 5.651 22.145 -1.553 1.00 6.08 C ATOM 792 CD2 LEU A 98 3.413 21.801 -2.634 1.00 6.08 C ATOM 793 N SER A 99 3.933 16.395 -1.418 1.00 6.08 N ATOM 794 CA SER A 99 3.847 15.299 -2.377 1.00 6.08 C ATOM 795 C SER A 99 2.856 14.236 -1.915 1.00 6.08 C ATOM 796 CB SER A 99 5.222 14.666 -2.593 1.00 6.08 C ATOM 797 O SER A 99 3.126 13.039 -2.024 1.00 6.08 O ATOM 798 OG SER A 99 6.045 14.848 -1.453 1.00 6.08 O ATOM 799 N ILE A 100 1.863 14.672 -1.135 1.00 6.08 N ATOM 800 CA ILE A 100 0.897 13.774 -0.510 1.00 6.08 C ATOM 801 C ILE A 100 -0.327 13.626 -1.411 1.00 6.08 C ATOM 802 CB ILE A 100 0.475 14.281 0.887 1.00 6.08 C ATOM 803 O ILE A 100 -0.866 14.619 -1.905 1.00 6.08 O ATOM 804 CG1 ILE A 100 1.693 14.364 1.815 1.00 6.08 C ATOM 805 CG2 ILE A 100 -0.608 13.379 1.485 1.00 6.08 C ATOM 806 CD1 ILE A 100 1.410 15.041 3.149 1.00 6.08 C ATOM 807 N LYS A 101 -0.627 12.452 -2.003 1.00 6.08 N ATOM 808 CA LYS A 101 -1.914 12.267 -2.668 1.00 6.08 C ATOM 809 C LYS A 101 -2.834 11.369 -1.846 1.00 6.08 C ATOM 810 CB LYS A 101 -1.717 11.677 -4.065 1.00 6.08 C ATOM 811 O LYS A 101 -2.372 10.433 -1.190 1.00 6.08 O ATOM 812 CG LYS A 101 -1.039 12.621 -5.046 1.00 6.08 C ATOM 813 CD LYS A 101 -1.055 12.062 -6.463 1.00 6.08 C ATOM 814 CE LYS A 101 -0.350 12.992 -7.441 1.00 6.08 C ATOM 815 NZ LYS A 101 -0.430 12.486 -8.844 1.00 6.08 N ATOM 816 N GLU A 102 -3.972 11.868 -1.441 1.00 6.08 N ATOM 817 CA GLU A 102 -5.024 11.157 -0.721 1.00 6.08 C ATOM 818 C GLU A 102 -6.074 10.605 -1.681 1.00 6.08 C ATOM 819 CB GLU A 102 -5.686 12.076 0.310 1.00 6.08 C ATOM 820 O GLU A 102 -6.525 11.308 -2.587 1.00 6.08 O ATOM 821 CG GLU A 102 -6.179 11.350 1.553 1.00 6.08 C ATOM 822 CD GLU A 102 -6.742 12.286 2.611 1.00 6.08 C ATOM 823 OE1 GLU A 102 -7.929 12.141 2.980 1.00 6.08 O ATOM 824 OE2 GLU A 102 -5.989 13.172 3.073 1.00 6.08 O ATOM 825 N TYR A 103 -6.415 9.341 -1.509 1.00 5.36 N ATOM 826 CA TYR A 103 -7.466 8.743 -2.325 1.00 5.36 C ATOM 827 C TYR A 103 -8.614 8.244 -1.456 1.00 5.36 C ATOM 828 CB TYR A 103 -6.906 7.589 -3.163 1.00 5.36 C ATOM 829 O TYR A 103 -8.406 7.443 -0.541 1.00 5.36 O ATOM 830 CG TYR A 103 -5.758 7.990 -4.057 1.00 5.36 C ATOM 831 CD1 TYR A 103 -4.440 7.899 -3.614 1.00 5.36 C ATOM 832 CD2 TYR A 103 -5.988 8.459 -5.345 1.00 5.36 C ATOM 833 CE1 TYR A 103 -3.379 8.269 -4.434 1.00 5.36 C ATOM 834 CE2 TYR A 103 -4.935 8.832 -6.174 1.00 5.36 C ATOM 835 OH TYR A 103 -2.589 9.101 -6.526 1.00 5.36 O ATOM 836 CZ TYR A 103 -3.636 8.733 -5.710 1.00 5.36 C ATOM 837 N LYS A 104 -9.836 8.844 -1.571 1.00 6.08 N ATOM 838 CA LYS A 104 -11.038 8.471 -0.832 1.00 6.08 C ATOM 839 C LYS A 104 -11.649 7.188 -1.387 1.00 6.08 C ATOM 840 CB LYS A 104 -12.066 9.602 -0.872 1.00 6.08 C ATOM 841 O LYS A 104 -11.782 7.033 -2.603 1.00 6.08 O ATOM 842 CG LYS A 104 -13.244 9.402 0.070 1.00 6.08 C ATOM 843 CD LYS A 104 -14.209 10.579 0.017 1.00 6.08 C ATOM 844 CE LYS A 104 -15.411 10.360 0.925 1.00 6.08 C ATOM 845 NZ LYS A 104 -16.346 11.524 0.898 1.00 6.08 N ATOM 846 N PHE A 105 -11.952 6.243 -0.555 1.00 6.08 N ATOM 847 CA PHE A 105 -12.601 4.981 -0.891 1.00 6.08 C ATOM 848 C PHE A 105 -14.029 4.948 -0.359 1.00 6.08 C ATOM 849 CB PHE A 105 -11.804 3.799 -0.330 1.00 6.08 C ATOM 850 O PHE A 105 -14.252 5.098 0.844 1.00 6.08 O ATOM 851 CG PHE A 105 -11.481 2.744 -1.354 1.00 6.08 C ATOM 852 CD1 PHE A 105 -10.418 2.913 -2.234 1.00 6.08 C ATOM 853 CD2 PHE A 105 -12.239 1.584 -1.436 1.00 6.08 C ATOM 854 CE1 PHE A 105 -10.116 1.938 -3.182 1.00 6.08 C ATOM 855 CE2 PHE A 105 -11.944 0.606 -2.382 1.00 6.08 C ATOM 856 CZ PHE A 105 -10.883 0.785 -3.254 1.00 6.08 C ATOM 857 N GLY A 106 -15.105 4.749 -1.141 1.00 6.08 N ATOM 858 CA GLY A 106 -16.469 4.462 -0.727 1.00 6.08 C ATOM 859 C GLY A 106 -17.097 5.584 0.078 1.00 6.08 C ATOM 860 O GLY A 106 -16.419 6.547 0.445 1.00 6.08 O ATOM 861 N THR A 107 -18.460 5.770 -0.034 1.00 6.08 N ATOM 862 CA THR A 107 -19.388 6.728 0.555 1.00 6.08 C ATOM 863 C THR A 107 -20.150 6.098 1.717 1.00 6.08 C ATOM 864 CB THR A 107 -20.386 7.256 -0.492 1.00 6.08 C ATOM 865 O THR A 107 -21.036 5.267 1.507 1.00 6.08 O ATOM 866 CG2 THR A 107 -19.699 8.182 -1.490 1.00 6.08 C ATOM 867 OG1 THR A 107 -20.957 6.148 -1.200 1.00 6.08 O ATOM 868 N ARG A 108 -19.518 5.476 2.709 1.00 6.08 N ATOM 869 CA ARG A 108 -20.503 5.366 3.780 1.00 6.08 C ATOM 870 C ARG A 108 -20.263 6.422 4.855 1.00 6.08 C ATOM 871 CB ARG A 108 -20.469 3.968 4.402 1.00 6.08 C ATOM 872 O ARG A 108 -19.123 6.646 5.268 1.00 6.08 O ATOM 873 CG ARG A 108 -21.303 2.941 3.653 1.00 6.08 C ATOM 874 CD ARG A 108 -21.351 1.609 4.389 1.00 6.08 C ATOM 875 NE ARG A 108 -22.338 0.706 3.804 1.00 6.08 N ATOM 876 NH1 ARG A 108 -22.022 -0.977 5.356 1.00 6.08 N ATOM 877 NH2 ARG A 108 -23.549 -1.241 3.667 1.00 6.08 N ATOM 878 CZ ARG A 108 -22.634 -0.502 4.277 1.00 6.08 C ATOM 879 N THR A 109 -21.000 7.550 4.650 1.00 6.08 N ATOM 880 CA THR A 109 -21.263 8.726 5.472 1.00 6.08 C ATOM 881 C THR A 109 -21.852 8.323 6.821 1.00 6.08 C ATOM 882 CB THR A 109 -22.219 9.702 4.762 1.00 6.08 C ATOM 883 O THR A 109 -22.761 7.492 6.883 1.00 6.08 O ATOM 884 CG2 THR A 109 -21.477 10.545 3.730 1.00 6.08 C ATOM 885 OG1 THR A 109 -23.249 8.956 4.102 1.00 6.08 O ATOM 886 N GLY A 110 -21.151 8.030 7.805 1.00 6.08 N ATOM 887 CA GLY A 110 -21.715 8.302 9.117 1.00 6.08 C ATOM 888 C GLY A 110 -20.888 7.731 10.253 1.00 6.08 C ATOM 889 O GLY A 110 -20.720 6.514 10.354 1.00 6.08 O ATOM 890 N GLY A 111 -20.142 8.505 10.862 1.00 6.08 N ATOM 891 CA GLY A 111 -19.936 8.533 12.301 1.00 6.08 C ATOM 892 C GLY A 111 -18.518 8.904 12.693 1.00 6.08 C ATOM 893 O GLY A 111 -17.638 9.007 11.836 1.00 6.08 O ATOM 894 N ASN A 112 -18.313 9.718 13.747 1.00 6.08 N ATOM 895 CA ASN A 112 -17.174 10.179 14.534 1.00 6.08 C ATOM 896 C ASN A 112 -16.127 9.082 14.702 1.00 6.08 C ATOM 897 CB ASN A 112 -17.637 10.685 15.902 1.00 6.08 C ATOM 898 O ASN A 112 -16.444 7.978 15.149 1.00 6.08 O ATOM 899 CG ASN A 112 -18.364 12.013 15.817 1.00 6.08 C ATOM 900 ND2 ASN A 112 -19.255 12.262 16.770 1.00 6.08 N ATOM 901 OD1 ASN A 112 -18.128 12.807 14.904 1.00 6.08 O ATOM 902 N PHE A 113 -14.987 8.972 14.050 1.00 6.08 N ATOM 903 CA PHE A 113 -14.107 7.891 14.478 1.00 6.08 C ATOM 904 C PHE A 113 -12.665 8.373 14.576 1.00 6.08 C ATOM 905 CB PHE A 113 -14.201 6.706 13.512 1.00 6.08 C ATOM 906 O PHE A 113 -12.245 9.251 13.819 1.00 6.08 O ATOM 907 CG PHE A 113 -15.131 5.617 13.975 1.00 6.08 C ATOM 908 CD1 PHE A 113 -16.472 5.629 13.613 1.00 6.08 C ATOM 909 CD2 PHE A 113 -14.664 4.581 14.774 1.00 6.08 C ATOM 910 CE1 PHE A 113 -17.336 4.623 14.040 1.00 6.08 C ATOM 911 CE2 PHE A 113 -15.520 3.572 15.204 1.00 6.08 C ATOM 912 CZ PHE A 113 -16.856 3.595 14.837 1.00 6.08 C ATOM 913 N THR A 114 -11.825 7.651 15.237 1.00 6.08 N ATOM 914 CA THR A 114 -10.413 7.467 15.554 1.00 6.08 C ATOM 915 C THR A 114 -10.065 5.983 15.631 1.00 6.08 C ATOM 916 CB THR A 114 -10.044 8.154 16.882 1.00 6.08 C ATOM 917 O THR A 114 -10.307 5.336 16.652 1.00 6.08 O ATOM 918 CG2 THR A 114 -10.124 9.672 16.757 1.00 6.08 C ATOM 919 OG1 THR A 114 -10.951 7.722 17.904 1.00 6.08 O ATOM 920 N GLY A 115 -10.385 5.096 14.476 1.00 6.08 N ATOM 921 CA GLY A 115 -9.894 3.756 14.757 1.00 6.08 C ATOM 922 C GLY A 115 -9.108 3.156 13.607 1.00 6.08 C ATOM 923 O GLY A 115 -8.864 3.823 12.600 1.00 6.08 O ATOM 924 N GLU A 116 -8.292 2.078 13.803 1.00 6.08 N ATOM 925 CA GLU A 116 -7.455 1.166 13.029 1.00 6.08 C ATOM 926 C GLU A 116 -8.271 0.435 11.966 1.00 6.08 C ATOM 927 CB GLU A 116 -6.766 0.156 13.950 1.00 6.08 C ATOM 928 O GLU A 116 -9.471 0.214 12.141 1.00 6.08 O ATOM 929 CG GLU A 116 -5.620 0.745 14.760 1.00 6.08 C ATOM 930 CD GLU A 116 -4.833 -0.301 15.533 1.00 6.08 C ATOM 931 OE1 GLU A 116 -3.793 0.046 16.138 1.00 6.08 O ATOM 932 OE2 GLU A 116 -5.258 -1.478 15.533 1.00 6.08 O ATOM 933 N LEU A 117 -7.867 0.276 10.616 1.00 5.36 N ATOM 934 CA LEU A 117 -8.515 -0.475 9.546 1.00 5.36 C ATOM 935 C LEU A 117 -8.722 -1.930 9.952 1.00 5.36 C ATOM 936 CB LEU A 117 -7.684 -0.404 8.263 1.00 5.36 C ATOM 937 O LEU A 117 -7.933 -2.483 10.723 1.00 5.36 O ATOM 938 CG LEU A 117 -7.563 0.973 7.608 1.00 5.36 C ATOM 939 CD1 LEU A 117 -6.504 0.947 6.511 1.00 5.36 C ATOM 940 CD2 LEU A 117 -8.910 1.418 7.048 1.00 5.36 C ATOM 941 N THR A 118 -9.851 -2.455 9.647 1.00 5.36 N ATOM 942 CA THR A 118 -10.035 -3.895 9.790 1.00 5.36 C ATOM 943 C THR A 118 -9.157 -4.654 8.798 1.00 5.36 C ATOM 944 CB THR A 118 -11.508 -4.294 9.584 1.00 5.36 C ATOM 945 O THR A 118 -8.605 -4.060 7.869 1.00 5.36 O ATOM 946 CG2 THR A 118 -12.428 -3.487 10.493 1.00 5.36 C ATOM 947 OG1 THR A 118 -11.875 -4.057 8.219 1.00 5.36 O ATOM 948 N LYS A 119 -8.889 -5.923 9.112 1.00 6.08 N ATOM 949 CA LYS A 119 -8.123 -6.769 8.201 1.00 6.08 C ATOM 950 C LYS A 119 -8.726 -6.753 6.799 1.00 6.08 C ATOM 951 CB LYS A 119 -8.057 -8.204 8.727 1.00 6.08 C ATOM 952 O LYS A 119 -8.000 -6.675 5.806 1.00 6.08 O ATOM 953 CG LYS A 119 -7.022 -9.073 8.027 1.00 6.08 C ATOM 954 CD LYS A 119 -6.951 -10.463 8.644 1.00 6.08 C ATOM 955 CE LYS A 119 -6.004 -11.371 7.872 1.00 6.08 C ATOM 956 NZ LYS A 119 -5.944 -12.741 8.463 1.00 6.08 N ATOM 957 N GLN A 120 -10.033 -6.874 6.687 1.00 6.08 N ATOM 958 CA GLN A 120 -10.739 -6.867 5.410 1.00 6.08 C ATOM 959 C GLN A 120 -10.510 -5.558 4.661 1.00 6.08 C ATOM 960 CB GLN A 120 -12.236 -7.096 5.623 1.00 6.08 C ATOM 961 O GLN A 120 -10.287 -5.560 3.449 1.00 6.08 O ATOM 962 CG GLN A 120 -12.965 -7.594 4.383 1.00 6.08 C ATOM 963 CD GLN A 120 -14.269 -8.298 4.711 1.00 6.08 C ATOM 964 NE2 GLN A 120 -14.806 -9.032 3.742 1.00 6.08 N ATOM 965 OE1 GLN A 120 -14.788 -8.184 5.826 1.00 6.08 O ATOM 966 N GLU A 121 -10.563 -4.457 5.339 1.00 5.36 N ATOM 967 CA GLU A 121 -10.315 -3.150 4.738 1.00 5.36 C ATOM 968 C GLU A 121 -8.891 -3.052 4.198 1.00 5.36 C ATOM 969 CB GLU A 121 -10.571 -2.034 5.753 1.00 5.36 C ATOM 970 O GLU A 121 -8.667 -2.500 3.119 1.00 5.36 O ATOM 971 CG GLU A 121 -12.041 -1.836 6.092 1.00 5.36 C ATOM 972 CD GLU A 121 -12.266 -0.891 7.262 1.00 5.36 C ATOM 973 OE1 GLU A 121 -13.256 -0.126 7.243 1.00 5.36 O ATOM 974 OE2 GLU A 121 -11.443 -0.916 8.205 1.00 5.36 O ATOM 975 N LEU A 122 -7.942 -3.571 4.960 1.00 5.36 N ATOM 976 CA LEU A 122 -6.554 -3.544 4.512 1.00 5.36 C ATOM 977 C LEU A 122 -6.385 -4.331 3.217 1.00 5.36 C ATOM 978 CB LEU A 122 -5.632 -4.115 5.593 1.00 5.36 C ATOM 979 O LEU A 122 -5.705 -3.876 2.294 1.00 5.36 O ATOM 980 CG LEU A 122 -5.295 -3.183 6.758 1.00 5.36 C ATOM 981 CD1 LEU A 122 -4.667 -3.971 7.903 1.00 5.36 C ATOM 982 CD2 LEU A 122 -4.365 -2.066 6.298 1.00 5.36 C ATOM 983 N VAL A 123 -6.991 -5.567 3.232 1.00 5.36 N ATOM 984 CA VAL A 123 -6.926 -6.409 2.042 1.00 5.36 C ATOM 985 C VAL A 123 -7.518 -5.664 0.848 1.00 5.36 C ATOM 986 CB VAL A 123 -7.667 -7.749 2.255 1.00 5.36 C ATOM 987 O VAL A 123 -6.921 -5.633 -0.230 1.00 5.36 O ATOM 988 CG1 VAL A 123 -7.796 -8.509 0.936 1.00 5.36 C ATOM 989 CG2 VAL A 123 -6.942 -8.599 3.296 1.00 5.36 C ATOM 990 N TYR A 124 -8.671 -5.070 1.043 1.00 5.36 N ATOM 991 CA TYR A 124 -9.359 -4.338 -0.015 1.00 5.36 C ATOM 992 C TYR A 124 -8.521 -3.160 -0.496 1.00 5.36 C ATOM 993 CB TYR A 124 -10.724 -3.844 0.473 1.00 5.36 C ATOM 994 O TYR A 124 -8.387 -2.937 -1.702 1.00 5.36 O ATOM 995 CG TYR A 124 -11.884 -4.667 -0.033 1.00 5.36 C ATOM 996 CD1 TYR A 124 -12.554 -5.552 0.808 1.00 5.36 C ATOM 997 CD2 TYR A 124 -12.312 -4.561 -1.352 1.00 5.36 C ATOM 998 CE1 TYR A 124 -13.622 -6.314 0.346 1.00 5.36 C ATOM 999 CE2 TYR A 124 -13.379 -5.318 -1.825 1.00 5.36 C ATOM 1000 OH TYR A 124 -15.084 -6.942 -1.432 1.00 5.36 O ATOM 1001 CZ TYR A 124 -14.027 -6.190 -0.969 1.00 5.36 C ATOM 1002 N THR A 125 -8.064 -2.317 0.476 1.00 5.36 N ATOM 1003 CA THR A 125 -7.230 -1.175 0.117 1.00 5.36 C ATOM 1004 C THR A 125 -6.008 -1.626 -0.679 1.00 5.36 C ATOM 1005 CB THR A 125 -6.774 -0.402 1.368 1.00 5.36 C ATOM 1006 O THR A 125 -5.643 -0.999 -1.675 1.00 5.36 O ATOM 1007 CG2 THR A 125 -7.392 0.992 1.408 1.00 5.36 C ATOM 1008 OG1 THR A 125 -7.173 -1.123 2.540 1.00 5.36 O ATOM 1009 N ASN A 126 -5.437 -2.705 -0.271 1.00 5.36 N ATOM 1010 CA ASN A 126 -4.265 -3.214 -0.977 1.00 5.36 C ATOM 1011 C ASN A 126 -4.614 -3.656 -2.395 1.00 5.36 C ATOM 1012 CB ASN A 126 -3.631 -4.370 -0.201 1.00 5.36 C ATOM 1013 O ASN A 126 -3.866 -3.384 -3.336 1.00 5.36 O ATOM 1014 CG ASN A 126 -2.693 -3.896 0.891 1.00 5.36 C ATOM 1015 ND2 ASN A 126 -2.429 -4.760 1.864 1.00 5.36 N ATOM 1016 OD1 ASN A 126 -2.209 -2.761 0.861 1.00 5.36 O ATOM 1017 N GLN A 127 -5.691 -4.483 -2.497 1.00 5.36 N ATOM 1018 CA GLN A 127 -6.138 -4.897 -3.823 1.00 5.36 C ATOM 1019 C GLN A 127 -6.385 -3.689 -4.722 1.00 5.36 C ATOM 1020 CB GLN A 127 -7.407 -5.744 -3.721 1.00 5.36 C ATOM 1021 O GLN A 127 -5.973 -3.679 -5.884 1.00 5.36 O ATOM 1022 CG GLN A 127 -7.729 -6.525 -4.989 1.00 5.36 C ATOM 1023 CD GLN A 127 -8.927 -7.440 -4.826 1.00 5.36 C ATOM 1024 NE2 GLN A 127 -9.350 -8.064 -5.921 1.00 5.36 N ATOM 1025 OE1 GLN A 127 -9.468 -7.587 -3.726 1.00 5.36 O ATOM 1026 N TRP A 128 -7.149 -2.688 -4.151 1.00 5.36 N ATOM 1027 CA TRP A 128 -7.418 -1.471 -4.911 1.00 5.36 C ATOM 1028 C TRP A 128 -6.119 -0.818 -5.371 1.00 5.36 C ATOM 1029 CB TRP A 128 -8.232 -0.482 -4.072 1.00 5.36 C ATOM 1030 O TRP A 128 -5.992 -0.427 -6.534 1.00 5.36 O ATOM 1031 CG TRP A 128 -8.637 0.757 -4.813 1.00 5.36 C ATOM 1032 CD1 TRP A 128 -9.759 0.931 -5.576 1.00 5.36 C ATOM 1033 CD2 TRP A 128 -7.919 1.993 -4.866 1.00 5.36 C ATOM 1034 CE2 TRP A 128 -8.665 2.875 -5.680 1.00 5.36 C ATOM 1035 CE3 TRP A 128 -6.717 2.442 -4.304 1.00 5.36 C ATOM 1036 NE1 TRP A 128 -9.781 2.203 -6.099 1.00 5.36 N ATOM 1037 CH2 TRP A 128 -7.067 4.595 -5.381 1.00 5.36 C ATOM 1038 CZ2 TRP A 128 -8.247 4.181 -5.944 1.00 5.36 C ATOM 1039 CZ3 TRP A 128 -6.302 3.742 -4.568 1.00 5.36 C ATOM 1040 N VAL A 129 -5.185 -0.613 -4.368 1.00 4.42 N ATOM 1041 CA VAL A 129 -3.899 -0.000 -4.687 1.00 4.42 C ATOM 1042 C VAL A 129 -3.213 -0.789 -5.800 1.00 4.42 C ATOM 1043 CB VAL A 129 -2.983 0.077 -3.446 1.00 4.42 C ATOM 1044 O VAL A 129 -2.691 -0.205 -6.753 1.00 4.42 O ATOM 1045 CG1 VAL A 129 -1.562 0.471 -3.846 1.00 4.42 C ATOM 1046 CG2 VAL A 129 -3.548 1.065 -2.427 1.00 4.42 C ATOM 1047 N ASN A 130 -3.323 -2.084 -5.765 1.00 5.36 N ATOM 1048 CA ASN A 130 -2.699 -2.948 -6.762 1.00 5.36 C ATOM 1049 C ASN A 130 -3.320 -2.751 -8.142 1.00 5.36 C ATOM 1050 CB ASN A 130 -2.799 -4.415 -6.339 1.00 5.36 C ATOM 1051 O ASN A 130 -2.613 -2.751 -9.151 1.00 5.36 O ATOM 1052 CG ASN A 130 -1.767 -4.793 -5.294 1.00 5.36 C ATOM 1053 ND2 ASN A 130 -2.027 -5.874 -4.568 1.00 5.36 N ATOM 1054 OD1 ASN A 130 -0.746 -4.118 -5.140 1.00 5.36 O ATOM 1055 N GLU A 131 -4.600 -2.603 -8.153 1.00 5.36 N ATOM 1056 CA GLU A 131 -5.337 -2.535 -9.412 1.00 5.36 C ATOM 1057 C GLU A 131 -5.256 -1.140 -10.024 1.00 5.36 C ATOM 1058 CB GLU A 131 -6.800 -2.932 -9.200 1.00 5.36 C ATOM 1059 O GLU A 131 -5.324 -0.988 -11.246 1.00 5.36 O ATOM 1060 CG GLU A 131 -7.000 -4.413 -8.911 1.00 5.36 C ATOM 1061 CD GLU A 131 -8.445 -4.776 -8.611 1.00 5.36 C ATOM 1062 OE1 GLU A 131 -8.733 -5.970 -8.365 1.00 5.36 O ATOM 1063 OE2 GLU A 131 -9.297 -3.860 -8.623 1.00 5.36 O ATOM 1064 N ASN A 132 -5.147 -0.162 -9.186 1.00 5.36 N ATOM 1065 CA ASN A 132 -5.357 1.190 -9.693 1.00 5.36 C ATOM 1066 C ASN A 132 -4.037 1.936 -9.863 1.00 5.36 C ATOM 1067 CB ASN A 132 -6.292 1.971 -8.767 1.00 5.36 C ATOM 1068 O ASN A 132 -3.931 2.838 -10.696 1.00 5.36 O ATOM 1069 CG ASN A 132 -7.729 1.494 -8.851 1.00 5.36 C ATOM 1070 ND2 ASN A 132 -8.165 0.745 -7.845 1.00 5.36 N ATOM 1071 OD1 ASN A 132 -8.441 1.795 -9.813 1.00 5.36 O ATOM 1072 N ILE A 133 -3.015 1.608 -8.992 1.00 5.36 N ATOM 1073 CA ILE A 133 -1.781 2.384 -9.062 1.00 5.36 C ATOM 1074 C ILE A 133 -0.907 1.861 -10.200 1.00 5.36 C ATOM 1075 CB ILE A 133 -1.007 2.336 -7.726 1.00 5.36 C ATOM 1076 O ILE A 133 -0.112 2.609 -10.773 1.00 5.36 O ATOM 1077 CG1 ILE A 133 -1.777 3.089 -6.635 1.00 5.36 C ATOM 1078 CG2 ILE A 133 0.402 2.911 -7.897 1.00 5.36 C ATOM 1079 CD1 ILE A 133 -1.113 3.045 -5.266 1.00 5.36 C ATOM 1080 N THR A 134 -1.214 0.937 -10.975 1.00 6.08 N ATOM 1081 CA THR A 134 -0.412 0.479 -12.104 1.00 6.08 C ATOM 1082 C THR A 134 -0.466 1.485 -13.250 1.00 6.08 C ATOM 1083 CB THR A 134 -0.887 -0.898 -12.605 1.00 6.08 C ATOM 1084 O THR A 134 0.513 1.656 -13.980 1.00 6.08 O ATOM 1085 CG2 THR A 134 0.024 -2.012 -12.097 1.00 6.08 C ATOM 1086 OG1 THR A 134 -2.220 -1.137 -12.137 1.00 6.08 O ATOM 1087 N LEU A 135 -1.656 2.194 -13.502 1.00 6.08 N ATOM 1088 CA LEU A 135 -2.187 2.386 -14.847 1.00 6.08 C ATOM 1089 C LEU A 135 -2.051 3.841 -15.283 1.00 6.08 C ATOM 1090 CB LEU A 135 -3.656 1.958 -14.908 1.00 6.08 C ATOM 1091 O LEU A 135 -2.144 4.147 -16.474 1.00 6.08 O ATOM 1092 CG LEU A 135 -3.923 0.452 -14.925 1.00 6.08 C ATOM 1093 CD1 LEU A 135 -5.388 0.171 -14.609 1.00 6.08 C ATOM 1094 CD2 LEU A 135 -3.538 -0.144 -16.274 1.00 6.08 C ATOM 1095 N ALA A 136 -1.314 4.761 -14.697 1.00 6.08 N ATOM 1096 CA ALA A 136 -1.322 5.912 -15.597 1.00 6.08 C ATOM 1097 C ALA A 136 0.036 6.607 -15.610 1.00 6.08 C ATOM 1098 CB ALA A 136 -2.417 6.896 -15.193 1.00 6.08 C ATOM 1099 O ALA A 136 0.626 6.851 -14.555 1.00 6.08 O ATOM 1100 N ASN A 137 1.001 6.147 -16.376 1.00 6.08 N ATOM 1101 CA ASN A 137 1.962 7.100 -16.923 1.00 6.08 C ATOM 1102 C ASN A 137 2.561 7.982 -15.832 1.00 6.08 C ATOM 1103 CB ASN A 137 1.305 7.963 -18.003 1.00 6.08 C ATOM 1104 O ASN A 137 2.685 9.196 -16.007 1.00 6.08 O ATOM 1105 CG ASN A 137 1.244 7.267 -19.349 1.00 6.08 C ATOM 1106 ND2 ASN A 137 0.354 7.734 -20.218 1.00 6.08 N ATOM 1107 OD1 ASN A 137 1.989 6.318 -19.606 1.00 6.08 O ATOM 1108 N GLY A 138 2.939 7.445 -14.762 1.00 6.08 N ATOM 1109 CA GLY A 138 3.642 8.286 -13.808 1.00 6.08 C ATOM 1110 C GLY A 138 2.721 9.212 -13.036 1.00 6.08 C ATOM 1111 O GLY A 138 3.179 10.003 -12.209 1.00 6.08 O ATOM 1112 N TYR A 139 1.463 9.234 -13.302 1.00 6.08 N ATOM 1113 CA TYR A 139 0.469 10.113 -12.696 1.00 6.08 C ATOM 1114 C TYR A 139 -0.736 9.318 -12.207 1.00 6.08 C ATOM 1115 CB TYR A 139 0.019 11.184 -13.694 1.00 6.08 C ATOM 1116 O TYR A 139 -1.121 8.321 -12.822 1.00 6.08 O ATOM 1117 CG TYR A 139 0.919 12.395 -13.732 1.00 6.08 C ATOM 1118 CD1 TYR A 139 1.986 12.467 -14.625 1.00 6.08 C ATOM 1119 CD2 TYR A 139 0.705 13.469 -12.874 1.00 6.08 C ATOM 1120 CE1 TYR A 139 2.819 13.580 -14.662 1.00 6.08 C ATOM 1121 CE2 TYR A 139 1.532 14.587 -12.903 1.00 6.08 C ATOM 1122 OH TYR A 139 3.406 15.738 -13.831 1.00 6.08 O ATOM 1123 CZ TYR A 139 2.584 14.634 -13.799 1.00 6.08 C ATOM 1124 N ILE A 140 -0.939 9.058 -10.837 1.00 6.08 N ATOM 1125 CA ILE A 140 -2.155 8.654 -10.138 1.00 6.08 C ATOM 1126 C ILE A 140 -3.276 9.645 -10.440 1.00 6.08 C ATOM 1127 CB ILE A 140 -1.924 8.553 -8.614 1.00 6.08 C ATOM 1128 O ILE A 140 -3.182 10.824 -10.091 1.00 6.08 O ATOM 1129 CG1 ILE A 140 -0.789 7.569 -8.310 1.00 6.08 C ATOM 1130 CG2 ILE A 140 -3.213 8.140 -7.899 1.00 6.08 C ATOM 1131 CD1 ILE A 140 -0.415 7.492 -6.836 1.00 6.08 C ATOM 1132 N SER A 141 -3.684 9.839 -11.715 1.00 6.08 N ATOM 1133 CA SER A 141 -4.883 10.669 -11.786 1.00 6.08 C ATOM 1134 C SER A 141 -6.105 9.922 -11.262 1.00 6.08 C ATOM 1135 CB SER A 141 -5.133 11.127 -13.224 1.00 6.08 C ATOM 1136 O SER A 141 -6.378 8.796 -11.682 1.00 6.08 O ATOM 1137 OG SER A 141 -6.496 10.963 -13.574 1.00 6.08 O ATOM 1138 N ALA A 142 -6.198 9.687 -9.878 1.00 6.08 N ATOM 1139 CA ALA A 142 -7.356 9.155 -9.164 1.00 6.08 C ATOM 1140 C ALA A 142 -8.656 9.539 -9.865 1.00 6.08 C ATOM 1141 CB ALA A 142 -7.366 9.651 -7.721 1.00 6.08 C ATOM 1142 O ALA A 142 -8.874 10.710 -10.184 1.00 6.08 O ATOM 1143 N ASP A 143 -9.016 8.898 -10.877 1.00 6.08 N ATOM 1144 CA ASP A 143 -10.425 8.964 -11.253 1.00 6.08 C ATOM 1145 C ASP A 143 -11.295 9.345 -10.057 1.00 6.08 C ATOM 1146 CB ASP A 143 -10.889 7.628 -11.836 1.00 6.08 C ATOM 1147 O ASP A 143 -11.158 8.769 -8.975 1.00 6.08 O ATOM 1148 CG ASP A 143 -11.385 7.746 -13.267 1.00 6.08 C ATOM 1149 OD1 ASP A 143 -11.573 6.706 -13.934 1.00 6.08 O ATOM 1150 OD2 ASP A 143 -11.586 8.889 -13.731 1.00 6.08 O ATOM 1151 N SER A 144 -11.432 10.610 -9.724 1.00 6.08 N ATOM 1152 CA SER A 144 -12.633 11.251 -9.197 1.00 6.08 C ATOM 1153 C SER A 144 -13.803 10.274 -9.147 1.00 6.08 C ATOM 1154 CB SER A 144 -13.009 12.466 -10.046 1.00 6.08 C ATOM 1155 O SER A 144 -14.946 10.678 -8.919 1.00 6.08 O ATOM 1156 OG SER A 144 -12.987 12.143 -11.426 1.00 6.08 O ATOM 1157 N ARG A 145 -13.625 8.971 -9.055 1.00 6.08 N ATOM 1158 CA ARG A 145 -14.877 8.231 -8.942 1.00 6.08 C ATOM 1159 C ARG A 145 -15.517 8.442 -7.574 1.00 6.08 C ATOM 1160 CB ARG A 145 -14.644 6.738 -9.187 1.00 6.08 C ATOM 1161 O ARG A 145 -14.826 8.444 -6.554 1.00 6.08 O ATOM 1162 CG ARG A 145 -14.402 6.383 -10.645 1.00 6.08 C ATOM 1163 CD ARG A 145 -14.336 4.877 -10.856 1.00 6.08 C ATOM 1164 NE ARG A 145 -13.186 4.497 -11.671 1.00 6.08 N ATOM 1165 NH1 ARG A 145 -13.735 2.255 -11.769 1.00 6.08 N ATOM 1166 NH2 ARG A 145 -11.852 3.025 -12.824 1.00 6.08 N ATOM 1167 CZ ARG A 145 -12.927 3.260 -12.086 1.00 6.08 C ATOM 1168 N THR A 146 -16.379 9.419 -7.415 1.00 6.08 N ATOM 1169 CA THR A 146 -17.507 9.485 -6.494 1.00 6.08 C ATOM 1170 C THR A 146 -18.280 8.169 -6.491 1.00 6.08 C ATOM 1171 CB THR A 146 -18.458 10.641 -6.856 1.00 6.08 C ATOM 1172 O THR A 146 -18.534 7.590 -7.549 1.00 6.08 O ATOM 1173 CG2 THR A 146 -18.028 11.939 -6.180 1.00 6.08 C ATOM 1174 OG1 THR A 146 -18.451 10.830 -8.276 1.00 6.08 O ATOM 1175 N VAL A 147 -17.785 7.142 -5.708 1.00 6.08 N ATOM 1176 CA VAL A 147 -18.621 5.978 -5.435 1.00 6.08 C ATOM 1177 C VAL A 147 -20.048 6.427 -5.126 1.00 6.08 C ATOM 1178 CB VAL A 147 -18.061 5.139 -4.264 1.00 6.08 C ATOM 1179 O VAL A 147 -20.261 7.305 -4.287 1.00 6.08 O ATOM 1180 CG1 VAL A 147 -18.638 3.725 -4.289 1.00 6.08 C ATOM 1181 CG2 VAL A 147 -16.535 5.098 -4.321 1.00 6.08 C ATOM 1182 N ASP A 148 -20.960 6.728 -6.190 1.00 6.08 N ATOM 1183 CA ASP A 148 -22.394 6.829 -5.938 1.00 6.08 C ATOM 1184 C ASP A 148 -22.901 5.619 -5.157 1.00 6.08 C ATOM 1185 CB ASP A 148 -23.162 6.965 -7.254 1.00 6.08 C ATOM 1186 O ASP A 148 -22.505 4.485 -5.432 1.00 6.08 O ATOM 1187 CG ASP A 148 -22.902 8.285 -7.959 1.00 6.08 C ATOM 1188 OD1 ASP A 148 -23.140 8.380 -9.182 1.00 6.08 O ATOM 1189 OD2 ASP A 148 -22.451 9.237 -7.286 1.00 6.08 O TER 1190 ASP A 148 ENDMDL END ================================================ FILE: alphafold/relax/testdata/with_violations_casp14.pdb ================================================ MODEL 0 ATOM 1 N SER A 1 27.311 -3.395 37.375 1.00 8.64 N ATOM 2 CA SER A 1 26.072 -4.109 37.084 1.00 8.64 C ATOM 3 C SER A 1 26.047 -4.608 35.643 1.00 8.64 C ATOM 4 CB SER A 1 24.862 -3.211 37.342 1.00 8.64 C ATOM 5 O SER A 1 26.782 -4.101 34.792 1.00 8.64 O ATOM 6 OG SER A 1 24.740 -2.228 36.329 1.00 8.64 O ATOM 7 N PHE A 2 25.619 -5.987 35.357 1.00 8.64 N ATOM 8 CA PHE A 2 25.448 -6.479 33.995 1.00 8.64 C ATOM 9 C PHE A 2 25.049 -5.347 33.056 1.00 8.64 C ATOM 10 CB PHE A 2 24.395 -7.591 33.953 1.00 8.64 C ATOM 11 O PHE A 2 25.590 -5.226 31.955 1.00 8.64 O ATOM 12 CG PHE A 2 24.140 -8.134 32.573 1.00 8.64 C ATOM 13 CD1 PHE A 2 25.003 -9.063 32.006 1.00 8.64 C ATOM 14 CD2 PHE A 2 23.036 -7.714 31.842 1.00 8.64 C ATOM 15 CE1 PHE A 2 24.770 -9.567 30.728 1.00 8.64 C ATOM 16 CE2 PHE A 2 22.796 -8.214 30.565 1.00 8.64 C ATOM 17 CZ PHE A 2 23.665 -9.139 30.010 1.00 8.64 C ATOM 18 N GLU A 3 24.279 -4.453 33.583 1.00 8.64 N ATOM 19 CA GLU A 3 23.756 -3.316 32.831 1.00 8.64 C ATOM 20 C GLU A 3 24.858 -2.308 32.517 1.00 8.64 C ATOM 21 CB GLU A 3 22.624 -2.635 33.604 1.00 8.64 C ATOM 22 O GLU A 3 24.963 -1.828 31.387 1.00 8.64 O ATOM 23 CG GLU A 3 21.251 -3.239 33.345 1.00 8.64 C ATOM 24 CD GLU A 3 20.291 -3.067 34.511 1.00 8.64 C ATOM 25 OE1 GLU A 3 19.129 -3.525 34.413 1.00 8.64 O ATOM 26 OE2 GLU A 3 20.702 -2.469 35.530 1.00 8.64 O ATOM 27 N GLU A 4 25.795 -2.118 33.499 1.00 8.64 N ATOM 28 CA GLU A 4 26.873 -1.150 33.321 1.00 8.64 C ATOM 29 C GLU A 4 27.923 -1.667 32.341 1.00 8.64 C ATOM 30 CB GLU A 4 27.526 -0.820 34.666 1.00 8.64 C ATOM 31 O GLU A 4 28.401 -0.920 31.485 1.00 8.64 O ATOM 32 CG GLU A 4 26.709 0.130 35.529 1.00 8.64 C ATOM 33 CD GLU A 4 27.351 0.416 36.878 1.00 8.64 C ATOM 34 OE1 GLU A 4 26.801 1.234 37.650 1.00 8.64 O ATOM 35 OE2 GLU A 4 28.412 -0.182 37.164 1.00 8.64 O ATOM 36 N GLN A 5 28.078 -2.983 32.335 1.00 8.64 N ATOM 37 CA GLN A 5 29.050 -3.614 31.449 1.00 8.64 C ATOM 38 C GLN A 5 28.520 -3.696 30.020 1.00 8.64 C ATOM 39 CB GLN A 5 29.410 -5.012 31.956 1.00 8.64 C ATOM 40 O GLN A 5 29.268 -3.487 29.063 1.00 8.64 O ATOM 41 CG GLN A 5 30.587 -5.031 32.922 1.00 8.64 C ATOM 42 CD GLN A 5 30.906 -6.425 33.430 1.00 8.64 C ATOM 43 NE2 GLN A 5 31.803 -6.509 34.407 1.00 8.64 N ATOM 44 OE1 GLN A 5 30.350 -7.418 32.950 1.00 8.64 O ATOM 45 N PHE A 6 27.127 -3.824 29.849 1.00 8.64 N ATOM 46 CA PHE A 6 26.442 -3.868 28.562 1.00 8.64 C ATOM 47 C PHE A 6 26.501 -2.512 27.870 1.00 8.64 C ATOM 48 CB PHE A 6 24.983 -4.302 28.744 1.00 8.64 C ATOM 49 O PHE A 6 26.819 -2.429 26.682 1.00 8.64 O ATOM 50 CG PHE A 6 24.232 -4.461 27.450 1.00 8.64 C ATOM 51 CD1 PHE A 6 24.326 -5.636 26.715 1.00 8.64 C ATOM 52 CD2 PHE A 6 23.431 -3.434 26.968 1.00 8.64 C ATOM 53 CE1 PHE A 6 23.631 -5.786 25.517 1.00 8.64 C ATOM 54 CE2 PHE A 6 22.734 -3.576 25.771 1.00 8.64 C ATOM 55 CZ PHE A 6 22.836 -4.753 25.047 1.00 8.64 C ATOM 56 N ILE A 7 26.367 -1.421 28.620 1.00 8.64 N ATOM 57 CA ILE A 7 26.395 -0.058 28.103 1.00 8.64 C ATOM 58 C ILE A 7 27.816 0.304 27.677 1.00 8.64 C ATOM 59 CB ILE A 7 25.874 0.954 29.148 1.00 8.64 C ATOM 60 O ILE A 7 28.020 0.896 26.614 1.00 8.64 O ATOM 61 CG1 ILE A 7 24.383 0.725 29.417 1.00 8.64 C ATOM 62 CG2 ILE A 7 26.133 2.391 28.685 1.00 8.64 C ATOM 63 CD1 ILE A 7 23.831 1.540 30.579 1.00 8.64 C ATOM 64 N LYS A 8 28.765 -0.137 28.420 1.00 8.64 N ATOM 65 CA LYS A 8 30.171 0.158 28.160 1.00 8.64 C ATOM 66 C LYS A 8 30.668 -0.584 26.922 1.00 8.64 C ATOM 67 CB LYS A 8 31.030 -0.210 29.371 1.00 8.64 C ATOM 68 O LYS A 8 31.368 -0.008 26.086 1.00 8.64 O ATOM 69 CG LYS A 8 32.396 0.462 29.387 1.00 8.64 C ATOM 70 CD LYS A 8 33.170 0.123 30.655 1.00 8.64 C ATOM 71 CE LYS A 8 34.584 0.686 30.615 1.00 8.64 C ATOM 72 NZ LYS A 8 35.350 0.348 31.852 1.00 8.64 N ATOM 73 N ASN A 9 30.138 -1.772 26.738 1.00 8.64 N ATOM 74 CA ASN A 9 30.622 -2.602 25.640 1.00 8.64 C ATOM 75 C ASN A 9 29.908 -2.274 24.332 1.00 8.64 C ATOM 76 CB ASN A 9 30.461 -4.086 25.976 1.00 8.64 C ATOM 77 O ASN A 9 30.396 -2.610 23.252 1.00 8.64 O ATOM 78 CG ASN A 9 31.429 -4.551 27.046 1.00 8.64 C ATOM 79 ND2 ASN A 9 31.123 -5.682 27.670 1.00 8.64 N ATOM 80 OD1 ASN A 9 32.442 -3.898 27.310 1.00 8.64 O ATOM 81 N ASN A 10 28.860 -1.389 24.447 1.00 8.64 N ATOM 82 CA ASN A 10 28.104 -1.128 23.227 1.00 8.64 C ATOM 83 C ASN A 10 28.029 0.366 22.923 1.00 8.64 C ATOM 84 CB ASN A 10 26.697 -1.720 23.330 1.00 8.64 C ATOM 85 O ASN A 10 27.356 0.778 21.977 1.00 8.64 O ATOM 86 CG ASN A 10 26.693 -3.234 23.250 1.00 8.64 C ATOM 87 ND2 ASN A 10 26.544 -3.888 24.396 1.00 8.64 N ATOM 88 OD1 ASN A 10 26.823 -3.811 22.167 1.00 8.64 O ATOM 89 N SER A 11 28.833 1.149 23.636 1.00 8.64 N ATOM 90 CA SER A 11 28.835 2.602 23.500 1.00 8.64 C ATOM 91 C SER A 11 29.617 3.040 22.266 1.00 8.64 C ATOM 92 CB SER A 11 29.427 3.257 24.748 1.00 8.64 C ATOM 93 O SER A 11 29.395 4.132 21.740 1.00 8.64 O ATOM 94 OG SER A 11 30.701 2.712 25.046 1.00 8.64 O ATOM 95 N ASP A 12 30.212 2.067 21.630 1.00 8.64 N ATOM 96 CA ASP A 12 30.855 2.541 20.408 1.00 8.64 C ATOM 97 C ASP A 12 29.975 2.284 19.188 1.00 8.64 C ATOM 98 CB ASP A 12 32.218 1.871 20.224 1.00 8.64 C ATOM 99 O ASP A 12 30.218 2.836 18.113 1.00 8.64 O ATOM 100 CG ASP A 12 33.270 2.391 21.189 1.00 8.64 C ATOM 101 OD1 ASP A 12 34.250 1.668 21.471 1.00 8.64 O ATOM 102 OD2 ASP A 12 33.116 3.533 21.673 1.00 8.64 O ATOM 103 N SER A 13 28.711 1.753 19.485 1.00 8.64 N ATOM 104 CA SER A 13 27.850 1.458 18.344 1.00 8.64 C ATOM 105 C SER A 13 26.738 2.492 18.209 1.00 8.64 C ATOM 106 CB SER A 13 27.245 0.060 18.477 1.00 8.64 C ATOM 107 O SER A 13 26.268 3.040 19.208 1.00 8.64 O ATOM 108 OG SER A 13 26.522 -0.062 19.690 1.00 8.64 O ATOM 109 N ASN A 14 26.876 3.556 17.578 1.00 8.64 N ATOM 110 CA ASN A 14 25.876 4.507 17.103 1.00 8.64 C ATOM 111 C ASN A 14 24.502 3.857 16.973 1.00 8.64 C ATOM 112 CB ASN A 14 26.306 5.114 15.766 1.00 8.64 C ATOM 113 O ASN A 14 23.638 4.361 16.252 1.00 8.64 O ATOM 114 CG ASN A 14 27.367 6.185 15.925 1.00 8.64 C ATOM 115 ND2 ASN A 14 28.105 6.452 14.854 1.00 8.64 N ATOM 116 OD1 ASN A 14 27.523 6.767 17.002 1.00 8.64 O ATOM 117 N ILE A 15 24.147 2.876 17.739 1.00 8.64 N ATOM 118 CA ILE A 15 22.782 2.392 17.562 1.00 8.64 C ATOM 119 C ILE A 15 21.867 3.040 18.600 1.00 8.64 C ATOM 120 CB ILE A 15 22.709 0.853 17.670 1.00 8.64 C ATOM 121 O ILE A 15 22.173 3.037 19.794 1.00 8.64 O ATOM 122 CG1 ILE A 15 23.583 0.200 16.594 1.00 8.64 C ATOM 123 CG2 ILE A 15 21.259 0.372 17.564 1.00 8.64 C ATOM 124 CD1 ILE A 15 23.694 -1.313 16.720 1.00 8.64 C ATOM 125 N LEU A 16 21.054 3.988 18.304 1.00 8.64 N ATOM 126 CA LEU A 16 19.978 4.667 19.017 1.00 8.64 C ATOM 127 C LEU A 16 18.932 3.668 19.501 1.00 8.64 C ATOM 128 CB LEU A 16 19.320 5.718 18.120 1.00 8.64 C ATOM 129 O LEU A 16 18.483 2.813 18.734 1.00 8.64 O ATOM 130 CG LEU A 16 20.096 7.021 17.921 1.00 8.64 C ATOM 131 CD1 LEU A 16 19.696 7.681 16.605 1.00 8.64 C ATOM 132 CD2 LEU A 16 19.860 7.968 19.093 1.00 8.64 C ATOM 133 N ALA A 17 18.869 3.238 20.703 1.00 8.64 N ATOM 134 CA ALA A 17 17.774 2.555 21.387 1.00 8.64 C ATOM 135 C ALA A 17 16.496 3.388 21.343 1.00 8.64 C ATOM 136 CB ALA A 17 18.158 2.251 22.833 1.00 8.64 C ATOM 137 O ALA A 17 16.550 4.620 21.358 1.00 8.64 O ATOM 138 N PRO A 18 15.357 2.800 20.785 1.00 8.64 N ATOM 139 CA PRO A 18 14.061 3.472 20.894 1.00 8.64 C ATOM 140 C PRO A 18 13.755 3.936 22.317 1.00 8.64 C ATOM 141 CB PRO A 18 13.067 2.397 20.446 1.00 8.64 C ATOM 142 O PRO A 18 14.149 3.277 23.283 1.00 8.64 O ATOM 143 CG PRO A 18 13.852 1.125 20.452 1.00 8.64 C ATOM 144 CD PRO A 18 15.296 1.456 20.699 1.00 8.64 C ATOM 145 N LYS A 19 13.655 5.179 22.533 1.00 8.64 N ATOM 146 CA LYS A 19 13.091 5.770 23.743 1.00 8.64 C ATOM 147 C LYS A 19 11.590 5.512 23.832 1.00 8.64 C ATOM 148 CB LYS A 19 13.369 7.273 23.786 1.00 8.64 C ATOM 149 O LYS A 19 10.851 5.783 22.884 1.00 8.64 O ATOM 150 CG LYS A 19 14.728 7.635 24.367 1.00 8.64 C ATOM 151 CD LYS A 19 14.887 9.143 24.519 1.00 8.64 C ATOM 152 CE LYS A 19 16.267 9.509 25.048 1.00 8.64 C ATOM 153 NZ LYS A 19 16.425 10.986 25.206 1.00 8.64 N ATOM 154 N VAL A 20 11.044 4.381 24.383 1.00 8.64 N ATOM 155 CA VAL A 20 9.629 4.231 24.706 1.00 8.64 C ATOM 156 C VAL A 20 9.274 5.116 25.898 1.00 8.64 C ATOM 157 CB VAL A 20 9.268 2.759 25.009 1.00 8.64 C ATOM 158 O VAL A 20 9.977 5.115 26.911 1.00 8.64 O ATOM 159 CG1 VAL A 20 7.753 2.575 25.067 1.00 8.64 C ATOM 160 CG2 VAL A 20 9.882 1.833 23.960 1.00 8.64 C ATOM 161 N SER A 21 8.650 6.317 25.693 1.00 8.64 N ATOM 162 CA SER A 21 8.096 7.229 26.687 1.00 8.64 C ATOM 163 C SER A 21 7.175 6.497 27.657 1.00 8.64 C ATOM 164 CB SER A 21 7.332 8.365 26.005 1.00 8.64 C ATOM 165 O SER A 21 6.372 5.657 27.245 1.00 8.64 O ATOM 166 OG SER A 21 5.963 8.343 26.373 1.00 8.64 O ATOM 167 N GLN A 22 7.597 6.311 28.856 1.00 8.64 N ATOM 168 CA GLN A 22 6.871 5.820 30.022 1.00 8.64 C ATOM 169 C GLN A 22 5.495 6.472 30.128 1.00 8.64 C ATOM 170 CB GLN A 22 7.672 6.073 31.300 1.00 8.64 C ATOM 171 O GLN A 22 4.544 5.852 30.609 1.00 8.64 O ATOM 172 CG GLN A 22 8.650 4.958 31.644 1.00 8.64 C ATOM 173 CD GLN A 22 9.489 5.270 32.869 1.00 8.64 C ATOM 174 NE2 GLN A 22 10.341 4.329 33.260 1.00 8.64 N ATOM 175 OE1 GLN A 22 9.372 6.349 33.460 1.00 8.64 O ATOM 176 N SER A 23 5.264 7.531 29.349 1.00 8.64 N ATOM 177 CA SER A 23 4.000 8.243 29.506 1.00 8.64 C ATOM 178 C SER A 23 2.897 7.603 28.670 1.00 8.64 C ATOM 179 CB SER A 23 4.160 9.713 29.115 1.00 8.64 C ATOM 180 O SER A 23 1.719 7.671 29.029 1.00 8.64 O ATOM 181 OG SER A 23 4.522 9.834 27.751 1.00 8.64 O ATOM 182 N VAL A 24 3.264 6.700 27.791 1.00 8.64 N ATOM 183 CA VAL A 24 2.305 6.038 26.913 1.00 8.64 C ATOM 184 C VAL A 24 1.784 4.767 27.581 1.00 8.64 C ATOM 185 CB VAL A 24 2.931 5.700 25.541 1.00 8.64 C ATOM 186 O VAL A 24 0.599 4.443 27.474 1.00 8.64 O ATOM 187 CG1 VAL A 24 1.954 4.895 24.686 1.00 8.64 C ATOM 188 CG2 VAL A 24 3.350 6.979 24.818 1.00 8.64 C ATOM 189 N ILE A 25 2.491 4.247 28.597 1.00 8.64 N ATOM 190 CA ILE A 25 2.093 2.989 29.220 1.00 8.64 C ATOM 191 C ILE A 25 1.071 3.261 30.322 1.00 8.64 C ATOM 192 CB ILE A 25 3.311 2.231 29.793 1.00 8.64 C ATOM 193 O ILE A 25 0.106 2.509 30.482 1.00 8.64 O ATOM 194 CG1 ILE A 25 4.253 1.802 28.662 1.00 8.64 C ATOM 195 CG2 ILE A 25 2.856 1.021 30.615 1.00 8.64 C ATOM 196 CD1 ILE A 25 5.548 1.162 29.144 1.00 8.64 C ATOM 197 N LYS A 26 0.966 4.583 30.669 1.00 8.64 N ATOM 198 CA LYS A 26 0.057 4.828 31.785 1.00 8.64 C ATOM 199 C LYS A 26 -1.334 5.210 31.288 1.00 8.64 C ATOM 200 CB LYS A 26 0.608 5.928 32.694 1.00 8.64 C ATOM 201 O LYS A 26 -2.335 4.927 31.951 1.00 8.64 O ATOM 202 CG LYS A 26 1.656 5.444 33.686 1.00 8.64 C ATOM 203 CD LYS A 26 2.100 6.562 34.621 1.00 8.64 C ATOM 204 CE LYS A 26 3.222 6.107 35.544 1.00 8.64 C ATOM 205 NZ LYS A 26 3.671 7.205 36.452 1.00 8.64 N ATOM 206 N SER A 27 -1.519 5.405 29.984 1.00 8.64 N ATOM 207 CA SER A 27 -2.818 5.830 29.472 1.00 8.64 C ATOM 208 C SER A 27 -3.593 4.654 28.886 1.00 8.64 C ATOM 209 CB SER A 27 -2.647 6.918 28.412 1.00 8.64 C ATOM 210 O SER A 27 -4.818 4.714 28.757 1.00 8.64 O ATOM 211 OG SER A 27 -1.783 7.941 28.876 1.00 8.64 O ATOM 212 N ILE A 28 -3.005 3.525 29.012 1.00 8.64 N ATOM 213 CA ILE A 28 -3.699 2.421 28.358 1.00 8.64 C ATOM 214 C ILE A 28 -4.341 1.519 29.410 1.00 8.64 C ATOM 215 CB ILE A 28 -2.741 1.603 27.463 1.00 8.64 C ATOM 216 O ILE A 28 -5.121 0.624 29.076 1.00 8.64 O ATOM 217 CG1 ILE A 28 -2.140 2.495 26.370 1.00 8.64 C ATOM 218 CG2 ILE A 28 -3.468 0.402 26.851 1.00 8.64 C ATOM 219 CD1 ILE A 28 -1.059 1.814 25.541 1.00 8.64 C ATOM 220 N LYS A 29 -4.577 2.107 30.648 1.00 8.64 N ATOM 221 CA LYS A 29 -5.233 1.333 31.698 1.00 8.64 C ATOM 222 C LYS A 29 -6.750 1.358 31.533 1.00 8.64 C ATOM 223 CB LYS A 29 -4.847 1.867 33.078 1.00 8.64 C ATOM 224 O LYS A 29 -7.358 2.430 31.493 1.00 8.64 O ATOM 225 CG LYS A 29 -3.666 1.147 33.712 1.00 8.64 C ATOM 226 CD LYS A 29 -3.402 1.645 35.127 1.00 8.64 C ATOM 227 CE LYS A 29 -2.190 0.960 35.745 1.00 8.64 C ATOM 228 NZ LYS A 29 -1.924 1.448 37.131 1.00 8.64 N ATOM 229 N GLY A 30 -7.229 1.083 30.294 1.00 8.64 N ATOM 230 CA GLY A 30 -8.601 0.618 30.176 1.00 8.64 C ATOM 231 C GLY A 30 -8.899 -0.029 28.837 1.00 8.64 C ATOM 232 O GLY A 30 -9.937 -0.674 28.670 1.00 8.64 O ATOM 233 N ILE A 31 -7.830 -0.266 28.050 1.00 8.64 N ATOM 234 CA ILE A 31 -8.106 -0.892 26.762 1.00 8.64 C ATOM 235 C ILE A 31 -7.458 -2.274 26.711 1.00 8.64 C ATOM 236 CB ILE A 31 -7.601 -0.021 25.590 1.00 8.64 C ATOM 237 O ILE A 31 -6.281 -2.428 27.045 1.00 8.64 O ATOM 238 CG1 ILE A 31 -8.334 1.326 25.572 1.00 8.64 C ATOM 239 CG2 ILE A 31 -7.773 -0.756 24.258 1.00 8.64 C ATOM 240 CD1 ILE A 31 -7.778 2.319 24.562 1.00 8.64 C ATOM 241 N LYS A 32 -8.177 -3.230 27.032 1.00 8.64 N ATOM 242 CA LYS A 32 -7.883 -4.648 26.851 1.00 8.64 C ATOM 243 C LYS A 32 -7.261 -4.910 25.482 1.00 8.64 C ATOM 244 CB LYS A 32 -9.152 -5.485 27.018 1.00 8.64 C ATOM 245 O LYS A 32 -7.777 -4.449 24.461 1.00 8.64 O ATOM 246 CG LYS A 32 -9.602 -5.645 28.463 1.00 8.64 C ATOM 247 CD LYS A 32 -10.735 -6.656 28.587 1.00 8.64 C ATOM 248 CE LYS A 32 -11.232 -6.767 30.022 1.00 8.64 C ATOM 249 NZ LYS A 32 -12.323 -7.777 30.154 1.00 8.64 N ATOM 250 N SER A 33 -5.945 -4.505 25.154 1.00 8.64 N ATOM 251 CA SER A 33 -4.816 -4.797 24.277 1.00 8.64 C ATOM 252 C SER A 33 -5.289 -5.219 22.890 1.00 8.64 C ATOM 253 CB SER A 33 -3.937 -5.894 24.880 1.00 8.64 C ATOM 254 O SER A 33 -6.134 -6.107 22.759 1.00 8.64 O ATOM 255 OG SER A 33 -4.706 -7.046 25.181 1.00 8.64 O ATOM 256 N LYS A 34 -5.506 -4.290 21.907 1.00 8.64 N ATOM 257 CA LYS A 34 -5.176 -4.717 20.550 1.00 8.64 C ATOM 258 C LYS A 34 -3.963 -3.963 20.015 1.00 8.64 C ATOM 259 CB LYS A 34 -6.372 -4.514 19.618 1.00 8.64 C ATOM 260 O LYS A 34 -3.833 -2.755 20.227 1.00 8.64 O ATOM 261 CG LYS A 34 -7.490 -5.528 19.815 1.00 8.64 C ATOM 262 CD LYS A 34 -8.616 -5.321 18.811 1.00 8.64 C ATOM 263 CE LYS A 34 -9.773 -6.278 19.062 1.00 8.64 C ATOM 264 NZ LYS A 34 -10.875 -6.087 18.072 1.00 8.64 N ATOM 265 N HIS A 35 -2.824 -4.493 19.949 1.00 8.64 N ATOM 266 CA HIS A 35 -1.491 -4.114 19.495 1.00 8.64 C ATOM 267 C HIS A 35 -1.527 -3.581 18.066 1.00 8.64 C ATOM 268 CB HIS A 35 -0.535 -5.304 19.588 1.00 8.64 C ATOM 269 O HIS A 35 -2.122 -4.202 17.182 1.00 8.64 O ATOM 270 CG HIS A 35 -0.328 -5.799 20.983 1.00 8.64 C ATOM 271 CD2 HIS A 35 -0.455 -7.038 21.515 1.00 8.64 C ATOM 272 ND1 HIS A 35 0.057 -4.973 22.017 1.00 8.64 N ATOM 273 CE1 HIS A 35 0.158 -5.684 23.127 1.00 8.64 C ATOM 274 NE2 HIS A 35 -0.147 -6.940 22.850 1.00 8.64 N ATOM 275 N VAL A 36 -1.503 -2.286 17.829 1.00 8.64 N ATOM 276 CA VAL A 36 -1.192 -1.701 16.529 1.00 8.64 C ATOM 277 C VAL A 36 0.304 -1.410 16.437 1.00 8.64 C ATOM 278 CB VAL A 36 -2.002 -0.410 16.279 1.00 8.64 C ATOM 279 O VAL A 36 0.894 -0.861 17.371 1.00 8.64 O ATOM 280 CG1 VAL A 36 -1.660 0.188 14.915 1.00 8.64 C ATOM 281 CG2 VAL A 36 -3.500 -0.692 16.381 1.00 8.64 C ATOM 282 N PHE A 37 1.020 -2.124 15.486 1.00 8.64 N ATOM 283 CA PHE A 37 2.422 -1.855 15.187 1.00 8.64 C ATOM 284 C PHE A 37 2.551 -0.928 13.985 1.00 8.64 C ATOM 285 CB PHE A 37 3.177 -3.162 14.926 1.00 8.64 C ATOM 286 O PHE A 37 1.807 -1.060 13.010 1.00 8.64 O ATOM 287 CG PHE A 37 3.251 -4.071 16.124 1.00 8.64 C ATOM 288 CD1 PHE A 37 2.301 -5.066 16.318 1.00 8.64 C ATOM 289 CD2 PHE A 37 4.270 -3.928 17.057 1.00 8.64 C ATOM 290 CE1 PHE A 37 2.367 -5.908 17.426 1.00 8.64 C ATOM 291 CE2 PHE A 37 4.342 -4.766 18.166 1.00 8.64 C ATOM 292 CZ PHE A 37 3.389 -5.755 18.349 1.00 8.64 C ATOM 293 N GLU A 38 3.248 0.202 14.094 1.00 8.64 N ATOM 294 CA GLU A 38 3.645 1.092 13.007 1.00 8.64 C ATOM 295 C GLU A 38 5.086 0.830 12.578 1.00 8.64 C ATOM 296 CB GLU A 38 3.477 2.556 13.421 1.00 8.64 C ATOM 297 O GLU A 38 5.981 0.731 13.419 1.00 8.64 O ATOM 298 CG GLU A 38 2.545 3.348 12.515 1.00 8.64 C ATOM 299 CD GLU A 38 2.381 4.798 12.943 1.00 8.64 C ATOM 300 OE1 GLU A 38 1.724 5.575 12.214 1.00 8.64 O ATOM 301 OE2 GLU A 38 2.914 5.159 14.016 1.00 8.64 O ATOM 302 N LEU A 39 5.280 0.263 11.288 1.00 8.64 N ATOM 303 CA LEU A 39 6.615 0.024 10.751 1.00 8.64 C ATOM 304 C LEU A 39 7.133 1.253 10.013 1.00 8.64 C ATOM 305 CB LEU A 39 6.607 -1.185 9.811 1.00 8.64 C ATOM 306 O LEU A 39 6.371 1.936 9.324 1.00 8.64 O ATOM 307 CG LEU A 39 6.486 -2.558 10.474 1.00 8.64 C ATOM 308 CD1 LEU A 39 5.969 -3.586 9.473 1.00 8.64 C ATOM 309 CD2 LEU A 39 7.829 -2.994 11.050 1.00 8.64 C ATOM 310 N PRO A 40 8.338 1.782 10.282 1.00 8.64 N ATOM 311 CA PRO A 40 8.943 2.928 9.599 1.00 8.64 C ATOM 312 C PRO A 40 9.200 2.662 8.117 1.00 8.64 C ATOM 313 CB PRO A 40 10.259 3.133 10.353 1.00 8.64 C ATOM 314 O PRO A 40 9.522 1.534 7.735 1.00 8.64 O ATOM 315 CG PRO A 40 10.482 1.852 11.090 1.00 8.64 C ATOM 316 CD PRO A 40 9.238 1.017 10.981 1.00 8.64 C ATOM 317 N ILE A 41 8.660 3.312 7.012 1.00 8.64 N ATOM 318 CA ILE A 41 8.626 3.183 5.560 1.00 8.64 C ATOM 319 C ILE A 41 9.887 3.798 4.958 1.00 8.64 C ATOM 320 CB ILE A 41 7.367 3.850 4.962 1.00 8.64 C ATOM 321 O ILE A 41 10.222 4.950 5.244 1.00 8.64 O ATOM 322 CG1 ILE A 41 6.099 3.238 5.570 1.00 8.64 C ATOM 323 CG2 ILE A 41 7.360 3.722 3.436 1.00 8.64 C ATOM 324 CD1 ILE A 41 4.813 3.939 5.155 1.00 8.64 C ATOM 325 N ASN A 42 10.941 3.063 4.710 1.00 8.64 N ATOM 326 CA ASN A 42 11.934 3.552 3.759 1.00 8.64 C ATOM 327 C ASN A 42 11.614 3.106 2.335 1.00 8.64 C ATOM 328 CB ASN A 42 13.336 3.085 4.159 1.00 8.64 C ATOM 329 O ASN A 42 10.806 2.198 2.131 1.00 8.64 O ATOM 330 CG ASN A 42 13.525 1.591 3.986 1.00 8.64 C ATOM 331 ND2 ASN A 42 14.569 1.051 4.604 1.00 8.64 N ATOM 332 OD1 ASN A 42 12.741 0.928 3.303 1.00 8.64 O ATOM 333 N ASP A 43 11.701 4.001 1.461 1.00 8.64 N ATOM 334 CA ASP A 43 11.331 4.253 0.072 1.00 8.64 C ATOM 335 C ASP A 43 11.757 3.096 -0.829 1.00 8.64 C ATOM 336 CB ASP A 43 11.956 5.561 -0.421 1.00 8.64 C ATOM 337 O ASP A 43 11.082 2.788 -1.813 1.00 8.64 O ATOM 338 CG ASP A 43 11.313 6.793 0.191 1.00 8.64 C ATOM 339 OD1 ASP A 43 11.900 7.893 0.108 1.00 8.64 O ATOM 340 OD2 ASP A 43 10.210 6.661 0.764 1.00 8.64 O ATOM 341 N LYS A 44 12.353 2.046 -0.514 1.00 8.64 N ATOM 342 CA LYS A 44 12.727 0.989 -1.449 1.00 8.64 C ATOM 343 C LYS A 44 11.978 -0.305 -1.142 1.00 8.64 C ATOM 344 CB LYS A 44 14.236 0.744 -1.407 1.00 8.64 C ATOM 345 O LYS A 44 11.810 -1.154 -2.021 1.00 8.64 O ATOM 346 CG LYS A 44 15.059 1.832 -2.080 1.00 8.64 C ATOM 347 CD LYS A 44 16.537 1.468 -2.124 1.00 8.64 C ATOM 348 CE LYS A 44 17.370 2.584 -2.741 1.00 8.64 C ATOM 349 NZ LYS A 44 18.820 2.229 -2.793 1.00 8.64 N ATOM 350 N THR A 45 11.103 -0.291 -0.142 1.00 8.64 N ATOM 351 CA THR A 45 10.454 -1.552 0.197 1.00 8.64 C ATOM 352 C THR A 45 8.939 -1.437 0.054 1.00 8.64 C ATOM 353 CB THR A 45 10.805 -1.993 1.630 1.00 8.64 C ATOM 354 O THR A 45 8.223 -2.436 0.149 1.00 8.64 O ATOM 355 CG2 THR A 45 12.095 -2.806 1.656 1.00 8.64 C ATOM 356 OG1 THR A 45 10.968 -0.832 2.454 1.00 8.64 O ATOM 357 N LYS A 46 8.412 -0.546 -0.642 1.00 8.64 N ATOM 358 CA LYS A 46 6.961 -0.392 -0.700 1.00 8.64 C ATOM 359 C LYS A 46 6.386 -1.066 -1.942 1.00 8.64 C ATOM 360 CB LYS A 46 6.578 1.089 -0.682 1.00 8.64 C ATOM 361 O LYS A 46 6.699 -0.675 -3.068 1.00 8.64 O ATOM 362 CG LYS A 46 6.727 1.750 0.680 1.00 8.64 C ATOM 363 CD LYS A 46 6.243 3.195 0.656 1.00 8.64 C ATOM 364 CE LYS A 46 6.459 3.880 1.998 1.00 8.64 C ATOM 365 NZ LYS A 46 6.003 5.302 1.974 1.00 8.64 N ATOM 366 N ARG A 47 6.500 -2.491 -2.290 1.00 8.64 N ATOM 367 CA ARG A 47 5.304 -2.979 -2.968 1.00 8.64 C ATOM 368 C ARG A 47 5.112 -4.474 -2.731 1.00 8.64 C ATOM 369 CB ARG A 47 5.382 -2.692 -4.469 1.00 8.64 C ATOM 370 O ARG A 47 5.990 -5.276 -3.055 1.00 8.64 O ATOM 371 CG ARG A 47 4.430 -1.603 -4.938 1.00 8.64 C ATOM 372 CD ARG A 47 4.526 -1.379 -6.440 1.00 8.64 C ATOM 373 NE ARG A 47 4.838 0.011 -6.759 1.00 8.64 N ATOM 374 NH1 ARG A 47 4.576 -0.237 -9.041 1.00 8.64 N ATOM 375 NH2 ARG A 47 5.152 1.801 -8.164 1.00 8.64 N ATOM 376 CZ ARG A 47 4.854 0.522 -7.987 1.00 8.64 C ATOM 377 N TYR A 48 4.776 -5.036 -1.672 1.00 8.64 N ATOM 378 CA TYR A 48 4.245 -6.394 -1.657 1.00 8.64 C ATOM 379 C TYR A 48 2.731 -6.390 -1.828 1.00 8.64 C ATOM 380 CB TYR A 48 4.621 -7.104 -0.353 1.00 8.64 C ATOM 381 O TYR A 48 2.027 -5.622 -1.168 1.00 8.64 O ATOM 382 CG TYR A 48 6.098 -7.385 -0.219 1.00 8.64 C ATOM 383 CD1 TYR A 48 6.931 -6.518 0.484 1.00 8.64 C ATOM 384 CD2 TYR A 48 6.663 -8.518 -0.795 1.00 8.64 C ATOM 385 CE1 TYR A 48 8.293 -6.772 0.609 1.00 8.64 C ATOM 386 CE2 TYR A 48 8.024 -8.782 -0.677 1.00 8.64 C ATOM 387 OH TYR A 48 10.177 -8.161 0.146 1.00 8.64 O ATOM 388 CZ TYR A 48 8.829 -7.905 0.026 1.00 8.64 C ATOM 389 N ILE A 49 2.115 -6.489 -3.067 1.00 8.64 N ATOM 390 CA ILE A 49 0.852 -6.880 -3.684 1.00 8.64 C ATOM 391 C ILE A 49 0.101 -7.837 -2.761 1.00 8.64 C ATOM 392 CB ILE A 49 1.076 -7.534 -5.066 1.00 8.64 C ATOM 393 O ILE A 49 0.588 -8.929 -2.459 1.00 8.64 O ATOM 394 CG1 ILE A 49 1.810 -6.567 -6.002 1.00 8.64 C ATOM 395 CG2 ILE A 49 -0.256 -7.981 -5.674 1.00 8.64 C ATOM 396 CD1 ILE A 49 2.101 -7.142 -7.381 1.00 8.64 C ATOM 397 N LEU A 50 -0.593 -7.592 -1.660 1.00 8.64 N ATOM 398 CA LEU A 50 -1.573 -8.173 -0.750 1.00 8.64 C ATOM 399 C LEU A 50 -2.949 -8.245 -1.405 1.00 8.64 C ATOM 400 CB LEU A 50 -1.653 -7.358 0.544 1.00 8.64 C ATOM 401 O LEU A 50 -3.384 -7.289 -2.050 1.00 8.64 O ATOM 402 CG LEU A 50 -0.484 -7.515 1.517 1.00 8.64 C ATOM 403 CD1 LEU A 50 -0.441 -6.339 2.488 1.00 8.64 C ATOM 404 CD2 LEU A 50 -0.591 -8.835 2.273 1.00 8.64 C ATOM 405 N GLY A 51 -3.407 -9.384 -2.202 1.00 8.64 N ATOM 406 CA GLY A 51 -4.655 -10.100 -1.989 1.00 8.64 C ATOM 407 C GLY A 51 -5.574 -10.070 -3.195 1.00 8.64 C ATOM 408 O GLY A 51 -6.476 -9.233 -3.274 1.00 8.64 O ATOM 409 N ALA A 52 -5.228 -10.625 -4.456 1.00 8.64 N ATOM 410 CA ALA A 52 -6.350 -10.631 -5.391 1.00 8.64 C ATOM 411 C ALA A 52 -6.952 -12.027 -5.518 1.00 8.64 C ATOM 412 CB ALA A 52 -5.905 -10.121 -6.760 1.00 8.64 C ATOM 413 O ALA A 52 -6.245 -12.989 -5.829 1.00 8.64 O ATOM 414 N THR A 53 -7.821 -12.550 -4.658 1.00 8.64 N ATOM 415 CA THR A 53 -8.645 -13.723 -4.929 1.00 8.64 C ATOM 416 C THR A 53 -9.877 -13.343 -5.745 1.00 8.64 C ATOM 417 CB THR A 53 -9.083 -14.411 -3.622 1.00 8.64 C ATOM 418 O THR A 53 -10.285 -12.180 -5.756 1.00 8.64 O ATOM 419 CG2 THR A 53 -7.877 -14.908 -2.831 1.00 8.64 C ATOM 420 OG1 THR A 53 -9.815 -13.477 -2.820 1.00 8.64 O ATOM 421 N GLU A 54 -10.028 -13.989 -6.922 1.00 8.64 N ATOM 422 CA GLU A 54 -11.170 -13.968 -7.831 1.00 8.64 C ATOM 423 C GLU A 54 -12.473 -13.725 -7.074 1.00 8.64 C ATOM 424 CB GLU A 54 -11.256 -15.279 -8.618 1.00 8.64 C ATOM 425 O GLU A 54 -13.399 -13.109 -7.604 1.00 8.64 O ATOM 426 CG GLU A 54 -10.288 -15.357 -9.789 1.00 8.64 C ATOM 427 CD GLU A 54 -10.430 -16.635 -10.601 1.00 8.64 C ATOM 428 OE1 GLU A 54 -9.704 -16.798 -11.608 1.00 8.64 O ATOM 429 OE2 GLU A 54 -11.276 -17.478 -10.228 1.00 8.64 O ATOM 430 N THR A 55 -12.360 -13.799 -5.890 1.00 8.64 N ATOM 431 CA THR A 55 -13.448 -13.571 -4.946 1.00 8.64 C ATOM 432 C THR A 55 -13.101 -12.439 -3.983 1.00 8.64 C ATOM 433 CB THR A 55 -13.771 -14.847 -4.146 1.00 8.64 C ATOM 434 O THR A 55 -11.941 -12.282 -3.594 1.00 8.64 O ATOM 435 CG2 THR A 55 -14.391 -15.915 -5.041 1.00 8.64 C ATOM 436 OG1 THR A 55 -12.563 -15.363 -3.573 1.00 8.64 O ATOM 437 N LYS A 56 -13.303 -11.292 -4.478 1.00 8.64 N ATOM 438 CA LYS A 56 -13.121 -9.990 -3.842 1.00 8.64 C ATOM 439 C LYS A 56 -12.513 -10.138 -2.450 1.00 8.64 C ATOM 440 CB LYS A 56 -14.454 -9.244 -3.755 1.00 8.64 C ATOM 441 O LYS A 56 -13.231 -10.124 -1.449 1.00 8.64 O ATOM 442 CG LYS A 56 -15.022 -8.833 -5.105 1.00 8.64 C ATOM 443 CD LYS A 56 -16.241 -7.932 -4.948 1.00 8.64 C ATOM 444 CE LYS A 56 -16.839 -7.558 -6.298 1.00 8.64 C ATOM 445 NZ LYS A 56 -18.009 -6.643 -6.150 1.00 8.64 N ATOM 446 N GLU A 57 -11.444 -10.923 -2.365 1.00 8.64 N ATOM 447 CA GLU A 57 -10.922 -10.869 -1.003 1.00 8.64 C ATOM 448 C GLU A 57 -9.945 -9.710 -0.832 1.00 8.64 C ATOM 449 CB GLU A 57 -10.241 -12.190 -0.635 1.00 8.64 C ATOM 450 O GLU A 57 -9.129 -9.443 -1.717 1.00 8.64 O ATOM 451 CG GLU A 57 -11.101 -13.108 0.221 1.00 8.64 C ATOM 452 CD GLU A 57 -10.378 -14.373 0.656 1.00 8.64 C ATOM 453 OE1 GLU A 57 -10.943 -15.149 1.461 1.00 8.64 O ATOM 454 OE2 GLU A 57 -9.238 -14.590 0.190 1.00 8.64 O ATOM 455 N GLU A 58 -10.407 -8.718 -0.201 1.00 8.64 N ATOM 456 CA GLU A 58 -9.599 -7.616 0.312 1.00 8.64 C ATOM 457 C GLU A 58 -8.294 -8.124 0.918 1.00 8.64 C ATOM 458 CB GLU A 58 -10.384 -6.812 1.352 1.00 8.64 C ATOM 459 O GLU A 58 -8.299 -9.054 1.728 1.00 8.64 O ATOM 460 CG GLU A 58 -10.114 -5.315 1.303 1.00 8.64 C ATOM 461 CD GLU A 58 -10.947 -4.523 2.298 1.00 8.64 C ATOM 462 OE1 GLU A 58 -10.733 -3.296 2.428 1.00 8.64 O ATOM 463 OE2 GLU A 58 -11.819 -5.134 2.955 1.00 8.64 O ATOM 464 N VAL A 59 -7.183 -8.070 0.289 1.00 6.72 N ATOM 465 CA VAL A 59 -5.863 -8.557 0.675 1.00 6.72 C ATOM 466 C VAL A 59 -5.151 -7.505 1.523 1.00 6.72 C ATOM 467 CB VAL A 59 -5.006 -8.915 -0.560 1.00 6.72 C ATOM 468 O VAL A 59 -4.402 -7.842 2.442 1.00 6.72 O ATOM 469 CG1 VAL A 59 -3.820 -9.790 -0.159 1.00 6.72 C ATOM 470 CG2 VAL A 59 -5.860 -9.616 -1.615 1.00 6.72 C ATOM 471 N LEU A 60 -5.923 -6.877 2.559 1.00 6.72 N ATOM 472 CA LEU A 60 -5.509 -6.065 3.699 1.00 6.72 C ATOM 473 C LEU A 60 -5.287 -4.615 3.281 1.00 6.72 C ATOM 474 CB LEU A 60 -4.231 -6.631 4.324 1.00 6.72 C ATOM 475 O LEU A 60 -4.724 -4.351 2.216 1.00 6.72 O ATOM 476 CG LEU A 60 -4.398 -7.870 5.205 1.00 6.72 C ATOM 477 CD1 LEU A 60 -3.064 -8.591 5.363 1.00 6.72 C ATOM 478 CD2 LEU A 60 -4.969 -7.486 6.565 1.00 6.72 C ATOM 479 N PRO A 61 -6.061 -3.706 3.745 1.00 6.72 N ATOM 480 CA PRO A 61 -5.827 -2.294 3.434 1.00 6.72 C ATOM 481 C PRO A 61 -4.391 -1.859 3.717 1.00 6.72 C ATOM 482 CB PRO A 61 -6.810 -1.563 4.353 1.00 6.72 C ATOM 483 O PRO A 61 -3.782 -2.317 4.687 1.00 6.72 O ATOM 484 CG PRO A 61 -7.183 -2.571 5.392 1.00 6.72 C ATOM 485 CD PRO A 61 -6.789 -3.933 4.898 1.00 6.72 C ATOM 486 N ASN A 62 -3.671 -1.566 2.620 1.00 6.72 N ATOM 487 CA ASN A 62 -2.420 -0.834 2.785 1.00 6.72 C ATOM 488 C ASN A 62 -2.630 0.672 2.655 1.00 6.72 C ATOM 489 CB ASN A 62 -1.379 -1.315 1.772 1.00 6.72 C ATOM 490 O ASN A 62 -3.578 1.117 2.004 1.00 6.72 O ATOM 491 CG ASN A 62 -0.729 -2.622 2.178 1.00 6.72 C ATOM 492 ND2 ASN A 62 -0.250 -3.376 1.195 1.00 6.72 N ATOM 493 OD1 ASN A 62 -0.659 -2.953 3.364 1.00 6.72 O ATOM 494 N TYR A 63 -2.223 1.347 3.620 1.00 6.72 N ATOM 495 CA TYR A 63 -2.253 2.806 3.627 1.00 6.72 C ATOM 496 C TYR A 63 -0.969 3.381 3.043 1.00 6.72 C ATOM 497 CB TYR A 63 -2.461 3.332 5.050 1.00 6.72 C ATOM 498 O TYR A 63 0.099 2.774 3.157 1.00 6.72 O ATOM 499 CG TYR A 63 -3.732 2.841 5.700 1.00 6.72 C ATOM 500 CD1 TYR A 63 -3.747 1.663 6.442 1.00 6.72 C ATOM 501 CD2 TYR A 63 -4.920 3.553 5.571 1.00 6.72 C ATOM 502 CE1 TYR A 63 -4.917 1.205 7.041 1.00 6.72 C ATOM 503 CE2 TYR A 63 -6.095 3.105 6.166 1.00 6.72 C ATOM 504 OH TYR A 63 -7.244 1.484 7.488 1.00 6.72 O ATOM 505 CZ TYR A 63 -6.083 1.932 6.898 1.00 6.72 C ATOM 506 N VAL A 64 -1.142 4.342 2.173 1.00 4.66 N ATOM 507 CA VAL A 64 -0.000 5.090 1.658 1.00 4.66 C ATOM 508 C VAL A 64 -0.129 6.561 2.046 1.00 4.66 C ATOM 509 CB VAL A 64 0.125 4.951 0.125 1.00 4.66 C ATOM 510 O VAL A 64 -1.219 7.133 1.982 1.00 4.66 O ATOM 511 CG1 VAL A 64 -1.005 5.701 -0.579 1.00 4.66 C ATOM 512 CG2 VAL A 64 1.485 5.462 -0.348 1.00 4.66 C ATOM 513 N LYS A 65 0.916 7.003 2.673 1.00 6.72 N ATOM 514 CA LYS A 65 0.982 8.432 2.966 1.00 6.72 C ATOM 515 C LYS A 65 1.692 9.190 1.848 1.00 6.72 C ATOM 516 CB LYS A 65 1.693 8.674 4.298 1.00 6.72 C ATOM 517 O LYS A 65 2.804 8.830 1.455 1.00 6.72 O ATOM 518 CG LYS A 65 1.604 10.110 4.795 1.00 6.72 C ATOM 519 CD LYS A 65 2.207 10.258 6.186 1.00 6.72 C ATOM 520 CE LYS A 65 2.153 11.701 6.669 1.00 6.72 C ATOM 521 NZ LYS A 65 2.726 11.848 8.040 1.00 6.72 N ATOM 522 N VAL A 66 1.057 10.179 1.205 1.00 6.72 N ATOM 523 CA VAL A 66 1.588 11.120 0.224 1.00 6.72 C ATOM 524 C VAL A 66 1.485 12.544 0.766 1.00 6.72 C ATOM 525 CB VAL A 66 0.847 11.009 -1.127 1.00 6.72 C ATOM 526 O VAL A 66 0.389 13.105 0.851 1.00 6.72 O ATOM 527 CG1 VAL A 66 1.477 11.935 -2.166 1.00 6.72 C ATOM 528 CG2 VAL A 66 0.854 9.564 -1.622 1.00 6.72 C ATOM 529 N GLY A 67 2.645 13.103 1.210 1.00 6.72 N ATOM 530 CA GLY A 67 2.556 14.375 1.909 1.00 6.72 C ATOM 531 C GLY A 67 1.847 14.273 3.247 1.00 6.72 C ATOM 532 O GLY A 67 2.248 13.488 4.109 1.00 6.72 O ATOM 533 N SER A 68 0.772 15.228 3.461 1.00 6.72 N ATOM 534 CA SER A 68 -0.022 15.225 4.685 1.00 6.72 C ATOM 535 C SER A 68 -1.250 14.332 4.545 1.00 6.72 C ATOM 536 CB SER A 68 -0.453 16.647 5.048 1.00 6.72 C ATOM 537 O SER A 68 -2.061 14.234 5.469 1.00 6.72 O ATOM 538 OG SER A 68 -1.210 17.226 3.999 1.00 6.72 O ATOM 539 N ASP A 69 -1.295 13.620 3.451 1.00 6.72 N ATOM 540 CA ASP A 69 -2.507 12.844 3.203 1.00 6.72 C ATOM 541 C ASP A 69 -2.237 11.347 3.332 1.00 6.72 C ATOM 542 CB ASP A 69 -3.071 13.160 1.816 1.00 6.72 C ATOM 543 O ASP A 69 -1.146 10.877 3.002 1.00 6.72 O ATOM 544 CG ASP A 69 -3.522 14.603 1.673 1.00 6.72 C ATOM 545 OD1 ASP A 69 -3.312 15.204 0.598 1.00 6.72 O ATOM 546 OD2 ASP A 69 -4.090 15.144 2.646 1.00 6.72 O ATOM 547 N LEU A 70 -3.211 10.550 3.934 1.00 4.66 N ATOM 548 CA LEU A 70 -3.196 9.096 4.057 1.00 4.66 C ATOM 549 C LEU A 70 -4.202 8.459 3.105 1.00 4.66 C ATOM 550 CB LEU A 70 -3.502 8.677 5.498 1.00 4.66 C ATOM 551 O LEU A 70 -5.357 8.886 3.039 1.00 4.66 O ATOM 552 CG LEU A 70 -3.258 7.207 5.842 1.00 4.66 C ATOM 553 CD1 LEU A 70 -1.767 6.890 5.788 1.00 4.66 C ATOM 554 CD2 LEU A 70 -3.830 6.877 7.216 1.00 4.66 C ATOM 555 N TYR A 71 -3.655 7.568 2.260 1.00 4.66 N ATOM 556 CA TYR A 71 -4.497 6.862 1.300 1.00 4.66 C ATOM 557 C TYR A 71 -4.630 5.390 1.671 1.00 4.66 C ATOM 558 CB TYR A 71 -3.926 6.994 -0.115 1.00 4.66 C ATOM 559 O TYR A 71 -3.674 4.774 2.148 1.00 4.66 O ATOM 560 CG TYR A 71 -3.900 8.412 -0.629 1.00 4.66 C ATOM 561 CD1 TYR A 71 -2.852 9.272 -0.307 1.00 4.66 C ATOM 562 CD2 TYR A 71 -4.923 8.897 -1.437 1.00 4.66 C ATOM 563 CE1 TYR A 71 -2.824 10.581 -0.777 1.00 4.66 C ATOM 564 CE2 TYR A 71 -4.906 10.204 -1.913 1.00 4.66 C ATOM 565 OH TYR A 71 -3.832 12.332 -2.046 1.00 4.66 O ATOM 566 CZ TYR A 71 -3.854 11.037 -1.578 1.00 4.66 C ATOM 567 N ARG A 72 -5.791 4.900 1.584 1.00 4.66 N ATOM 568 CA ARG A 72 -6.044 3.465 1.655 1.00 4.66 C ATOM 569 C ARG A 72 -5.981 2.829 0.270 1.00 4.66 C ATOM 570 CB ARG A 72 -7.406 3.190 2.296 1.00 4.66 C ATOM 571 O ARG A 72 -6.604 3.321 -0.674 1.00 4.66 O ATOM 572 CG ARG A 72 -7.679 1.717 2.555 1.00 4.66 C ATOM 573 CD ARG A 72 -9.040 1.500 3.201 1.00 4.66 C ATOM 574 NE ARG A 72 -9.274 0.091 3.505 1.00 4.66 N ATOM 575 NH1 ARG A 72 -11.472 0.383 4.153 1.00 4.66 N ATOM 576 NH2 ARG A 72 -10.528 -1.705 4.194 1.00 4.66 N ATOM 577 CZ ARG A 72 -10.424 -0.407 3.950 1.00 4.66 C ATOM 578 N LEU A 73 -5.092 1.875 0.180 1.00 4.66 N ATOM 579 CA LEU A 73 -4.937 1.157 -1.080 1.00 4.66 C ATOM 580 C LEU A 73 -5.727 -0.147 -1.064 1.00 4.66 C ATOM 581 CB LEU A 73 -3.458 0.868 -1.354 1.00 4.66 C ATOM 582 O LEU A 73 -5.700 -0.882 -0.074 1.00 4.66 O ATOM 583 CG LEU A 73 -2.548 2.087 -1.518 1.00 4.66 C ATOM 584 CD1 LEU A 73 -1.084 1.663 -1.481 1.00 4.66 C ATOM 585 CD2 LEU A 73 -2.866 2.820 -2.817 1.00 4.66 C ATOM 586 N LYS A 74 -6.458 -0.297 -2.040 1.00 4.66 N ATOM 587 CA LYS A 74 -7.147 -1.567 -2.251 1.00 4.66 C ATOM 588 C LYS A 74 -6.751 -2.192 -3.586 1.00 4.66 C ATOM 589 CB LYS A 74 -8.662 -1.371 -2.193 1.00 4.66 C ATOM 590 O LYS A 74 -6.697 -1.504 -4.608 1.00 4.66 O ATOM 591 CG LYS A 74 -9.189 -1.022 -0.809 1.00 4.66 C ATOM 592 CD LYS A 74 -10.710 -0.932 -0.796 1.00 4.66 C ATOM 593 CE LYS A 74 -11.234 -0.515 0.572 1.00 4.66 C ATOM 594 NZ LYS A 74 -12.725 -0.424 0.589 1.00 4.66 N ATOM 595 N ALA A 75 -6.218 -3.399 -3.444 1.00 4.66 N ATOM 596 CA ALA A 75 -5.851 -4.111 -4.666 1.00 4.66 C ATOM 597 C ALA A 75 -6.823 -5.253 -4.948 1.00 4.66 C ATOM 598 CB ALA A 75 -4.424 -4.644 -4.562 1.00 4.66 C ATOM 599 O ALA A 75 -7.332 -5.887 -4.021 1.00 4.66 O ATOM 600 N TYR A 76 -7.207 -5.295 -6.175 1.00 6.72 N ATOM 601 CA TYR A 76 -8.028 -6.438 -6.558 1.00 6.72 C ATOM 602 C TYR A 76 -7.576 -7.011 -7.896 1.00 6.72 C ATOM 603 CB TYR A 76 -9.505 -6.039 -6.633 1.00 6.72 C ATOM 604 O TYR A 76 -6.891 -6.335 -8.668 1.00 6.72 O ATOM 605 CG TYR A 76 -9.757 -4.799 -7.457 1.00 6.72 C ATOM 606 CD1 TYR A 76 -10.045 -4.889 -8.817 1.00 6.72 C ATOM 607 CD2 TYR A 76 -9.707 -3.536 -6.878 1.00 6.72 C ATOM 608 CE1 TYR A 76 -10.276 -3.750 -9.580 1.00 6.72 C ATOM 609 CE2 TYR A 76 -9.937 -2.389 -7.631 1.00 6.72 C ATOM 610 OH TYR A 76 -10.448 -1.375 -9.730 1.00 6.72 O ATOM 611 CZ TYR A 76 -10.220 -2.506 -8.979 1.00 6.72 C ATOM 612 N ARG A 77 -7.735 -8.365 -8.035 1.00 6.72 N ATOM 613 CA ARG A 77 -7.400 -9.083 -9.261 1.00 6.72 C ATOM 614 C ARG A 77 -8.658 -9.466 -10.033 1.00 6.72 C ATOM 615 CB ARG A 77 -6.578 -10.335 -8.944 1.00 6.72 C ATOM 616 O ARG A 77 -9.624 -9.964 -9.449 1.00 6.72 O ATOM 617 CG ARG A 77 -6.025 -11.036 -10.174 1.00 6.72 C ATOM 618 CD ARG A 77 -5.161 -12.233 -9.800 1.00 6.72 C ATOM 619 NE ARG A 77 -4.366 -12.698 -10.933 1.00 6.72 N ATOM 620 NH1 ARG A 77 -3.944 -14.788 -10.043 1.00 6.72 N ATOM 621 NH2 ARG A 77 -3.103 -14.221 -12.098 1.00 6.72 N ATOM 622 CZ ARG A 77 -3.806 -13.901 -11.022 1.00 6.72 C ATOM 623 N GLU A 78 -8.703 -8.968 -11.357 1.00 6.72 N ATOM 624 CA GLU A 78 -9.710 -9.433 -12.306 1.00 6.72 C ATOM 625 C GLU A 78 -9.072 -10.231 -13.440 1.00 6.72 C ATOM 626 CB GLU A 78 -10.500 -8.252 -12.875 1.00 6.72 C ATOM 627 O GLU A 78 -7.847 -10.344 -13.513 1.00 6.72 O ATOM 628 CG GLU A 78 -11.352 -7.528 -11.842 1.00 6.72 C ATOM 629 CD GLU A 78 -12.234 -6.446 -12.444 1.00 6.72 C ATOM 630 OE1 GLU A 78 -12.957 -5.760 -11.686 1.00 6.72 O ATOM 631 OE2 GLU A 78 -12.203 -6.283 -13.684 1.00 6.72 O ATOM 632 N LYS A 79 -9.991 -10.926 -14.239 1.00 6.72 N ATOM 633 CA LYS A 79 -9.539 -11.713 -15.383 1.00 6.72 C ATOM 634 C LYS A 79 -8.611 -10.898 -16.279 1.00 6.72 C ATOM 635 CB LYS A 79 -10.735 -12.221 -16.191 1.00 6.72 C ATOM 636 O LYS A 79 -7.610 -11.415 -16.778 1.00 6.72 O ATOM 637 CG LYS A 79 -10.419 -13.415 -17.079 1.00 6.72 C ATOM 638 CD LYS A 79 -11.665 -13.928 -17.790 1.00 6.72 C ATOM 639 CE LYS A 79 -11.329 -15.033 -18.782 1.00 6.72 C ATOM 640 NZ LYS A 79 -12.556 -15.601 -19.415 1.00 6.72 N ATOM 641 N SER A 80 -8.775 -9.596 -16.232 1.00 6.72 N ATOM 642 CA SER A 80 -8.111 -8.740 -17.209 1.00 6.72 C ATOM 643 C SER A 80 -6.887 -8.057 -16.606 1.00 6.72 C ATOM 644 CB SER A 80 -9.080 -7.685 -17.745 1.00 6.72 C ATOM 645 O SER A 80 -6.072 -7.482 -17.329 1.00 6.72 O ATOM 646 OG SER A 80 -9.634 -6.926 -16.684 1.00 6.72 O ATOM 647 N GLY A 81 -6.705 -8.234 -15.324 1.00 6.72 N ATOM 648 CA GLY A 81 -5.576 -7.527 -14.740 1.00 6.72 C ATOM 649 C GLY A 81 -5.757 -7.232 -13.263 1.00 6.72 C ATOM 650 O GLY A 81 -6.659 -7.775 -12.622 1.00 6.72 O ATOM 651 N VAL A 82 -4.698 -6.651 -12.655 1.00 6.72 N ATOM 652 CA VAL A 82 -4.661 -6.238 -11.256 1.00 6.72 C ATOM 653 C VAL A 82 -4.972 -4.747 -11.149 1.00 6.72 C ATOM 654 CB VAL A 82 -3.292 -6.545 -10.609 1.00 6.72 C ATOM 655 O VAL A 82 -4.465 -3.943 -11.935 1.00 6.72 O ATOM 656 CG1 VAL A 82 -3.263 -6.076 -9.156 1.00 6.72 C ATOM 657 CG2 VAL A 82 -2.983 -8.039 -10.698 1.00 6.72 C ATOM 658 N TYR A 83 -5.928 -4.428 -10.292 1.00 6.72 N ATOM 659 CA TYR A 83 -6.336 -3.045 -10.073 1.00 6.72 C ATOM 660 C TYR A 83 -5.965 -2.583 -8.668 1.00 6.72 C ATOM 661 CB TYR A 83 -7.843 -2.888 -10.293 1.00 6.72 C ATOM 662 O TYR A 83 -5.976 -3.376 -7.724 1.00 6.72 O ATOM 663 CG TYR A 83 -8.298 -3.276 -11.679 1.00 6.72 C ATOM 664 CD1 TYR A 83 -8.526 -4.610 -12.011 1.00 6.72 C ATOM 665 CD2 TYR A 83 -8.499 -2.311 -12.660 1.00 6.72 C ATOM 666 CE1 TYR A 83 -8.942 -4.973 -13.287 1.00 6.72 C ATOM 667 CE2 TYR A 83 -8.916 -2.662 -13.940 1.00 6.72 C ATOM 668 OH TYR A 83 -9.548 -4.347 -15.509 1.00 6.72 O ATOM 669 CZ TYR A 83 -9.135 -3.993 -14.243 1.00 6.72 C ATOM 670 N VAL A 84 -5.503 -1.346 -8.569 1.00 4.66 N ATOM 671 CA VAL A 84 -5.269 -0.727 -7.268 1.00 4.66 C ATOM 672 C VAL A 84 -6.170 0.496 -7.109 1.00 4.66 C ATOM 673 CB VAL A 84 -3.788 -0.325 -7.089 1.00 4.66 C ATOM 674 O VAL A 84 -6.240 1.343 -8.002 1.00 4.66 O ATOM 675 CG1 VAL A 84 -3.573 0.352 -5.737 1.00 4.66 C ATOM 676 CG2 VAL A 84 -2.884 -1.549 -7.227 1.00 4.66 C ATOM 677 N ARG A 85 -6.913 0.488 -6.095 1.00 6.72 N ATOM 678 CA ARG A 85 -7.754 1.633 -5.763 1.00 6.72 C ATOM 679 C ARG A 85 -7.206 2.383 -4.553 1.00 6.72 C ATOM 680 CB ARG A 85 -9.192 1.183 -5.492 1.00 6.72 C ATOM 681 O ARG A 85 -6.730 1.766 -3.597 1.00 6.72 O ATOM 682 CG ARG A 85 -10.184 2.329 -5.379 1.00 6.72 C ATOM 683 CD ARG A 85 -11.596 1.828 -5.108 1.00 6.72 C ATOM 684 NE ARG A 85 -12.400 1.796 -6.326 1.00 6.72 N ATOM 685 NH1 ARG A 85 -14.250 0.839 -5.327 1.00 6.72 N ATOM 686 NH2 ARG A 85 -14.283 1.347 -7.562 1.00 6.72 N ATOM 687 CZ ARG A 85 -13.643 1.327 -6.402 1.00 6.72 C ATOM 688 N THR A 86 -7.071 3.732 -4.691 1.00 6.72 N ATOM 689 CA THR A 86 -6.621 4.528 -3.555 1.00 6.72 C ATOM 690 C THR A 86 -7.733 5.453 -3.068 1.00 6.72 C ATOM 691 CB THR A 86 -5.376 5.361 -3.914 1.00 6.72 C ATOM 692 O THR A 86 -8.527 5.952 -3.868 1.00 6.72 O ATOM 693 CG2 THR A 86 -4.246 4.471 -4.420 1.00 6.72 C ATOM 694 OG1 THR A 86 -5.719 6.306 -4.935 1.00 6.72 O ATOM 695 N ASN A 87 -7.936 5.475 -1.707 1.00 6.72 N ATOM 696 CA ASN A 87 -8.831 6.444 -1.084 1.00 6.72 C ATOM 697 C ASN A 87 -8.087 7.347 -0.105 1.00 6.72 C ATOM 698 CB ASN A 87 -9.985 5.730 -0.376 1.00 6.72 C ATOM 699 O ASN A 87 -7.297 6.868 0.711 1.00 6.72 O ATOM 700 CG ASN A 87 -10.918 5.027 -1.342 1.00 6.72 C ATOM 701 ND2 ASN A 87 -11.709 4.093 -0.828 1.00 6.72 N ATOM 702 OD1 ASN A 87 -10.927 5.321 -2.540 1.00 6.72 O ATOM 703 N LYS A 88 -8.092 8.633 -0.265 1.00 6.72 N ATOM 704 CA LYS A 88 -7.558 9.565 0.724 1.00 6.72 C ATOM 705 C LYS A 88 -8.305 9.448 2.049 1.00 6.72 C ATOM 706 CB LYS A 88 -7.634 11.001 0.204 1.00 6.72 C ATOM 707 O LYS A 88 -9.536 9.505 2.081 1.00 6.72 O ATOM 708 CG LYS A 88 -6.902 12.014 1.072 1.00 6.72 C ATOM 709 CD LYS A 88 -6.972 13.415 0.478 1.00 6.72 C ATOM 710 CE LYS A 88 -6.293 14.439 1.377 1.00 6.72 C ATOM 711 NZ LYS A 88 -6.372 15.816 0.806 1.00 6.72 N ATOM 712 N LEU A 89 -7.493 9.040 3.089 1.00 6.72 N ATOM 713 CA LEU A 89 -8.056 8.925 4.430 1.00 6.72 C ATOM 714 C LEU A 89 -8.211 10.298 5.074 1.00 6.72 C ATOM 715 CB LEU A 89 -7.174 8.033 5.307 1.00 6.72 C ATOM 716 O LEU A 89 -7.367 11.177 4.884 1.00 6.72 O ATOM 717 CG LEU A 89 -7.197 6.537 4.993 1.00 6.72 C ATOM 718 CD1 LEU A 89 -6.028 5.834 5.676 1.00 6.72 C ATOM 719 CD2 LEU A 89 -8.523 5.920 5.422 1.00 6.72 C ATOM 720 N GLY A 90 -9.340 10.708 5.578 1.00 6.72 N ATOM 721 CA GLY A 90 -9.715 11.894 6.333 1.00 6.72 C ATOM 722 C GLY A 90 -10.588 12.851 5.544 1.00 6.72 C ATOM 723 O GLY A 90 -11.001 13.892 6.061 1.00 6.72 O ATOM 724 N PHE A 91 -10.821 12.471 4.312 1.00 8.64 N ATOM 725 CA PHE A 91 -11.769 13.293 3.569 1.00 8.64 C ATOM 726 C PHE A 91 -12.999 12.482 3.179 1.00 8.64 C ATOM 727 CB PHE A 91 -11.109 13.881 2.318 1.00 8.64 C ATOM 728 O PHE A 91 -12.889 11.479 2.471 1.00 8.64 O ATOM 729 CG PHE A 91 -10.275 15.103 2.589 1.00 8.64 C ATOM 730 CD1 PHE A 91 -8.918 14.989 2.865 1.00 8.64 C ATOM 731 CD2 PHE A 91 -10.848 16.368 2.568 1.00 8.64 C ATOM 732 CE1 PHE A 91 -8.143 16.119 3.117 1.00 8.64 C ATOM 733 CE2 PHE A 91 -10.081 17.502 2.818 1.00 8.64 C ATOM 734 CZ PHE A 91 -8.729 17.376 3.093 1.00 8.64 C ATOM 735 N GLU A 92 -13.879 12.165 4.125 1.00 8.64 N ATOM 736 CA GLU A 92 -15.112 11.423 3.881 1.00 8.64 C ATOM 737 C GLU A 92 -16.103 12.251 3.067 1.00 8.64 C ATOM 738 CB GLU A 92 -15.750 10.990 5.203 1.00 8.64 C ATOM 739 O GLU A 92 -16.591 13.281 3.535 1.00 8.64 O ATOM 740 CG GLU A 92 -15.244 9.651 5.721 1.00 8.64 C ATOM 741 CD GLU A 92 -15.990 9.164 6.954 1.00 8.64 C ATOM 742 OE1 GLU A 92 -15.708 8.041 7.429 1.00 8.64 O ATOM 743 OE2 GLU A 92 -16.864 9.911 7.447 1.00 8.64 O ATOM 744 N ASP A 93 -15.801 12.461 1.827 1.00 8.64 N ATOM 745 CA ASP A 93 -17.029 12.844 1.137 1.00 8.64 C ATOM 746 C ASP A 93 -17.790 11.614 0.648 1.00 8.64 C ATOM 747 CB ASP A 93 -16.717 13.772 -0.039 1.00 8.64 C ATOM 748 O ASP A 93 -17.320 10.899 -0.240 1.00 8.64 O ATOM 749 CG ASP A 93 -17.958 14.419 -0.628 1.00 8.64 C ATOM 750 OD1 ASP A 93 -17.828 15.359 -1.442 1.00 8.64 O ATOM 751 OD2 ASP A 93 -19.076 13.986 -0.274 1.00 8.64 O ATOM 752 N PRO A 94 -18.711 11.191 1.508 1.00 8.64 N ATOM 753 CA PRO A 94 -19.501 10.003 1.175 1.00 8.64 C ATOM 754 C PRO A 94 -20.029 10.028 -0.257 1.00 8.64 C ATOM 755 CB PRO A 94 -20.652 10.050 2.183 1.00 8.64 C ATOM 756 O PRO A 94 -20.234 8.972 -0.862 1.00 8.64 O ATOM 757 CG PRO A 94 -20.438 11.316 2.948 1.00 8.64 C ATOM 758 CD PRO A 94 -19.181 11.969 2.449 1.00 8.64 C ATOM 759 N LYS A 95 -19.825 11.145 -1.002 1.00 8.64 N ATOM 760 CA LYS A 95 -20.410 11.170 -2.340 1.00 8.64 C ATOM 761 C LYS A 95 -19.342 11.416 -3.402 1.00 8.64 C ATOM 762 CB LYS A 95 -21.496 12.243 -2.431 1.00 8.64 C ATOM 763 O LYS A 95 -19.636 11.407 -4.599 1.00 8.64 O ATOM 764 CG LYS A 95 -22.740 11.936 -1.610 1.00 8.64 C ATOM 765 CD LYS A 95 -23.832 12.972 -1.841 1.00 8.64 C ATOM 766 CE LYS A 95 -25.054 12.701 -0.973 1.00 8.64 C ATOM 767 NZ LYS A 95 -26.134 13.705 -1.208 1.00 8.64 N ATOM 768 N SER A 96 -18.077 11.513 -2.983 1.00 8.64 N ATOM 769 CA SER A 96 -17.157 11.939 -4.032 1.00 8.64 C ATOM 770 C SER A 96 -16.418 10.749 -4.635 1.00 8.64 C ATOM 771 CB SER A 96 -16.149 12.950 -3.483 1.00 8.64 C ATOM 772 O SER A 96 -15.813 9.955 -3.912 1.00 8.64 O ATOM 773 OG SER A 96 -14.940 12.907 -4.222 1.00 8.64 O ATOM 774 N PHE A 97 -16.938 10.059 -5.545 1.00 8.64 N ATOM 775 CA PHE A 97 -16.265 9.188 -6.501 1.00 8.64 C ATOM 776 C PHE A 97 -14.975 9.827 -7.000 1.00 8.64 C ATOM 777 CB PHE A 97 -17.186 8.871 -7.683 1.00 8.64 C ATOM 778 O PHE A 97 -14.111 9.144 -7.554 1.00 8.64 O ATOM 779 CG PHE A 97 -18.358 7.998 -7.322 1.00 8.64 C ATOM 780 CD1 PHE A 97 -19.593 8.558 -7.018 1.00 8.64 C ATOM 781 CD2 PHE A 97 -18.224 6.616 -7.288 1.00 8.64 C ATOM 782 CE1 PHE A 97 -20.679 7.752 -6.684 1.00 8.64 C ATOM 783 CE2 PHE A 97 -19.305 5.804 -6.955 1.00 8.64 C ATOM 784 CZ PHE A 97 -20.531 6.375 -6.652 1.00 8.64 C ATOM 785 N LEU A 98 -14.602 11.045 -6.442 1.00 8.64 N ATOM 786 CA LEU A 98 -13.538 11.768 -7.129 1.00 8.64 C ATOM 787 C LEU A 98 -12.193 11.530 -6.451 1.00 8.64 C ATOM 788 CB LEU A 98 -13.845 13.267 -7.166 1.00 8.64 C ATOM 789 O LEU A 98 -11.141 11.781 -7.043 1.00 8.64 O ATOM 790 CG LEU A 98 -14.980 13.704 -8.094 1.00 8.64 C ATOM 791 CD1 LEU A 98 -15.347 15.161 -7.833 1.00 8.64 C ATOM 792 CD2 LEU A 98 -14.586 13.500 -9.553 1.00 8.64 C ATOM 793 N SER A 99 -12.192 10.556 -5.446 1.00 8.64 N ATOM 794 CA SER A 99 -10.815 10.410 -4.984 1.00 8.64 C ATOM 795 C SER A 99 -10.321 8.979 -5.164 1.00 8.64 C ATOM 796 CB SER A 99 -10.696 10.819 -3.515 1.00 8.64 C ATOM 797 O SER A 99 -9.273 8.607 -4.630 1.00 8.64 O ATOM 798 OG SER A 99 -11.600 10.080 -2.712 1.00 8.64 O ATOM 799 N ILE A 100 -11.121 8.337 -6.116 1.00 6.72 N ATOM 800 CA ILE A 100 -10.638 6.974 -6.304 1.00 6.72 C ATOM 801 C ILE A 100 -9.891 6.870 -7.632 1.00 6.72 C ATOM 802 CB ILE A 100 -11.796 5.953 -6.259 1.00 6.72 C ATOM 803 O ILE A 100 -10.389 7.318 -8.668 1.00 6.72 O ATOM 804 CG1 ILE A 100 -12.507 6.010 -4.902 1.00 6.72 C ATOM 805 CG2 ILE A 100 -11.282 4.539 -6.549 1.00 6.72 C ATOM 806 CD1 ILE A 100 -13.793 5.197 -4.841 1.00 6.72 C ATOM 807 N LYS A 101 -8.620 6.701 -7.581 1.00 6.72 N ATOM 808 CA LYS A 101 -7.845 6.403 -8.782 1.00 6.72 C ATOM 809 C LYS A 101 -7.608 4.902 -8.924 1.00 6.72 C ATOM 810 CB LYS A 101 -6.507 7.144 -8.756 1.00 6.72 C ATOM 811 O LYS A 101 -7.289 4.223 -7.946 1.00 6.72 O ATOM 812 CG LYS A 101 -6.629 8.647 -8.958 1.00 6.72 C ATOM 813 CD LYS A 101 -5.263 9.304 -9.110 1.00 6.72 C ATOM 814 CE LYS A 101 -5.380 10.815 -9.257 1.00 6.72 C ATOM 815 NZ LYS A 101 -4.046 11.459 -9.443 1.00 6.72 N ATOM 816 N GLU A 102 -8.161 4.357 -9.913 1.00 8.64 N ATOM 817 CA GLU A 102 -7.946 2.952 -10.245 1.00 8.64 C ATOM 818 C GLU A 102 -6.847 2.794 -11.292 1.00 8.64 C ATOM 819 CB GLU A 102 -9.244 2.312 -10.744 1.00 8.64 C ATOM 820 O GLU A 102 -6.808 3.537 -12.275 1.00 8.64 O ATOM 821 CG GLU A 102 -9.192 0.793 -10.818 1.00 8.64 C ATOM 822 CD GLU A 102 -10.515 0.167 -11.229 1.00 8.64 C ATOM 823 OE1 GLU A 102 -10.588 -0.435 -12.325 1.00 8.64 O ATOM 824 OE2 GLU A 102 -11.488 0.280 -10.449 1.00 8.64 O ATOM 825 N TYR A 103 -5.920 1.999 -10.999 1.00 6.72 N ATOM 826 CA TYR A 103 -4.857 1.671 -11.943 1.00 6.72 C ATOM 827 C TYR A 103 -5.001 0.241 -12.451 1.00 6.72 C ATOM 828 CB TYR A 103 -3.483 1.857 -11.292 1.00 6.72 C ATOM 829 O TYR A 103 -5.256 -0.679 -11.670 1.00 6.72 O ATOM 830 CG TYR A 103 -3.244 3.253 -10.767 1.00 6.72 C ATOM 831 CD1 TYR A 103 -3.589 3.595 -9.462 1.00 6.72 C ATOM 832 CD2 TYR A 103 -2.676 4.231 -11.576 1.00 6.72 C ATOM 833 CE1 TYR A 103 -3.372 4.880 -8.975 1.00 6.72 C ATOM 834 CE2 TYR A 103 -2.455 5.519 -11.100 1.00 6.72 C ATOM 835 OH TYR A 103 -2.589 7.107 -9.323 1.00 6.72 O ATOM 836 CZ TYR A 103 -2.805 5.833 -9.800 1.00 6.72 C ATOM 837 N LYS A 104 -5.083 -0.004 -13.802 1.00 8.64 N ATOM 838 CA LYS A 104 -5.140 -1.339 -14.393 1.00 8.64 C ATOM 839 C LYS A 104 -3.759 -1.796 -14.852 1.00 8.64 C ATOM 840 CB LYS A 104 -6.119 -1.364 -15.568 1.00 8.64 C ATOM 841 O LYS A 104 -3.042 -1.048 -15.520 1.00 8.64 O ATOM 842 CG LYS A 104 -6.341 -2.749 -16.158 1.00 8.64 C ATOM 843 CD LYS A 104 -7.313 -2.708 -17.331 1.00 8.64 C ATOM 844 CE LYS A 104 -7.429 -4.065 -18.010 1.00 8.64 C ATOM 845 NZ LYS A 104 -8.354 -4.022 -19.181 1.00 8.64 N ATOM 846 N PHE A 105 -3.346 -2.868 -14.276 1.00 8.64 N ATOM 847 CA PHE A 105 -2.144 -3.522 -14.782 1.00 8.64 C ATOM 848 C PHE A 105 -2.504 -4.749 -15.611 1.00 8.64 C ATOM 849 CB PHE A 105 -1.221 -3.921 -13.626 1.00 8.64 C ATOM 850 O PHE A 105 -3.367 -5.537 -15.220 1.00 8.64 O ATOM 851 CG PHE A 105 -0.739 -2.756 -12.804 1.00 8.64 C ATOM 852 CD1 PHE A 105 -1.429 -2.357 -11.666 1.00 8.64 C ATOM 853 CD2 PHE A 105 0.405 -2.059 -13.171 1.00 8.64 C ATOM 854 CE1 PHE A 105 -0.985 -1.279 -10.904 1.00 8.64 C ATOM 855 CE2 PHE A 105 0.855 -0.981 -12.414 1.00 8.64 C ATOM 856 CZ PHE A 105 0.158 -0.592 -11.282 1.00 8.64 C ATOM 857 N GLY A 106 -2.172 -4.885 -16.945 1.00 8.64 N ATOM 858 CA GLY A 106 -2.470 -5.978 -17.858 1.00 8.64 C ATOM 859 C GLY A 106 -1.496 -7.136 -17.740 1.00 8.64 C ATOM 860 O GLY A 106 -0.364 -6.957 -17.287 1.00 8.64 O ATOM 861 N THR A 107 -1.964 -8.404 -17.592 1.00 8.64 N ATOM 862 CA THR A 107 -1.518 -9.786 -17.454 1.00 8.64 C ATOM 863 C THR A 107 -0.972 -10.313 -18.777 1.00 8.64 C ATOM 864 CB THR A 107 -2.662 -10.696 -16.969 1.00 8.64 C ATOM 865 O THR A 107 -0.155 -11.237 -18.794 1.00 8.64 O ATOM 866 CG2 THR A 107 -2.988 -10.435 -15.502 1.00 8.64 C ATOM 867 OG1 THR A 107 -3.831 -10.446 -17.758 1.00 8.64 O ATOM 868 N ARG A 108 -0.421 -9.500 -19.707 1.00 8.64 N ATOM 869 CA ARG A 108 0.415 -10.048 -20.770 1.00 8.64 C ATOM 870 C ARG A 108 0.370 -9.165 -22.012 1.00 8.64 C ATOM 871 CB ARG A 108 -0.025 -11.471 -21.121 1.00 8.64 C ATOM 872 O ARG A 108 1.162 -9.347 -22.939 1.00 8.64 O ATOM 873 CG ARG A 108 0.888 -12.553 -20.567 1.00 8.64 C ATOM 874 CD ARG A 108 0.437 -13.943 -20.992 1.00 8.64 C ATOM 875 NE ARG A 108 1.440 -14.956 -20.674 1.00 8.64 N ATOM 876 NH1 ARG A 108 0.214 -16.728 -21.506 1.00 8.64 N ATOM 877 NH2 ARG A 108 2.286 -17.089 -20.593 1.00 8.64 N ATOM 878 CZ ARG A 108 1.311 -16.255 -20.925 1.00 8.64 C ATOM 879 N THR A 109 0.007 -7.906 -21.921 1.00 8.64 N ATOM 880 CA THR A 109 0.199 -7.193 -23.179 1.00 8.64 C ATOM 881 C THR A 109 0.557 -5.731 -22.923 1.00 8.64 C ATOM 882 CB THR A 109 -1.060 -7.269 -24.063 1.00 8.64 C ATOM 883 O THR A 109 -0.113 -5.050 -22.143 1.00 8.64 O ATOM 884 CG2 THR A 109 -1.194 -8.643 -24.711 1.00 8.64 C ATOM 885 OG1 THR A 109 -2.218 -7.018 -23.257 1.00 8.64 O ATOM 886 N GLY A 110 1.725 -5.448 -22.409 1.00 8.64 N ATOM 887 CA GLY A 110 2.620 -4.305 -22.494 1.00 8.64 C ATOM 888 C GLY A 110 1.933 -3.044 -22.984 1.00 8.64 C ATOM 889 O GLY A 110 1.499 -2.976 -24.136 1.00 8.64 O ATOM 890 N GLY A 111 0.749 -2.551 -22.421 1.00 8.64 N ATOM 891 CA GLY A 111 0.179 -1.258 -22.766 1.00 8.64 C ATOM 892 C GLY A 111 1.093 -0.094 -22.431 1.00 8.64 C ATOM 893 O GLY A 111 1.993 -0.225 -21.598 1.00 8.64 O ATOM 894 N ASN A 112 1.646 0.666 -23.583 1.00 8.64 N ATOM 895 CA ASN A 112 2.351 1.904 -23.896 1.00 8.64 C ATOM 896 C ASN A 112 2.500 2.792 -22.664 1.00 8.64 C ATOM 897 CB ASN A 112 1.633 2.664 -25.014 1.00 8.64 C ATOM 898 O ASN A 112 1.528 3.028 -21.943 1.00 8.64 O ATOM 899 CG ASN A 112 1.795 2.002 -26.368 1.00 8.64 C ATOM 900 ND2 ASN A 112 0.868 2.277 -27.278 1.00 8.64 N ATOM 901 OD1 ASN A 112 2.746 1.248 -26.594 1.00 8.64 O ATOM 902 N PHE A 113 3.510 2.618 -21.947 1.00 8.64 N ATOM 903 CA PHE A 113 4.082 3.644 -21.083 1.00 8.64 C ATOM 904 C PHE A 113 4.194 4.972 -21.821 1.00 8.64 C ATOM 905 CB PHE A 113 5.459 3.211 -20.570 1.00 8.64 C ATOM 906 O PHE A 113 4.651 5.016 -22.966 1.00 8.64 O ATOM 907 CG PHE A 113 5.526 3.047 -19.075 1.00 8.64 C ATOM 908 CD1 PHE A 113 5.224 1.827 -18.482 1.00 8.64 C ATOM 909 CD2 PHE A 113 5.890 4.113 -18.264 1.00 8.64 C ATOM 910 CE1 PHE A 113 5.285 1.672 -17.099 1.00 8.64 C ATOM 911 CE2 PHE A 113 5.953 3.966 -16.881 1.00 8.64 C ATOM 912 CZ PHE A 113 5.649 2.745 -16.300 1.00 8.64 C ATOM 913 N THR A 114 3.305 5.791 -21.704 1.00 8.64 N ATOM 914 CA THR A 114 3.524 7.113 -22.280 1.00 8.64 C ATOM 915 C THR A 114 4.409 7.959 -21.369 1.00 8.64 C ATOM 916 CB THR A 114 2.190 7.843 -22.526 1.00 8.64 C ATOM 917 O THR A 114 4.850 9.044 -21.756 1.00 8.64 O ATOM 918 CG2 THR A 114 1.348 7.113 -23.568 1.00 8.64 C ATOM 919 OG1 THR A 114 1.456 7.913 -21.298 1.00 8.64 O ATOM 920 N GLY A 115 5.268 7.248 -20.677 1.00 8.64 N ATOM 921 CA GLY A 115 6.263 8.086 -20.027 1.00 8.64 C ATOM 922 C GLY A 115 7.507 7.322 -19.614 1.00 8.64 C ATOM 923 O GLY A 115 7.525 6.090 -19.647 1.00 8.64 O ATOM 924 N GLU A 116 8.641 7.657 -20.084 1.00 8.64 N ATOM 925 CA GLU A 116 9.970 7.216 -19.672 1.00 8.64 C ATOM 926 C GLU A 116 10.120 7.260 -18.154 1.00 8.64 C ATOM 927 CB GLU A 116 11.051 8.077 -20.332 1.00 8.64 C ATOM 928 O GLU A 116 9.646 8.194 -17.505 1.00 8.64 O ATOM 929 CG GLU A 116 11.400 7.645 -21.749 1.00 8.64 C ATOM 930 CD GLU A 116 12.569 8.417 -22.341 1.00 8.64 C ATOM 931 OE1 GLU A 116 12.995 8.099 -23.474 1.00 8.64 O ATOM 932 OE2 GLU A 116 13.062 9.347 -21.665 1.00 8.64 O ATOM 933 N LEU A 117 10.088 5.989 -17.564 1.00 8.64 N ATOM 934 CA LEU A 117 10.578 5.973 -16.190 1.00 8.64 C ATOM 935 C LEU A 117 12.036 6.415 -16.127 1.00 8.64 C ATOM 936 CB LEU A 117 10.430 4.575 -15.584 1.00 8.64 C ATOM 937 O LEU A 117 12.809 6.155 -17.053 1.00 8.64 O ATOM 938 CG LEU A 117 9.001 4.097 -15.323 1.00 8.64 C ATOM 939 CD1 LEU A 117 8.989 2.601 -15.025 1.00 8.64 C ATOM 940 CD2 LEU A 117 8.376 4.881 -14.175 1.00 8.64 C ATOM 941 N THR A 118 12.196 7.278 -15.327 1.00 8.64 N ATOM 942 CA THR A 118 13.590 7.626 -15.076 1.00 8.64 C ATOM 943 C THR A 118 14.353 6.432 -14.511 1.00 8.64 C ATOM 944 CB THR A 118 13.702 8.816 -14.105 1.00 8.64 C ATOM 945 O THR A 118 13.747 5.457 -14.061 1.00 8.64 O ATOM 946 CG2 THR A 118 12.896 10.011 -14.604 1.00 8.64 C ATOM 947 OG1 THR A 118 13.207 8.424 -12.818 1.00 8.64 O ATOM 948 N LYS A 119 15.698 6.199 -14.938 1.00 8.64 N ATOM 949 CA LYS A 119 16.574 5.167 -14.391 1.00 8.64 C ATOM 950 C LYS A 119 16.371 5.015 -12.886 1.00 8.64 C ATOM 951 CB LYS A 119 18.038 5.489 -14.693 1.00 8.64 C ATOM 952 O LYS A 119 16.303 3.897 -12.373 1.00 8.64 O ATOM 953 CG LYS A 119 18.973 4.296 -14.566 1.00 8.64 C ATOM 954 CD LYS A 119 20.389 4.646 -15.006 1.00 8.64 C ATOM 955 CE LYS A 119 21.344 3.477 -14.803 1.00 8.64 C ATOM 956 NZ LYS A 119 22.724 3.802 -15.272 1.00 8.64 N ATOM 957 N GLN A 120 16.211 6.129 -12.176 1.00 8.64 N ATOM 958 CA GLN A 120 16.025 6.126 -10.729 1.00 8.64 C ATOM 959 C GLN A 120 14.683 5.507 -10.349 1.00 8.64 C ATOM 960 CB GLN A 120 16.124 7.547 -10.171 1.00 8.64 C ATOM 961 O GLN A 120 14.600 4.729 -9.396 1.00 8.64 O ATOM 962 CG GLN A 120 17.540 7.960 -9.792 1.00 8.64 C ATOM 963 CD GLN A 120 17.891 9.357 -10.270 1.00 8.64 C ATOM 964 NE2 GLN A 120 19.145 9.751 -10.077 1.00 8.64 N ATOM 965 OE1 GLN A 120 17.043 10.074 -10.809 1.00 8.64 O ATOM 966 N GLU A 121 13.628 5.733 -11.076 1.00 8.64 N ATOM 967 CA GLU A 121 12.298 5.200 -10.795 1.00 8.64 C ATOM 968 C GLU A 121 12.253 3.689 -11.006 1.00 8.64 C ATOM 969 CB GLU A 121 11.248 5.885 -11.674 1.00 8.64 C ATOM 970 O GLU A 121 11.648 2.965 -10.213 1.00 8.64 O ATOM 971 CG GLU A 121 10.953 7.323 -11.272 1.00 8.64 C ATOM 972 CD GLU A 121 10.094 8.064 -12.284 1.00 8.64 C ATOM 973 OE1 GLU A 121 9.364 9.002 -11.889 1.00 8.64 O ATOM 974 OE2 GLU A 121 10.149 7.704 -13.481 1.00 8.64 O ATOM 975 N LEU A 122 12.979 3.340 -12.063 1.00 8.64 N ATOM 976 CA LEU A 122 13.046 1.913 -12.359 1.00 8.64 C ATOM 977 C LEU A 122 13.813 1.168 -11.272 1.00 8.64 C ATOM 978 CB LEU A 122 13.709 1.678 -13.719 1.00 8.64 C ATOM 979 O LEU A 122 13.397 0.090 -10.840 1.00 8.64 O ATOM 980 CG LEU A 122 12.936 0.805 -14.709 1.00 8.64 C ATOM 981 CD1 LEU A 122 12.751 1.540 -16.032 1.00 8.64 C ATOM 982 CD2 LEU A 122 13.653 -0.523 -14.925 1.00 8.64 C ATOM 983 N VAL A 123 14.840 1.780 -10.710 1.00 8.64 N ATOM 984 CA VAL A 123 15.653 1.191 -9.651 1.00 8.64 C ATOM 985 C VAL A 123 14.832 1.085 -8.368 1.00 8.64 C ATOM 986 CB VAL A 123 16.936 2.013 -9.397 1.00 8.64 C ATOM 987 O VAL A 123 14.826 0.040 -7.712 1.00 8.64 O ATOM 988 CG1 VAL A 123 17.646 1.529 -8.134 1.00 8.64 C ATOM 989 CG2 VAL A 123 17.870 1.931 -10.603 1.00 8.64 C ATOM 990 N TYR A 124 14.059 2.039 -8.098 1.00 8.64 N ATOM 991 CA TYR A 124 13.254 2.069 -6.881 1.00 8.64 C ATOM 992 C TYR A 124 12.121 1.051 -6.952 1.00 8.64 C ATOM 993 CB TYR A 124 12.683 3.471 -6.649 1.00 8.64 C ATOM 994 O TYR A 124 11.855 0.342 -5.979 1.00 8.64 O ATOM 995 CG TYR A 124 13.673 4.438 -6.047 1.00 8.64 C ATOM 996 CD1 TYR A 124 13.975 5.640 -6.682 1.00 8.64 C ATOM 997 CD2 TYR A 124 14.309 4.151 -4.844 1.00 8.64 C ATOM 998 CE1 TYR A 124 14.889 6.534 -6.133 1.00 8.64 C ATOM 999 CE2 TYR A 124 15.225 5.037 -4.286 1.00 8.64 C ATOM 1000 OH TYR A 124 16.413 7.105 -4.387 1.00 8.64 O ATOM 1001 CZ TYR A 124 15.507 6.224 -4.936 1.00 8.64 C ATOM 1002 N THR A 125 11.428 1.001 -8.096 1.00 6.72 N ATOM 1003 CA THR A 125 10.313 0.078 -8.276 1.00 6.72 C ATOM 1004 C THR A 125 10.789 -1.369 -8.188 1.00 6.72 C ATOM 1005 CB THR A 125 9.609 0.308 -9.626 1.00 6.72 C ATOM 1006 O THR A 125 10.169 -2.192 -7.510 1.00 6.72 O ATOM 1007 CG2 THR A 125 8.382 -0.585 -9.767 1.00 6.72 C ATOM 1008 OG1 THR A 125 9.202 1.679 -9.718 1.00 6.72 O ATOM 1009 N ASN A 126 11.985 -1.576 -8.827 1.00 8.64 N ATOM 1010 CA ASN A 126 12.563 -2.916 -8.803 1.00 8.64 C ATOM 1011 C ASN A 126 13.002 -3.311 -7.396 1.00 8.64 C ATOM 1012 CB ASN A 126 13.742 -3.009 -9.773 1.00 8.64 C ATOM 1013 O ASN A 126 12.771 -4.442 -6.965 1.00 8.64 O ATOM 1014 CG ASN A 126 13.310 -3.334 -11.189 1.00 8.64 C ATOM 1015 ND2 ASN A 126 14.170 -3.035 -12.156 1.00 8.64 N ATOM 1016 OD1 ASN A 126 12.211 -3.848 -11.413 1.00 8.64 O ATOM 1017 N GLN A 127 13.590 -2.342 -6.627 1.00 8.64 N ATOM 1018 CA GLN A 127 14.004 -2.576 -5.247 1.00 8.64 C ATOM 1019 C GLN A 127 12.798 -2.827 -4.346 1.00 8.64 C ATOM 1020 CB GLN A 127 14.814 -1.390 -4.721 1.00 8.64 C ATOM 1021 O GLN A 127 12.824 -3.725 -3.501 1.00 8.64 O ATOM 1022 CG GLN A 127 16.303 -1.478 -5.029 1.00 8.64 C ATOM 1023 CD GLN A 127 17.083 -0.291 -4.496 1.00 8.64 C ATOM 1024 NE2 GLN A 127 18.405 -0.421 -4.454 1.00 8.64 N ATOM 1025 OE1 GLN A 127 16.503 0.734 -4.125 1.00 8.64 O ATOM 1026 N TRP A 128 11.824 -2.167 -4.535 1.00 6.72 N ATOM 1027 CA TRP A 128 10.602 -2.286 -3.746 1.00 6.72 C ATOM 1028 C TRP A 128 9.926 -3.632 -3.989 1.00 6.72 C ATOM 1029 CB TRP A 128 9.634 -1.147 -4.077 1.00 6.72 C ATOM 1030 O TRP A 128 9.562 -4.331 -3.040 1.00 6.72 O ATOM 1031 CG TRP A 128 8.375 -1.162 -3.264 1.00 6.72 C ATOM 1032 CD1 TRP A 128 8.207 -0.675 -1.997 1.00 6.72 C ATOM 1033 CD2 TRP A 128 7.108 -1.696 -3.661 1.00 6.72 C ATOM 1034 CE2 TRP A 128 6.216 -1.497 -2.584 1.00 6.72 C ATOM 1035 CE3 TRP A 128 6.641 -2.322 -4.824 1.00 6.72 C ATOM 1036 NE1 TRP A 128 6.910 -0.874 -1.583 1.00 6.72 N ATOM 1037 CH2 TRP A 128 4.449 -2.515 -3.786 1.00 6.72 C ATOM 1038 CZ2 TRP A 128 4.880 -1.904 -2.637 1.00 6.72 C ATOM 1039 CZ3 TRP A 128 5.311 -2.726 -4.874 1.00 6.72 C ATOM 1040 N VAL A 129 9.837 -4.041 -5.286 1.00 6.72 N ATOM 1041 CA VAL A 129 9.170 -5.280 -5.670 1.00 6.72 C ATOM 1042 C VAL A 129 9.963 -6.477 -5.149 1.00 6.72 C ATOM 1043 CB VAL A 129 8.999 -5.381 -7.203 1.00 6.72 C ATOM 1044 O VAL A 129 9.389 -7.411 -4.585 1.00 6.72 O ATOM 1045 CG1 VAL A 129 8.505 -6.771 -7.600 1.00 6.72 C ATOM 1046 CG2 VAL A 129 8.036 -4.306 -7.703 1.00 6.72 C ATOM 1047 N ASN A 130 11.351 -6.333 -5.277 1.00 8.64 N ATOM 1048 CA ASN A 130 12.247 -7.407 -4.861 1.00 8.64 C ATOM 1049 C ASN A 130 12.259 -7.571 -3.344 1.00 8.64 C ATOM 1050 CB ASN A 130 13.664 -7.155 -5.379 1.00 8.64 C ATOM 1051 O ASN A 130 12.263 -8.695 -2.837 1.00 8.64 O ATOM 1052 CG ASN A 130 13.854 -7.617 -6.810 1.00 8.64 C ATOM 1053 ND2 ASN A 130 14.863 -7.073 -7.481 1.00 8.64 N ATOM 1054 OD1 ASN A 130 13.100 -8.457 -7.309 1.00 8.64 O ATOM 1055 N GLU A 131 12.069 -6.443 -2.521 1.00 8.64 N ATOM 1056 CA GLU A 131 12.094 -6.449 -1.061 1.00 8.64 C ATOM 1057 C GLU A 131 10.759 -6.913 -0.488 1.00 8.64 C ATOM 1058 CB GLU A 131 12.442 -5.058 -0.524 1.00 8.64 C ATOM 1059 O GLU A 131 10.721 -7.591 0.541 1.00 8.64 O ATOM 1060 CG GLU A 131 13.913 -4.694 -0.665 1.00 8.64 C ATOM 1061 CD GLU A 131 14.234 -3.292 -0.171 1.00 8.64 C ATOM 1062 OE1 GLU A 131 15.414 -2.879 -0.244 1.00 8.64 O ATOM 1063 OE2 GLU A 131 13.299 -2.603 0.293 1.00 8.64 O ATOM 1064 N ASN A 132 9.736 -6.720 -1.184 1.00 8.64 N ATOM 1065 CA ASN A 132 8.429 -6.916 -0.566 1.00 8.64 C ATOM 1066 C ASN A 132 7.786 -8.224 -1.016 1.00 8.64 C ATOM 1067 CB ASN A 132 7.506 -5.736 -0.876 1.00 8.64 C ATOM 1068 O ASN A 132 7.067 -8.865 -0.247 1.00 8.64 O ATOM 1069 CG ASN A 132 7.833 -4.505 -0.054 1.00 8.64 C ATOM 1070 ND2 ASN A 132 8.463 -3.521 -0.684 1.00 8.64 N ATOM 1071 OD1 ASN A 132 7.524 -4.440 1.139 1.00 8.64 O ATOM 1072 N ILE A 133 8.282 -8.675 -2.231 1.00 8.64 N ATOM 1073 CA ILE A 133 7.755 -9.943 -2.723 1.00 8.64 C ATOM 1074 C ILE A 133 8.504 -11.102 -2.068 1.00 8.64 C ATOM 1075 CB ILE A 133 7.858 -10.039 -4.261 1.00 8.64 C ATOM 1076 O ILE A 133 7.902 -12.121 -1.721 1.00 8.64 O ATOM 1077 CG1 ILE A 133 6.915 -9.029 -4.924 1.00 8.64 C ATOM 1078 CG2 ILE A 133 7.555 -11.464 -4.735 1.00 8.64 C ATOM 1079 CD1 ILE A 133 7.015 -8.993 -6.443 1.00 8.64 C ATOM 1080 N THR A 134 9.730 -10.791 -1.686 1.00 8.64 N ATOM 1081 CA THR A 134 10.543 -11.821 -1.050 1.00 8.64 C ATOM 1082 C THR A 134 10.104 -12.041 0.394 1.00 8.64 C ATOM 1083 CB THR A 134 12.038 -11.453 -1.085 1.00 8.64 C ATOM 1084 O THR A 134 10.048 -13.179 0.865 1.00 8.64 O ATOM 1085 CG2 THR A 134 12.910 -12.668 -0.785 1.00 8.64 C ATOM 1086 OG1 THR A 134 12.370 -10.951 -2.386 1.00 8.64 O ATOM 1087 N LEU A 135 9.481 -11.013 1.084 1.00 8.64 N ATOM 1088 CA LEU A 135 9.061 -11.103 2.479 1.00 8.64 C ATOM 1089 C LEU A 135 7.653 -11.678 2.586 1.00 8.64 C ATOM 1090 CB LEU A 135 9.114 -9.726 3.145 1.00 8.64 C ATOM 1091 O LEU A 135 7.369 -12.474 3.484 1.00 8.64 O ATOM 1092 CG LEU A 135 10.480 -9.278 3.668 1.00 8.64 C ATOM 1093 CD1 LEU A 135 10.532 -7.758 3.780 1.00 8.64 C ATOM 1094 CD2 LEU A 135 10.777 -9.929 5.014 1.00 8.64 C ATOM 1095 N ALA A 136 6.896 -11.485 1.503 1.00 8.64 N ATOM 1096 CA ALA A 136 5.482 -11.826 1.637 1.00 8.64 C ATOM 1097 C ALA A 136 5.208 -13.240 1.133 1.00 8.64 C ATOM 1098 CB ALA A 136 4.618 -10.818 0.882 1.00 8.64 C ATOM 1099 O ALA A 136 4.289 -13.909 1.611 1.00 8.64 O ATOM 1100 N ASN A 137 6.194 -13.758 0.415 1.00 8.64 N ATOM 1101 CA ASN A 137 6.057 -15.090 -0.164 1.00 8.64 C ATOM 1102 C ASN A 137 6.849 -16.128 0.626 1.00 8.64 C ATOM 1103 CB ASN A 137 6.499 -15.087 -1.629 1.00 8.64 C ATOM 1104 O ASN A 137 8.055 -15.975 0.826 1.00 8.64 O ATOM 1105 CG ASN A 137 5.464 -14.473 -2.550 1.00 8.64 C ATOM 1106 ND2 ASN A 137 5.908 -13.993 -3.705 1.00 8.64 N ATOM 1107 OD1 ASN A 137 4.274 -14.431 -2.226 1.00 8.64 O ATOM 1108 N GLY A 138 6.587 -16.377 1.995 1.00 8.64 N ATOM 1109 CA GLY A 138 6.876 -17.550 2.803 1.00 8.64 C ATOM 1110 C GLY A 138 7.966 -18.427 2.215 1.00 8.64 C ATOM 1111 O GLY A 138 8.031 -19.623 2.504 1.00 8.64 O ATOM 1112 N TYR A 139 9.137 -17.824 1.543 1.00 8.64 N ATOM 1113 CA TYR A 139 10.214 -18.693 1.080 1.00 8.64 C ATOM 1114 C TYR A 139 11.083 -19.153 2.245 1.00 8.64 C ATOM 1115 CB TYR A 139 11.076 -17.973 0.039 1.00 8.64 C ATOM 1116 O TYR A 139 11.385 -18.370 3.149 1.00 8.64 O ATOM 1117 CG TYR A 139 10.546 -18.087 -1.370 1.00 8.64 C ATOM 1118 CD1 TYR A 139 9.749 -17.085 -1.919 1.00 8.64 C ATOM 1119 CD2 TYR A 139 10.841 -19.197 -2.155 1.00 8.64 C ATOM 1120 CE1 TYR A 139 9.257 -17.187 -3.216 1.00 8.64 C ATOM 1121 CE2 TYR A 139 10.355 -19.309 -3.454 1.00 8.64 C ATOM 1122 OH TYR A 139 9.082 -18.406 -5.260 1.00 8.64 O ATOM 1123 CZ TYR A 139 9.566 -18.300 -3.975 1.00 8.64 C ATOM 1124 N ILE A 140 10.744 -20.317 2.913 1.00 8.64 N ATOM 1125 CA ILE A 140 11.618 -21.208 3.668 1.00 8.64 C ATOM 1126 C ILE A 140 13.062 -21.031 3.204 1.00 8.64 C ATOM 1127 CB ILE A 140 11.185 -22.684 3.518 1.00 8.64 C ATOM 1128 O ILE A 140 13.364 -21.194 2.020 1.00 8.64 O ATOM 1129 CG1 ILE A 140 9.748 -22.872 4.019 1.00 8.64 C ATOM 1130 CG2 ILE A 140 12.150 -23.609 4.265 1.00 8.64 C ATOM 1131 CD1 ILE A 140 9.252 -24.310 3.951 1.00 8.64 C ATOM 1132 N SER A 141 13.713 -20.010 3.556 1.00 8.64 N ATOM 1133 CA SER A 141 15.171 -20.025 3.497 1.00 8.64 C ATOM 1134 C SER A 141 15.734 -21.319 4.073 1.00 8.64 C ATOM 1135 CB SER A 141 15.750 -18.827 4.252 1.00 8.64 C ATOM 1136 O SER A 141 15.479 -21.652 5.233 1.00 8.64 O ATOM 1137 OG SER A 141 17.145 -18.982 4.447 1.00 8.64 O ATOM 1138 N ALA A 142 15.693 -22.473 3.364 1.00 8.64 N ATOM 1139 CA ALA A 142 16.460 -23.706 3.208 1.00 8.64 C ATOM 1140 C ALA A 142 17.958 -23.439 3.331 1.00 8.64 C ATOM 1141 CB ALA A 142 16.148 -24.360 1.864 1.00 8.64 C ATOM 1142 O ALA A 142 18.474 -22.483 2.749 1.00 8.64 O ATOM 1143 N ASP A 143 18.576 -22.902 4.585 1.00 8.64 N ATOM 1144 CA ASP A 143 19.977 -23.243 4.809 1.00 8.64 C ATOM 1145 C ASP A 143 20.646 -22.233 5.738 1.00 8.64 C ATOM 1146 CB ASP A 143 20.732 -23.315 3.480 1.00 8.64 C ATOM 1147 O ASP A 143 20.988 -21.126 5.317 1.00 8.64 O ATOM 1148 CG ASP A 143 21.865 -24.326 3.495 1.00 8.64 C ATOM 1149 OD1 ASP A 143 22.444 -24.609 2.424 1.00 8.64 O ATOM 1150 OD2 ASP A 143 22.180 -24.846 4.587 1.00 8.64 O ATOM 1151 N SER A 144 20.228 -21.957 7.002 1.00 8.64 N ATOM 1152 CA SER A 144 21.341 -21.510 7.832 1.00 8.64 C ATOM 1153 C SER A 144 21.253 -22.095 9.238 1.00 8.64 C ATOM 1154 CB SER A 144 21.373 -19.983 7.908 1.00 8.64 C ATOM 1155 O SER A 144 21.817 -21.541 10.183 1.00 8.64 O ATOM 1156 OG SER A 144 20.155 -19.479 8.427 1.00 8.64 O ATOM 1157 N ARG A 145 20.767 -23.335 9.468 1.00 8.64 N ATOM 1158 CA ARG A 145 20.907 -23.823 10.836 1.00 8.64 C ATOM 1159 C ARG A 145 22.363 -24.145 11.156 1.00 8.64 C ATOM 1160 CB ARG A 145 20.036 -25.062 11.058 1.00 8.64 C ATOM 1161 O ARG A 145 23.035 -24.835 10.387 1.00 8.64 O ATOM 1162 CG ARG A 145 18.542 -24.781 11.007 1.00 8.64 C ATOM 1163 CD ARG A 145 17.724 -26.058 11.140 1.00 8.64 C ATOM 1164 NE ARG A 145 17.859 -26.910 9.963 1.00 8.64 N ATOM 1165 NH1 ARG A 145 16.657 -28.674 10.846 1.00 8.64 N ATOM 1166 NH2 ARG A 145 17.532 -28.821 8.732 1.00 8.64 N ATOM 1167 CZ ARG A 145 17.349 -28.133 9.850 1.00 8.64 C ATOM 1168 N THR A 146 23.240 -23.194 11.377 1.00 8.64 N ATOM 1169 CA THR A 146 24.353 -23.445 12.287 1.00 8.64 C ATOM 1170 C THR A 146 23.848 -23.974 13.626 1.00 8.64 C ATOM 1171 CB THR A 146 25.186 -22.170 12.516 1.00 8.64 C ATOM 1172 O THR A 146 22.915 -23.417 14.208 1.00 8.64 O ATOM 1173 CG2 THR A 146 26.113 -21.899 11.336 1.00 8.64 C ATOM 1174 OG1 THR A 146 24.303 -21.054 12.683 1.00 8.64 O ATOM 1175 N VAL A 147 23.601 -25.297 13.669 1.00 8.64 N ATOM 1176 CA VAL A 147 23.604 -26.015 14.940 1.00 8.64 C ATOM 1177 C VAL A 147 25.042 -26.295 15.372 1.00 8.64 C ATOM 1178 CB VAL A 147 22.809 -27.337 14.846 1.00 8.64 C ATOM 1179 O VAL A 147 25.856 -26.768 14.575 1.00 8.64 O ATOM 1180 CG1 VAL A 147 22.708 -28.004 16.217 1.00 8.64 C ATOM 1181 CG2 VAL A 147 21.418 -27.082 14.269 1.00 8.64 C ATOM 1182 N ASP A 148 25.801 -25.404 15.970 1.00 8.64 N ATOM 1183 CA ASP A 148 26.582 -25.450 17.202 1.00 8.64 C ATOM 1184 C ASP A 148 27.024 -24.051 17.625 1.00 8.64 C ATOM 1185 CB ASP A 148 27.802 -26.358 17.031 1.00 8.64 C ATOM 1186 O ASP A 148 27.467 -23.256 16.793 1.00 8.64 O ATOM 1187 CG ASP A 148 27.486 -27.826 17.259 1.00 8.64 C ATOM 1188 OD1 ASP A 148 28.258 -28.694 16.799 1.00 8.64 O ATOM 1189 OD2 ASP A 148 26.454 -28.116 17.901 1.00 8.64 O TER 1190 ASP A 148 ENDMDL END ================================================ FILE: alphafold/relax/utils.py ================================================ # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Utils for minimization.""" import io from alphafold.common import residue_constants from Bio import PDB import numpy as np def overwrite_b_factors(pdb_str: str, bfactors: np.ndarray) -> str: """Overwrites the B-factors in pdb_str with contents of bfactors array. Args: pdb_str: An input PDB string. bfactors: A numpy array with shape [1, n_residues, 37]. We assume that the B-factors are per residue; i.e. that the nonzero entries are identical in [0, i, :]. Returns: A new PDB string with the B-factors replaced. """ if bfactors.shape[-1] != residue_constants.atom_type_num: raise ValueError( f'Invalid final dimension size for bfactors: {bfactors.shape[-1]}.') parser = PDB.PDBParser(QUIET=True) handle = io.StringIO(pdb_str) structure = parser.get_structure('', handle) curr_resid = ('', '', '') idx = -1 for atom in structure.get_atoms(): atom_resid = atom.parent.get_id() if atom_resid != curr_resid: idx += 1 if idx >= bfactors.shape[0]: raise ValueError('Index into bfactors exceeds number of residues. ' 'B-factors shape: {shape}, idx: {idx}.') curr_resid = atom_resid atom.bfactor = bfactors[idx, residue_constants.atom_order['CA']] new_pdb = io.StringIO() pdb_io = PDB.PDBIO() pdb_io.set_structure(structure) pdb_io.save(new_pdb) return new_pdb.getvalue() def assert_equal_nonterminal_atom_types( atom_mask: np.ndarray, ref_atom_mask: np.ndarray): """Checks that pre- and post-minimized proteins have same atom set.""" # Ignore any terminal OXT atoms which may have been added by minimization. oxt = residue_constants.atom_order['OXT'] no_oxt_mask = np.ones(shape=atom_mask.shape, dtype=bool) no_oxt_mask[..., oxt] = False np.testing.assert_almost_equal(ref_atom_mask[no_oxt_mask], atom_mask[no_oxt_mask]) ================================================ FILE: alphafold/relax/utils_test.py ================================================ # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Tests for utils.""" import os from absl.testing import absltest from alphafold.common import protein from alphafold.relax import utils import numpy as np # Internal import (7716). class UtilsTest(absltest.TestCase): def test_overwrite_b_factors(self): testdir = os.path.join( absltest.get_default_test_srcdir(), 'alphafold/relax/testdata/' 'multiple_disulfides_target.pdb') with open(testdir) as f: test_pdb = f.read() n_residues = 191 bfactors = np.stack([np.arange(0, n_residues)] * 37, axis=-1) output_pdb = utils.overwrite_b_factors(test_pdb, bfactors) # Check that the atom lines are unchanged apart from the B-factors. atom_lines_original = [l for l in test_pdb.split('\n') if l[:4] == ('ATOM')] atom_lines_new = [l for l in output_pdb.split('\n') if l[:4] == ('ATOM')] for line_original, line_new in zip(atom_lines_original, atom_lines_new): self.assertEqual(line_original[:60].strip(), line_new[:60].strip()) self.assertEqual(line_original[66:].strip(), line_new[66:].strip()) # Check B-factors are correctly set for all atoms present. as_protein = protein.from_pdb_string(output_pdb) np.testing.assert_almost_equal( np.where(as_protein.atom_mask > 0, as_protein.b_factors, 0), np.where(as_protein.atom_mask > 0, bfactors, 0)) if __name__ == '__main__': absltest.main() ================================================ FILE: docs/python_inputs.md ================================================ # AlphaFold Python Input Author: Bozitao Zhong AlphaFold: v2.1.2; ParaFold: v1.1 `--fasta_paths`: required `--is_prokaryote_list`: default all false, optional for multimer, contain a boolean for each fasta file `--model_names`: default none, only in *ParaFold* `--data_dir`: required `--output_dir`: required `--jackhmmer_binary_path`: auto find by `which jackhmmer` `--hhblits_binary_path`: auto find by `which hhblits` `--hhsearch_binary_path`: auto find by `which hhsearch` `--hmmsearch_binary_path`: auto find by `which hmmsearch` `--hmmbuild_binary_path`: auto find by `which hmmbuild` `--kalign_binary_path`: auto find by `which kalign` `--uniref90_database_path`: required `--mgnify_database_path`: required `--bfd_database_path`: required when `--db_preset==full_dbs` `--small_bfd_database_path`: required when `--db_preset==reduced_dbs` `--uniclust30_database_path`: required when `--db_preset==full_dbs` `--uniprot_database_path`: required when `--model_preset==multimer` `--pdb70_database_path`: required when `--model_preset!=multimer` `--pdb_seqres_database_path`: required when `--model_preset==multimer` `--template_mmcif_dir`: required `--max_template_date`: required `--obsolete_pdbs_path`: required `--db_preset`: default `full_dbs`, have choice `full_dbs`, `reduced_dbs` `--model_preset`: default `full_dbs`, have choice `monomer`, `monomer_casp14`, `monomer_ptm`, `multimer` `--benchmark`: default false `--random_seed`: default none `--use_precomputed_msas`: default false `--run_relax`: default true `--use_gpu_relax`: required `--recycling`: default 3, only in *ParaFold* `--run_feature`: default false, only in *ParaFold* ================================================ FILE: docs/usage.md ================================================ # Usage ## Run features Run on CPUs to get features: ```bash ./run_alphafold.sh \ -d data \ -o output \ -p monomer_ptm \ -i input/GA98.fasta \ -t 1800-01-01 \ -m model_1 \ -f ``` `-f` means only run the featurization step, result in a `feature.pkl` file, and skip the following steps. > 8 CPUs is enough, according to my test, more CPUs won't help with speed Featuring step will output the `feature.pkl` and MSA folder in your output folder: `./output/[FASTA_NAME]/` PS: Here we put input files in an `input` folder to organize files in a better way. ## Run monomer prediction After the feature step, you can run `run_alphafold.sh` using GPU: ```bash ./run_alphafold.sh \ -d data \ -o output \ -m model_1,model_2,model_3,model_4,model_5 \ -p monomer_ptm \ -i input/GA98.fasta \ -t 1800-01-01 ``` If you have successfully output `feature.pkl`, you can have a very fast featuring step ## Run multimer prediction ```bash ./run_alphafold.sh \ -d data \ -o output \ -m model_1_multimer,model_2_multimer,model_3_multimer,model_4_multimer,model_5_multimer \ -p multimer \ -i input/GA98.fasta \ -t 1800-01-01 ``` ## Draw figures [This function is under repair] You can run `run_figure.py` to visualize your result: [This will be available soon] ```bash python3 run_figure.py [SystemName] ``` This python file will create a figure folder in your output folder. Notice: `run_figure.py` need a local conda environment with matplotlib, pymol and numpy. ================================================ FILE: environment/environment_gpu.yml ================================================ name: parafold_test channels: - conda-forge - defaults dependencies: - _libgcc_mutex=0.1=conda_forge - _openmp_mutex=4.5=2_kmp_llvm - absl-py=2.0.0=pyhd8ed1ab_0 - aiohttp=3.9.1=py310h2372a71_0 - aiosignal=1.3.1=pyhd8ed1ab_0 - aom=3.7.1=h59595ed_0 - asttokens=2.4.1=pyhd8ed1ab_0 - astunparse=1.6.3=pyhd8ed1ab_0 - async-timeout=4.0.3=pyhd8ed1ab_0 - attrs=23.2.0=pyh71513ae_0 - biopython=1.83=py310h2372a71_0 - blinker=1.7.0=pyhd8ed1ab_0 - blosc=1.21.5=h0f2a231_0 - brotli=1.1.0=hd590300_1 - brotli-bin=1.1.0=hd590300_1 - brotli-python=1.1.0=py310hc6cd4ac_1 - bzip2=1.0.8=h7b6447c_0 - c-ares=1.25.0=hd590300_0 - ca-certificates=2023.11.17=hbcca054_0 - cached-property=1.5.2=hd8ed1ab_1 - cached_property=1.5.2=pyha770c72_1 - cachetools=5.3.2=pyhd8ed1ab_0 - certifi=2023.11.17=pyhd8ed1ab_0 - cffi=1.16.0=py310h2fee648_0 - charset-normalizer=3.3.2=pyhd8ed1ab_0 - chex=0.1.85=pyhd8ed1ab_0 - click=8.1.7=unix_pyh707e725_0 - comm=0.2.1=pyhd8ed1ab_0 - contourpy=1.2.0=py310hd41b1e2_0 - cryptography=41.0.7=py310hb8475ec_1 - cycler=0.12.1=pyhd8ed1ab_0 - dataclasses=0.8=pyhc8e2a94_3 - dav1d=1.2.1=hd590300_0 - debugpy=1.8.0=py310hc6cd4ac_1 - decorator=5.1.1=pyhd8ed1ab_0 - dm-haiku=0.0.11=pyhd8ed1ab_1 - dm-tree=0.1.8=py310h620c231_2 - etils=1.6.0=pyhd8ed1ab_1 - exceptiongroup=1.2.0=pyhd8ed1ab_2 - executing=2.0.1=pyhd8ed1ab_0 - flatbuffers=23.5.26=h59595ed_1 - flax=0.7.5=pyhd8ed1ab_0 - fonttools=4.47.2=py310h2372a71_0 - freetype=2.12.1=h267a509_2 - frozenlist=1.4.1=py310h2372a71_0 - gast=0.5.4=pyhd8ed1ab_0 - giflib=5.2.1=h0b41bf4_3 - google-auth=2.26.2=pyhca7485f_0 - google-auth-oauthlib=1.2.0=pyhd8ed1ab_0 - google-pasta=0.2.0=pyh8c360ce_0 - grpcio=1.59.3=py310h1b8f574_0 - h5py=3.10.0=nompi_py310h65828d5_101 - hdf5=1.14.3=nompi_h4f84152_100 - icu=73.2=h59595ed_0 - idna=3.6=pyhd8ed1ab_0 - importlib-metadata=7.0.1=pyha770c72_0 - importlib_metadata=7.0.1=hd8ed1ab_0 - importlib_resources=6.1.1=pyhd8ed1ab_0 - ipykernel=6.28.0=pyhd33586a_0 - ipython=8.20.0=pyh707e725_0 - jedi=0.19.1=pyhd8ed1ab_0 - jmp=0.0.4=pyhd8ed1ab_0 - jupyter_client=8.6.0=pyhd8ed1ab_0 - jupyter_core=5.7.1=py310hff52083_0 - keras=2.15.0=pyhd8ed1ab_0 - keyutils=1.6.1=h166bdaf_0 - kiwisolver=1.4.5=py310hd41b1e2_1 - krb5=1.21.2=h659d440_0 - lcms2=2.16=hb7c19ff_0 - ld_impl_linux-64=2.38=h1181459_1 - lerc=4.0.0=h27087fc_0 - libabseil=20230802.1=cxx17_h59595ed_0 - libaec=1.1.2=h59595ed_1 - libavif16=1.0.3=hef5bec9_1 - libblas=3.9.0=20_linux64_openblas - libbrotlicommon=1.1.0=hd590300_1 - libbrotlidec=1.1.0=hd590300_1 - libbrotlienc=1.1.0=hd590300_1 - libcblas=3.9.0=20_linux64_openblas - libcurl=8.5.0=hca28451_0 - libdeflate=1.19=hd590300_0 - libedit=3.1.20191231=he28a2e2_2 - libev=4.33=hd590300_2 - libffi=3.4.4=h6a678d5_0 - libgcc-ng=13.2.0=h807b86a_3 - libgfortran-ng=13.2.0=h69a702a_3 - libgfortran5=13.2.0=ha4646dd_3 - libgrpc=1.59.3=hd6c4280_0 - libjpeg-turbo=3.0.0=hd590300_1 - liblapack=3.9.0=20_linux64_openblas - libnghttp2=1.58.0=h47da74e_1 - libopenblas=0.3.25=pthreads_h413a1c8_0 - libpng=1.6.39=h753d276_0 - libprotobuf=4.24.4=hf27288f_0 - libre2-11=2023.06.02=h7a70373_0 - libsodium=1.0.18=h36c2ea0_1 - libsqlite=3.44.2=h2797004_0 - libssh2=1.11.0=h0841786_0 - libstdcxx-ng=13.2.0=h7e041cc_3 - libtiff=4.6.0=ha9c0a0a_2 - libuuid=1.41.5=h5eee18b_0 - libwebp-base=1.3.2=hd590300_0 - libxcb=1.15=h0b41bf4_0 - libzlib=1.2.13=hd590300_5 - llvm-openmp=17.0.6=h4dfa4b3_0 - lz4-c=1.9.4=hcb278e6_0 - markdown=3.5.2=pyhd8ed1ab_0 - markdown-it-py=3.0.0=pyhd8ed1ab_0 - markupsafe=2.1.3=py310h2372a71_1 - matplotlib-base=3.8.2=py310h62c0568_0 - matplotlib-inline=0.1.6=pyhd8ed1ab_0 - mdurl=0.1.2=pyhd8ed1ab_0 - ml_dtypes=0.2.0=py310hcc13569_2 - msgpack-python=1.0.7=py310hd41b1e2_0 - multidict=6.0.4=py310h2372a71_1 - munkres=1.1.4=pyh9f0ad1d_0 - ncurses=6.4=h6a678d5_0 - nest-asyncio=1.5.8=pyhd8ed1ab_0 - numpy=1.26.3=py310hb13e2d6_0 - oauthlib=3.2.2=pyhd8ed1ab_0 - openjpeg=2.5.0=h488ebb8_3 - openssl=3.2.0=hd590300_1 - opt_einsum=3.3.0=pyhc1e730c_2 - optax=0.1.7=pyhd8ed1ab_0 - orbax-checkpoint=0.4.4=pyhd8ed1ab_0 - packaging=23.2=pyhd8ed1ab_0 - parso=0.8.3=pyhd8ed1ab_0 - pexpect=4.8.0=pyh1a96a4e_2 - pickleshare=0.7.5=py_1003 - pillow=10.2.0=py310h01dd4db_0 - pip=23.3.1=py310h06a4308_0 - platformdirs=4.1.0=pyhd8ed1ab_0 - prompt-toolkit=3.0.42=pyha770c72_0 - protobuf=4.24.4=py310h620c231_0 - psutil=5.9.7=py310h2372a71_0 - pthread-stubs=0.4=h36c2ea0_1001 - ptyprocess=0.7.0=pyhd3deb0d_0 - pure_eval=0.2.2=pyhd8ed1ab_0 - pyasn1=0.5.1=pyhd8ed1ab_0 - pyasn1-modules=0.3.0=pyhd8ed1ab_0 - pybind11-abi=4=hd8ed1ab_3 - pycparser=2.21=pyhd8ed1ab_0 - pygments=2.17.2=pyhd8ed1ab_0 - pyjwt=2.8.0=pyhd8ed1ab_0 - pyopenssl=23.3.0=pyhd8ed1ab_0 - pyparsing=3.1.1=pyhd8ed1ab_0 - pysocks=1.7.1=pyha2e5f31_6 - python=3.10.13=h955ad1f_0 - python-dateutil=2.8.2=pyhd8ed1ab_0 - python-flatbuffers=23.5.26=pyhd8ed1ab_0 - python_abi=3.10=2_cp310 - pyu2f=0.1.5=pyhd8ed1ab_0 - pyyaml=6.0.1=py310h2372a71_1 - pyzmq=25.1.2=py310h795f18f_0 - rav1e=0.6.6=he8a937b_2 - re2=2023.06.02=h2873b5e_0 - readline=8.2=h5eee18b_0 - requests=2.31.0=pyhd8ed1ab_0 - requests-oauthlib=1.3.1=pyhd8ed1ab_0 - rich=13.7.0=pyhd8ed1ab_0 - rsa=4.9=pyhd8ed1ab_0 - scipy=1.11.4=py310hb13e2d6_0 - setuptools=68.2.2=py310h06a4308_0 - six=1.16.0=pyh6c4a22f_0 - snappy=1.1.10=h9fff704_0 - sqlite=3.41.2=h5eee18b_0 - stack_data=0.6.2=pyhd8ed1ab_0 - svt-av1=1.8.0=h59595ed_0 - tabulate=0.9.0=pyhd8ed1ab_1 - tensorboard=2.15.1=pyhd8ed1ab_0 - tensorboard-data-server=0.7.0=py310h75e40e8_1 - tensorflow=2.15.0=cpu_py310h7825f03_1 - tensorflow-base=2.15.0=cpu_py310h7e4d085_1 - tensorflow-cpu=2.15.0=cpu_py310h718b53a_1 - tensorflow-estimator=2.15.0=cpu_py310haacee6a_1 - tensorstore=0.1.51=py310ha94ca7a_0 - termcolor=2.4.0=pyhd8ed1ab_0 - tk=8.6.13=noxft_h4845f30_101 - toolz=0.12.0=pyhd8ed1ab_0 - tornado=6.3.3=py310h2372a71_1 - traitlets=5.14.1=pyhd8ed1ab_0 - typing-extensions=4.9.0=hd8ed1ab_0 - typing_extensions=4.9.0=pyha770c72_0 - tzdata=2023d=h04d1e81_0 - unicodedata2=15.1.0=py310h2372a71_0 - urllib3=2.1.0=pyhd8ed1ab_0 - wcwidth=0.2.13=pyhd8ed1ab_0 - werkzeug=3.0.1=pyhd8ed1ab_0 - wheel=0.41.2=py310h06a4308_0 - wrapt=1.14.1=py310h5764c6d_1 - xorg-libxau=1.0.11=hd590300_0 - xorg-libxdmcp=1.1.3=h7f98852_0 - xz=5.4.5=h5eee18b_0 - yaml=0.2.5=h7f98852_2 - yarl=1.9.3=py310h2372a71_0 - zeromq=4.3.5=h59595ed_0 - zipp=3.17.0=pyhd8ed1ab_0 - zlib=1.2.13=hd590300_5 - zstd=1.5.5=hfc55251_0 - pip: - contextlib2==21.6.0 - jax==0.4.23 - jaxlib==0.4.23 - ml-collections==0.1.1 - nvidia-cublas-cu11==11.11.3.6 - nvidia-cuda-cupti-cu11==11.8.87 - nvidia-cuda-nvcc-cu11==11.8.89 - nvidia-cuda-nvrtc-cu11==11.8.89 - nvidia-cuda-runtime-cu11==11.8.89 - nvidia-cudnn-cu11==8.9.6.50 - nvidia-cufft-cu11==10.9.0.58 - nvidia-cusolver-cu11==11.4.1.48 - nvidia-cusparse-cu11==11.7.5.86 - nvidia-nccl-cu11==2.19.3 ================================================ FILE: input/mono_set1/GA98.fasta ================================================ >2LHC_1|Chain A|Ga98|artificial gene (32630) TTYKLILNLKQAKEEAIKELVDAGTAEKYFKLIANAKTVEGVWTLKDEIKTFTVTE ================================================ FILE: input/mono_set1/GB98.fasta ================================================ >2LHD_1|Chain A|GB98|artificial gene (32630) TTYKLILNLKQAKEEAIKELVDAGTAEKYFKLIANAKTVEGVWTYKDEIKTFTVTE ================================================ FILE: requirements.txt ================================================ absl-py==1.0.0 biopython==1.79 chex==0.0.7 dm-haiku==0.0.9 dm-tree==0.1.6 immutabledict==2.0.0 jax==0.3.25 ml-collections==0.1.0 numpy==1.21.6 pandas==1.3.4 scipy==1.7.0 tensorflow-cpu==2.11.0 ================================================ FILE: run_alphafold.py ================================================ # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Full AlphaFold protein structure prediction script.""" import enum import json import os import pathlib import pickle import random import shutil import sys import time from typing import Any, Dict, Mapping, Union from absl import app from absl import flags from absl import logging from alphafold.common import protein from alphafold.common import residue_constants from alphafold.data import pipeline from alphafold.data import pipeline_multimer from alphafold.data import templates from alphafold.data.tools import hhsearch from alphafold.data.tools import hmmsearch from alphafold.model import config from alphafold.model import data from alphafold.model import model from alphafold.relax import relax import jax.numpy as jnp import numpy as np # Internal import (7716). logging.set_verbosity(logging.INFO) @enum.unique class ModelsToRelax(enum.Enum): ALL = 0 BEST = 1 NONE = 2 flags.DEFINE_list( 'fasta_paths', None, 'Paths to FASTA files, each containing a prediction ' 'target that will be folded one after another. If a FASTA file contains ' 'multiple sequences, then it will be folded as a multimer. Paths should be ' 'separated by commas. All FASTA paths must have a unique basename as the ' 'basename is used to name the output directories for each prediction.') flags.DEFINE_list('model_names', None, 'Names of models to use.') flags.DEFINE_string('parameter_path', None, 'Path to directory of supporting data.') flags.DEFINE_string('output_dir', None, 'Path to a directory that will ' 'store the results.') flags.DEFINE_string('jackhmmer_binary_path', shutil.which('jackhmmer'), 'Path to the JackHMMER executable.') flags.DEFINE_string('hhblits_binary_path', shutil.which('hhblits'), 'Path to the HHblits executable.') flags.DEFINE_string('hhsearch_binary_path', shutil.which('hhsearch'), 'Path to the HHsearch executable.') flags.DEFINE_string('hmmsearch_binary_path', shutil.which('hmmsearch'), 'Path to the hmmsearch executable.') flags.DEFINE_string('hmmbuild_binary_path', shutil.which('hmmbuild'), 'Path to the hmmbuild executable.') flags.DEFINE_string('kalign_binary_path', shutil.which('kalign'), 'Path to the Kalign executable.') flags.DEFINE_string('uniref90_database_path', None, 'Path to the Uniref90 ' 'database for use by JackHMMER.') flags.DEFINE_string('mgnify_database_path', None, 'Path to the MGnify ' 'database for use by JackHMMER.') flags.DEFINE_string('bfd_database_path', None, 'Path to the BFD ' 'database for use by HHblits.') flags.DEFINE_string('small_bfd_database_path', None, 'Path to the small ' 'version of BFD used with the "reduced_dbs" preset.') flags.DEFINE_string('uniref30_database_path', None, 'Path to the UniRef30 ' 'database for use by HHblits.') flags.DEFINE_string('uniprot_database_path', None, 'Path to the Uniprot ' 'database for use by JackHMMer.') flags.DEFINE_string('pdb70_database_path', None, 'Path to the PDB70 ' 'database for use by HHsearch.') flags.DEFINE_string('pdb_seqres_database_path', None, 'Path to the PDB ' 'seqres database for use by hmmsearch.') flags.DEFINE_string('template_mmcif_dir', None, 'Path to a directory with ' 'template mmCIF structures, each named .cif') flags.DEFINE_string('max_template_date', None, 'Maximum template release date ' 'to consider. Important if folding historical test sets.') flags.DEFINE_string('obsolete_pdbs_path', None, 'Path to file containing a ' 'mapping from obsolete PDB IDs to the PDB IDs of their ' 'replacements.') flags.DEFINE_enum('db_preset', 'full_dbs', ['full_dbs', 'reduced_dbs'], 'Choose preset MSA database configuration - ' 'smaller genetic database config (reduced_dbs) or ' 'full genetic database config (full_dbs)') flags.DEFINE_enum('model_preset', 'monomer', ['monomer', 'monomer_casp14', 'monomer_ptm', 'multimer'], 'Choose preset model configuration - the monomer model, ' 'the monomer model with extra ensembling, monomer model with ' 'pTM head, or multimer model') flags.DEFINE_boolean('benchmark', False, 'Run multiple JAX model evaluations ' 'to obtain a timing that excludes the compilation time, ' 'which should be more indicative of the time required for ' 'inferencing many proteins.') flags.DEFINE_integer('random_seed', None, 'The random seed for the data ' 'pipeline. By default, this is randomly generated. Note ' 'that even if this is set, Alphafold may still not be ' 'deterministic, because processes like GPU inference are ' 'nondeterministic.') flags.DEFINE_integer('num_multimer_predictions_per_model', 5, 'How many ' 'predictions (each with a different random seed) will be ' 'generated per model. E.g. if this is 2 and there are 5 ' 'models then there will be 10 predictions per input. ' 'Note: this FLAG only applies if model_preset=multimer') flags.DEFINE_boolean('use_precomputed_msas', False, 'Whether to read MSAs that ' 'have been written to disk instead of running the MSA ' 'tools. The MSA files are looked up in the output ' 'directory, so it must stay the same between multiple ' 'runs that are to reuse the MSAs. WARNING: This will not ' 'check if the sequence, database or configuration have ' 'changed.') flags.DEFINE_enum_class('models_to_relax', ModelsToRelax.BEST, ModelsToRelax, 'The models to run the final relaxation step on. ' 'If `all`, all models are relaxed, which may be time ' 'consuming. If `best`, only the most confident model ' 'is relaxed. If `none`, relaxation is not run. Turning ' 'off relaxation might result in predictions with ' 'distracting stereochemical violations but might help ' 'in case you are having issues with the relaxation ' 'stage.') flags.DEFINE_boolean('use_gpu_relax', None, 'Whether to relax on GPU. ' 'Relax on GPU can be much faster than CPU, so it is ' 'recommended to enable if possible. GPUs must be available' ' if this setting is enabled.') flags.DEFINE_integer('recycling', 3, 'Set number of recyclings') flags.DEFINE_boolean('run_feature', False, 'Calculate MSA and template to generate ' 'feature') FLAGS = flags.FLAGS MAX_TEMPLATE_HITS = 20 RELAX_MAX_ITERATIONS = 0 RELAX_ENERGY_TOLERANCE = 2.39 RELAX_STIFFNESS = 10.0 RELAX_EXCLUDE_RESIDUES = [] RELAX_MAX_OUTER_ITERATIONS = 3 def _check_flag(flag_name: str, other_flag_name: str, should_be_set: bool): if should_be_set != bool(FLAGS[flag_name].value): verb = 'be' if should_be_set else 'not be' raise ValueError(f'{flag_name} must {verb} set when running with ' f'"--{other_flag_name}={FLAGS[other_flag_name].value}".') def _jnp_to_np(output: Dict[str, Any]) -> Dict[str, Any]: """Recursively changes jax arrays to numpy arrays.""" for k, v in output.items(): if isinstance(v, dict): output[k] = _jnp_to_np(v) elif isinstance(v, jnp.ndarray): output[k] = np.array(v) return output def predict_structure( fasta_path: str, fasta_name: str, output_dir_base: str, data_pipeline: Union[pipeline.DataPipeline, pipeline_multimer.DataPipeline], model_runners: Dict[str, model.RunModel], amber_relaxer: relax.AmberRelaxation, benchmark: bool, random_seed: int, models_to_relax: ModelsToRelax, run_feature: bool): """Predicts structure using AlphaFold for the given sequence.""" logging.info('Predicting %s', fasta_name) timings = {} output_dir = os.path.join(output_dir_base, fasta_name) if not os.path.exists(output_dir): os.makedirs(output_dir) msa_output_dir = os.path.join(output_dir, 'msas') if not os.path.exists(msa_output_dir): os.makedirs(msa_output_dir) # Get features. t_0 = time.time() features_output_path = os.path.join(output_dir, 'features.pkl') # If we already have feature.pkl file, skip the MSA and template finding step if os.path.exists(features_output_path): feature_dict = pickle.load(open(features_output_path, 'rb')) else: feature_dict = data_pipeline.process( input_fasta_path=fasta_path, msa_output_dir=msa_output_dir) # Write out features as a pickled dictionary. features_output_path = os.path.join(output_dir, 'features.pkl') with open(features_output_path, 'wb') as f: pickle.dump(feature_dict, f, protocol=4) timings['features'] = time.time() - t_0 if run_feature: # if not run_feature, skip the rest of the function return 0 unrelaxed_pdbs = {} unrelaxed_proteins = {} relaxed_pdbs = {} relax_metrics = {} ranking_confidences = {} # Run the models. num_models = len(model_runners) for model_index, (model_name, model_runner) in enumerate( model_runners.items()): logging.info('Running model %s on %s', model_name, fasta_name) t_0 = time.time() model_random_seed = model_index + random_seed * num_models processed_feature_dict = model_runner.process_features( feature_dict, random_seed=model_random_seed) timings[f'process_features_{model_name}'] = time.time() - t_0 t_0 = time.time() prediction_result = model_runner.predict(processed_feature_dict, random_seed=model_random_seed) t_diff = time.time() - t_0 timings[f'predict_and_compile_{model_name}'] = t_diff logging.info( 'Total JAX model %s on %s predict time (includes compilation time, see --benchmark): %.1fs', model_name, fasta_name, t_diff) if benchmark: t_0 = time.time() model_runner.predict(processed_feature_dict, random_seed=model_random_seed) t_diff = time.time() - t_0 timings[f'predict_benchmark_{model_name}'] = t_diff logging.info( 'Total JAX model %s on %s predict time (excludes compilation time): %.1fs', model_name, fasta_name, t_diff) plddt = prediction_result['plddt'] ranking_confidences[model_name] = prediction_result['ranking_confidence'] # Remove jax dependency from results. np_prediction_result = _jnp_to_np(dict(prediction_result)) # Save the model outputs. result_output_path = os.path.join(output_dir, f'result_{model_name}.pkl') with open(result_output_path, 'wb') as f: pickle.dump(np_prediction_result, f, protocol=4) # Add the predicted LDDT in the b-factor column. # Note that higher predicted LDDT value means higher model confidence. plddt_b_factors = np.repeat( plddt[:, None], residue_constants.atom_type_num, axis=-1) unrelaxed_protein = protein.from_prediction( features=processed_feature_dict, result=prediction_result, b_factors=plddt_b_factors, remove_leading_feature_dimension=not model_runner.multimer_mode) unrelaxed_proteins[model_name] = unrelaxed_protein unrelaxed_pdbs[model_name] = protein.to_pdb(unrelaxed_protein) unrelaxed_pdb_path = os.path.join(output_dir, f'unrelaxed_{model_name}.pdb') with open(unrelaxed_pdb_path, 'w') as f: f.write(unrelaxed_pdbs[model_name]) # Rank by model confidence. ranked_order = [ model_name for model_name, confidence in sorted(ranking_confidences.items(), key=lambda x: x[1], reverse=True)] # Relax predictions. if models_to_relax == ModelsToRelax.BEST: to_relax = [ranked_order[0]] elif models_to_relax == ModelsToRelax.ALL: to_relax = ranked_order elif models_to_relax == ModelsToRelax.NONE: to_relax = [] for model_name in to_relax: t_0 = time.time() relaxed_pdb_str, _, violations = amber_relaxer.process( prot=unrelaxed_proteins[model_name]) relax_metrics[model_name] = { 'remaining_violations': violations, 'remaining_violations_count': sum(violations) } timings[f'relax_{model_name}'] = time.time() - t_0 relaxed_pdbs[model_name] = relaxed_pdb_str # Save the relaxed PDB. relaxed_output_path = os.path.join( output_dir, f'relaxed_{model_name}.pdb') with open(relaxed_output_path, 'w') as f: f.write(relaxed_pdb_str) # Write out relaxed PDBs in rank order. for idx, model_name in enumerate(ranked_order): ranked_output_path = os.path.join(output_dir, f'ranked_{idx}.pdb') with open(ranked_output_path, 'w') as f: if model_name in relaxed_pdbs: f.write(relaxed_pdbs[model_name]) else: f.write(unrelaxed_pdbs[model_name]) ranking_output_path = os.path.join(output_dir, 'ranking_debug.json') with open(ranking_output_path, 'w') as f: label = 'iptm+ptm' if 'iptm' in prediction_result else 'plddts' f.write(json.dumps( {label: ranking_confidences, 'order': ranked_order}, indent=4)) logging.info('Final timings for %s: %s', fasta_name, timings) timings_output_path = os.path.join(output_dir, 'timings.json') with open(timings_output_path, 'w') as f: f.write(json.dumps(timings, indent=4)) if models_to_relax != ModelsToRelax.NONE: relax_metrics_path = os.path.join(output_dir, 'relax_metrics.json') with open(relax_metrics_path, 'w') as f: f.write(json.dumps(relax_metrics, indent=4)) def main(argv): if len(argv) > 1: raise app.UsageError('Too many command-line arguments.') for tool_name in ( 'jackhmmer', 'hhblits', 'hhsearch', 'hmmsearch', 'hmmbuild', 'kalign'): if not FLAGS[f'{tool_name}_binary_path'].value: raise ValueError(f'Could not find path to the "{tool_name}" binary. Make ' 'sure it is installed on your system.') use_small_bfd = FLAGS.db_preset == 'reduced_dbs' _check_flag('small_bfd_database_path', 'db_preset', should_be_set=use_small_bfd) _check_flag('bfd_database_path', 'db_preset', should_be_set=not use_small_bfd) _check_flag('uniref30_database_path', 'db_preset', should_be_set=not use_small_bfd) run_multimer_system = 'multimer' in FLAGS.model_preset _check_flag('pdb70_database_path', 'model_preset', should_be_set=not run_multimer_system) _check_flag('pdb_seqres_database_path', 'model_preset', should_be_set=run_multimer_system) _check_flag('uniprot_database_path', 'model_preset', should_be_set=run_multimer_system) if FLAGS.model_preset == 'monomer_casp14': num_ensemble = 8 else: num_ensemble = 1 # Check for duplicate FASTA file names. fasta_names = [pathlib.Path(p).stem for p in FLAGS.fasta_paths] if len(fasta_names) != len(set(fasta_names)): raise ValueError('All FASTA paths must have a unique basename.') if run_multimer_system: template_searcher = hmmsearch.Hmmsearch( binary_path=FLAGS.hmmsearch_binary_path, hmmbuild_binary_path=FLAGS.hmmbuild_binary_path, database_path=FLAGS.pdb_seqres_database_path) template_featurizer = templates.HmmsearchHitFeaturizer( mmcif_dir=FLAGS.template_mmcif_dir, max_template_date=FLAGS.max_template_date, max_hits=MAX_TEMPLATE_HITS, kalign_binary_path=FLAGS.kalign_binary_path, release_dates_path=None, obsolete_pdbs_path=FLAGS.obsolete_pdbs_path) else: template_searcher = hhsearch.HHSearch( binary_path=FLAGS.hhsearch_binary_path, databases=[FLAGS.pdb70_database_path]) template_featurizer = templates.HhsearchHitFeaturizer( mmcif_dir=FLAGS.template_mmcif_dir, max_template_date=FLAGS.max_template_date, max_hits=MAX_TEMPLATE_HITS, kalign_binary_path=FLAGS.kalign_binary_path, release_dates_path=None, obsolete_pdbs_path=FLAGS.obsolete_pdbs_path) monomer_data_pipeline = pipeline.DataPipeline( jackhmmer_binary_path=FLAGS.jackhmmer_binary_path, hhblits_binary_path=FLAGS.hhblits_binary_path, uniref90_database_path=FLAGS.uniref90_database_path, mgnify_database_path=FLAGS.mgnify_database_path, bfd_database_path=FLAGS.bfd_database_path, uniref30_database_path=FLAGS.uniref30_database_path, small_bfd_database_path=FLAGS.small_bfd_database_path, template_searcher=template_searcher, template_featurizer=template_featurizer, use_small_bfd=use_small_bfd, use_precomputed_msas=FLAGS.use_precomputed_msas) if run_multimer_system: num_predictions_per_model = FLAGS.num_multimer_predictions_per_model data_pipeline = pipeline_multimer.DataPipeline( monomer_data_pipeline=monomer_data_pipeline, jackhmmer_binary_path=FLAGS.jackhmmer_binary_path, uniprot_database_path=FLAGS.uniprot_database_path, use_precomputed_msas=FLAGS.use_precomputed_msas) else: num_predictions_per_model = 1 data_pipeline = monomer_data_pipeline model_runners = {} if FLAGS.model_names: model_names = FLAGS.model_names else: model_names = config.MODEL_PRESETS[FLAGS.model_preset] for model_name in model_names: model_config = config.model_config(model_name) if run_multimer_system: model_config.model.num_ensemble_eval = num_ensemble model_config.model.num_recycle = FLAGS.recycling else: model_config.data.eval.num_ensemble = num_ensemble model_config.model.num_recycle = FLAGS.recycling model_config.data.common.num_recycle = FLAGS.recycling model_params = data.get_model_haiku_params( model_name=model_name, parameter_path=FLAGS.parameter_path) model_runner = model.RunModel(model_config, model_params) for i in range(num_predictions_per_model): model_runners[f'{model_name}_pred_{i}'] = model_runner logging.info('Have %d models: %s', len(model_runners), list(model_runners.keys())) amber_relaxer = relax.AmberRelaxation( max_iterations=RELAX_MAX_ITERATIONS, tolerance=RELAX_ENERGY_TOLERANCE, stiffness=RELAX_STIFFNESS, exclude_residues=RELAX_EXCLUDE_RESIDUES, max_outer_iterations=RELAX_MAX_OUTER_ITERATIONS, use_gpu=FLAGS.use_gpu_relax) random_seed = FLAGS.random_seed if random_seed is None: random_seed = random.randrange(sys.maxsize // len(model_runners)) logging.info('Using random seed %d for the data pipeline', random_seed) # Predict structure for each of the sequences. for i, fasta_path in enumerate(FLAGS.fasta_paths): fasta_name = fasta_names[i] predict_structure( fasta_path=fasta_path, fasta_name=fasta_name, output_dir_base=FLAGS.output_dir, data_pipeline=data_pipeline, model_runners=model_runners, amber_relaxer=amber_relaxer, benchmark=FLAGS.benchmark, random_seed=random_seed, models_to_relax=FLAGS.models_to_relax, run_feature = FLAGS.run_feature) logging.info('%s AlphaFold structure prediction COMPLETE', fasta_name) if __name__ == '__main__': flags.mark_flags_as_required([ 'fasta_paths', 'output_dir', 'parameter_path', 'uniref90_database_path', 'mgnify_database_path', 'template_mmcif_dir', 'max_template_date', 'obsolete_pdbs_path', 'use_gpu_relax', ]) app.run(main) ================================================ FILE: run_alphafold.sh ================================================ #!/bin/bash # Description: AlphaFold non-docker version # Author: Sanjay Kumar Srikakulam # Modified by Bozitao Zhong usage() { echo "" echo "Usage: $0 " echo "Required Parameters:" echo "-d Path to directory of supporting data" echo "-o Path to a directory that will store the results." echo "-p Model preset. Use monomer, monomer_ptm, monomer_casp14 or multimer models" echo "-i Path to a FASTA file containing query sequence(s)" echo "Optional Parameters:" echo "-t Maximum template release date to consider (YYYY-MM-DD format). (default: 2020-12-01)" echo "-b Run multiple JAX model evaluations to obtain a timing that excludes the compilation time (default: 'False')" echo "-g Enable NVIDIA runtime to run with GPUs (default: 'True')" echo "-u Comma separated list of devices to pass to 'CUDA_VISIBLE_DEVICES' (default: '0')" echo "-c Choose database reduced_dbs or full_dbs (default: 'full_dbs')" echo "-r 'all': all models are relaxed, 'best': only the most confident model, 'none': no models are relaxed (default: 'all')" echo "-m Names of comma separated model names to use in prediction (default: All 5 models)" echo "-R Set cycles for recycling (default: '3')" echo "-f Only run MSA and template search to generate feature file" echo "-G Disable GPU relax" echo "Future Parameters (You cannot use them now):" echo "-s Skip MSA and template step, generate single sequence feature for ultimately fast prediction" echo "-q Quick mode. Use small BFD database, no templates" echo "-e Set random seed" echo "-P Use precomputed MSAs" echo "" exit 1 } while getopts ":d:o:p:i:t:u:c:m:R:r:bgvsqfG" i; do case "${i}" in d) data_dir=$OPTARG ;; o) output_dir=$OPTARG ;; p) model_preset=$OPTARG ;; i) fasta_path=$OPTARG ;; t) max_template_date=$OPTARG ;; b) benchmark=true ;; g) use_gpu=true ;; u) gpu_devices=$OPTARG ;; c) db_preset=$OPTARG ;; r) models_to_relax=$OPTARG ;; m) model_selection=$OPTARG ;; v) visualizaion=true ;; s) skip_msa=true ;; q) quick_mode=true ;; R) recycling=$OPTARG ;; f) run_feature=true ;; G) use_gpu_relax=false ;; esac done # Parse input and set defaults if [[ "$data_dir" == "" || "$output_dir" == "" || "$model_preset" == "" || "$fasta_path" == "" ]] ; then usage fi if [[ "$max_template_date" == "" ]] ; then max_template_date="2020-12-01" fi if [[ "$benchmark" == "" ]] ; then benchmark=false fi if [[ "$use_gpu" == "" ]] ; then use_gpu=true fi if [[ "$gpu_devices" == "" ]] ; then gpu_devices="0" fi if [[ "$db_preset" == "" ]] ; then db_preset="full_dbs" fi if [[ "$models_to_relax" == "" ]] ; then models_to_relax="all" fi if [[ "$model_selection" == "" ]] ; then model_selection="" fi if [[ "$visualizaion" == "" ]] ; then visualizaion=false fi if [[ "$skip_msa" == "" ]] ; then skip_msa=false fi if [[ "$quick_mode" == "" ]] ; then quick_mode=false fi if [[ "$recycling" == "" ]] ; then recycling=3 fi if [[ "$run_feature" == "" ]] ; then run_feature=false fi if [[ "$use_gpu_relax" == "" ]] ; then use_gpu_relax=true fi # This bash script looks for the run_alphafold.py script in its current working directory, if it does not exist then exits #current_working_dir=$(pwd) alphafold_script="$(readlink -f $(dirname $0))/run_alphafold.py" if [ ! -f "$alphafold_script" ]; then echo "Alphafold python script $alphafold_script does not exist." exit 1 fi # Export ENVIRONMENT variables and set CUDA devices for use if [[ "$use_gpu" == true ]] ; then export CUDA_VISIBLE_DEVICES=0 if [[ "$gpu_devices" ]] ; then export CUDA_VISIBLE_DEVICES=$gpu_devices fi fi export TF_FORCE_UNIFIED_MEMORY='1' export XLA_PYTHON_CLIENT_MEM_FRACTION='4.0' # Path and user config (change me if required) parameter_path="$data_dir/params" bfd_database_path="$data_dir/bfd/bfd_metaclust_clu_complete_id30_c90_final_seq.sorted_opt" small_bfd_database_path="$data_dir/small_bfd/bfd-first_non_consensus_sequences.fasta" mgnify_database_path="$data_dir/mgnify/mgy_clusters_2018_12.fa" template_mmcif_dir="$data_dir/pdb_mmcif/mmcif_files" obsolete_pdbs_path="$data_dir/pdb_mmcif/obsolete.dat" pdb70_database_path="$data_dir/pdb70/pdb70" pdb_seqres_database_path="$data_dir/pdb_seqres/pdb_seqres.txt" uniref30_database_path="$data_dir/uniref30/UniRef30_2021_03" # We recommend this use the 2020 version of uniclust uniref90_database_path="$data_dir/uniref90/uniref90.fasta" uniprot_database_path="$data_dir/uniprot/uniprot.fasta" if [[ "$db_preset" == "full_dbs" ]] ; then small_bfd_database_path="" fi if [[ "$db_preset" == "reduced_dbs" ]] ; then bfd_database_path="" uniref30_database_path="" fi # Binary path (change me if required) hhblits_binary_path=$(which hhblits) hhsearch_binary_path=$(which hhsearch) jackhmmer_binary_path=$(which jackhmmer) kalign_binary_path=$(which kalign) hmmsearch_binary_path=$(which hmmsearch) hmmbuild_binary_path=$(which hmmbuild) # Temporary # Missing random_seed, use_precomputed_msas if [[ "$model_preset" == "monomer" || "$model_preset" == "monomer_ptm" ]] ; then pdb_seqres_database_path="" uniprot_database_path="" fi if [[ "$model_preset" == "multimer" ]] ; then pdb70_database_path="" fi # Run AlphaFold with required parameters python $alphafold_script \ --fasta_paths=$fasta_path \ --model_names=$model_selection \ --parameter_path=$parameter_path \ --output_dir=$output_dir \ --jackhmmer_binary_path=$jackhmmer_binary_path \ --hhblits_binary_path=$hhblits_binary_path \ --hhsearch_binary_path=$hhsearch_binary_path \ --hmmsearch_binary_path=$hmmsearch_binary_path \ --hmmbuild_binary_path=$hmmbuild_binary_path \ --kalign_binary_path=$kalign_binary_path \ --uniref90_database_path=$uniref90_database_path \ --mgnify_database_path=$mgnify_database_path \ --bfd_database_path=$bfd_database_path \ --small_bfd_database_path=$small_bfd_database_path \ --uniref30_database_path=$uniref30_database_path \ --uniprot_database_path=$uniprot_database_path \ --pdb70_database_path=$pdb70_database_path \ --pdb_seqres_database_path=$pdb_seqres_database_path \ --template_mmcif_dir=$template_mmcif_dir \ --max_template_date=$max_template_date \ --obsolete_pdbs_path=$obsolete_pdbs_path \ --db_preset=$db_preset \ --model_preset=$model_preset \ --benchmark=$benchmark \ --models_to_relax=$models_to_relax \ --use_gpu_relax=$use_gpu_relax \ --recycling=$recycling \ --run_feature=$run_feature \ --logtostderr ================================================ FILE: scripts/download_all_data.sh ================================================ #!/bin/bash # # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Downloads and unzips all required data for AlphaFold. # # Usage: bash download_all_data.sh /path/to/download/directory set -e if [[ $# -eq 0 ]]; then echo "Error: download directory must be provided as an input argument." exit 1 fi if ! command -v aria2c &> /dev/null ; then echo "Error: aria2c could not be found. Please install aria2c (sudo apt install aria2)." exit 1 fi DOWNLOAD_DIR="$1" DOWNLOAD_MODE="${2:-full_dbs}" # Default mode to full_dbs. if [[ "${DOWNLOAD_MODE}" != full_dbs && "${DOWNLOAD_MODE}" != reduced_dbs ]] then echo "DOWNLOAD_MODE ${DOWNLOAD_MODE} not recognized." exit 1 fi SCRIPT_DIR="$(dirname "$(realpath "$0")")" echo "Downloading AlphaFold parameters..." bash "${SCRIPT_DIR}/download_alphafold_params.sh" "${DOWNLOAD_DIR}" if [[ "${DOWNLOAD_MODE}" = reduced_dbs ]] ; then echo "Downloading Small BFD..." bash "${SCRIPT_DIR}/download_small_bfd.sh" "${DOWNLOAD_DIR}" else echo "Downloading BFD..." bash "${SCRIPT_DIR}/download_bfd.sh" "${DOWNLOAD_DIR}" fi echo "Downloading MGnify..." bash "${SCRIPT_DIR}/download_mgnify.sh" "${DOWNLOAD_DIR}" echo "Downloading PDB70..." bash "${SCRIPT_DIR}/download_pdb70.sh" "${DOWNLOAD_DIR}" echo "Downloading PDB mmCIF files..." bash "${SCRIPT_DIR}/download_pdb_mmcif.sh" "${DOWNLOAD_DIR}" echo "Downloading Uniref30..." bash "${SCRIPT_DIR}/download_uniref30.sh" "${DOWNLOAD_DIR}" echo "Downloading Uniref90..." bash "${SCRIPT_DIR}/download_uniref90.sh" "${DOWNLOAD_DIR}" echo "Downloading UniProt..." bash "${SCRIPT_DIR}/download_uniprot.sh" "${DOWNLOAD_DIR}" echo "Downloading PDB SeqRes..." bash "${SCRIPT_DIR}/download_pdb_seqres.sh" "${DOWNLOAD_DIR}" echo "All data downloaded." ================================================ FILE: scripts/download_alphafold_params.sh ================================================ #!/bin/bash # # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Downloads and unzips the AlphaFold parameters. # # Usage: bash download_alphafold_params.sh /path/to/download/directory set -e if [[ $# -eq 0 ]]; then echo "Error: download directory must be provided as an input argument." exit 1 fi if ! command -v aria2c &> /dev/null ; then echo "Error: aria2c could not be found. Please install aria2c (sudo apt install aria2)." exit 1 fi DOWNLOAD_DIR="$1" ROOT_DIR="${DOWNLOAD_DIR}/params" SOURCE_URL="https://storage.googleapis.com/alphafold/alphafold_params_2022-12-06.tar" BASENAME=$(basename "${SOURCE_URL}") mkdir --parents "${ROOT_DIR}" aria2c "${SOURCE_URL}" --dir="${ROOT_DIR}" tar --extract --verbose --file="${ROOT_DIR}/${BASENAME}" \ --directory="${ROOT_DIR}" --preserve-permissions rm "${ROOT_DIR}/${BASENAME}" ================================================ FILE: scripts/download_bfd.sh ================================================ #!/bin/bash # # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Downloads and unzips the BFD database for AlphaFold. # # Usage: bash download_bfd.sh /path/to/download/directory set -e if [[ $# -eq 0 ]]; then echo "Error: download directory must be provided as an input argument." exit 1 fi if ! command -v aria2c &> /dev/null ; then echo "Error: aria2c could not be found. Please install aria2c (sudo apt install aria2)." exit 1 fi DOWNLOAD_DIR="$1" ROOT_DIR="${DOWNLOAD_DIR}/bfd" # Mirror of: # https://bfd.mmseqs.com/bfd_metaclust_clu_complete_id30_c90_final_seq.sorted_opt.tar.gz. SOURCE_URL="https://storage.googleapis.com/alphafold-databases/casp14_versions/bfd_metaclust_clu_complete_id30_c90_final_seq.sorted_opt.tar.gz" BASENAME=$(basename "${SOURCE_URL}") mkdir --parents "${ROOT_DIR}" aria2c "${SOURCE_URL}" --dir="${ROOT_DIR}" tar --extract --verbose --file="${ROOT_DIR}/${BASENAME}" \ --directory="${ROOT_DIR}" rm "${ROOT_DIR}/${BASENAME}" ================================================ FILE: scripts/download_mgnify.sh ================================================ #!/bin/bash # # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Downloads and unzips the MGnify database for AlphaFold. # # Usage: bash download_mgnify.sh /path/to/download/directory set -e if [[ $# -eq 0 ]]; then echo "Error: download directory must be provided as an input argument." exit 1 fi if ! command -v aria2c &> /dev/null ; then echo "Error: aria2c could not be found. Please install aria2c (sudo apt install aria2)." exit 1 fi DOWNLOAD_DIR="$1" ROOT_DIR="${DOWNLOAD_DIR}/mgnify" # Mirror of: # ftp://ftp.ebi.ac.uk/pub/databases/metagenomics/peptide_database/2022_05/mgy_clusters.fa.gz SOURCE_URL="https://storage.googleapis.com/alphafold-databases/v2.3/mgy_clusters_2022_05.fa.gz" BASENAME=$(basename "${SOURCE_URL}") mkdir --parents "${ROOT_DIR}" aria2c "${SOURCE_URL}" --dir="${ROOT_DIR}" pushd "${ROOT_DIR}" gunzip "${ROOT_DIR}/${BASENAME}" popd ================================================ FILE: scripts/download_pdb70.sh ================================================ #!/bin/bash # # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Downloads and unzips the PDB70 database for AlphaFold. # # Usage: bash download_pdb70.sh /path/to/download/directory set -e if [[ $# -eq 0 ]]; then echo "Error: download directory must be provided as an input argument." exit 1 fi if ! command -v aria2c &> /dev/null ; then echo "Error: aria2c could not be found. Please install aria2c (sudo apt install aria2)." exit 1 fi DOWNLOAD_DIR="$1" ROOT_DIR="${DOWNLOAD_DIR}/pdb70" SOURCE_URL="http://wwwuser.gwdg.de/~compbiol/data/hhsuite/databases/hhsuite_dbs/old-releases/pdb70_from_mmcif_200401.tar.gz" BASENAME=$(basename "${SOURCE_URL}") mkdir --parents "${ROOT_DIR}" aria2c "${SOURCE_URL}" --dir="${ROOT_DIR}" tar --extract --verbose --file="${ROOT_DIR}/${BASENAME}" \ --directory="${ROOT_DIR}" rm "${ROOT_DIR}/${BASENAME}" ================================================ FILE: scripts/download_pdb_mmcif.sh ================================================ #!/bin/bash # # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Downloads, unzips and flattens the PDB database for AlphaFold. # # Usage: bash download_pdb_mmcif.sh /path/to/download/directory set -e if [[ $# -eq 0 ]]; then echo "Error: download directory must be provided as an input argument." exit 1 fi if ! command -v aria2c &> /dev/null ; then echo "Error: aria2c could not be found. Please install aria2c (sudo apt install aria2)." exit 1 fi if ! command -v rsync &> /dev/null ; then echo "Error: rsync could not be found. Please install rsync." exit 1 fi DOWNLOAD_DIR="$1" ROOT_DIR="${DOWNLOAD_DIR}/pdb_mmcif" RAW_DIR="${ROOT_DIR}/raw" MMCIF_DIR="${ROOT_DIR}/mmcif_files" echo "Running rsync to fetch all mmCIF files (note that the rsync progress estimate might be inaccurate)..." echo "If the download speed is too slow, try changing the mirror to:" echo " * rsync.ebi.ac.uk::pub/databases/pdb/data/structures/divided/mmCIF/ (Europe)" echo " * ftp.pdbj.org::ftp_data/structures/divided/mmCIF/ (Asia)" echo "or see https://www.wwpdb.org/ftp/pdb-ftp-sites for more download options." mkdir --parents "${RAW_DIR}" rsync --recursive --links --perms --times --compress --info=progress2 --delete --port=33444 \ rsync.rcsb.org::ftp_data/structures/divided/mmCIF/ \ "${RAW_DIR}" echo "Unzipping all mmCIF files..." find "${RAW_DIR}/" -type f -iname "*.gz" -exec gunzip {} + echo "Flattening all mmCIF files..." mkdir --parents "${MMCIF_DIR}" find "${RAW_DIR}" -type d -empty -delete # Delete empty directories. for subdir in "${RAW_DIR}"/*; do mv "${subdir}/"*.cif "${MMCIF_DIR}" done # Delete empty download directory structure. find "${RAW_DIR}" -type d -empty -delete aria2c "ftp://ftp.wwpdb.org/pub/pdb/data/status/obsolete.dat" --dir="${ROOT_DIR}" ================================================ FILE: scripts/download_pdb_seqres.sh ================================================ #!/bin/bash # # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Downloads and unzips the PDB SeqRes database for AlphaFold. # # Usage: bash download_pdb_seqres.sh /path/to/download/directory set -e if [[ $# -eq 0 ]]; then echo "Error: download directory must be provided as an input argument." exit 1 fi if ! command -v aria2c &> /dev/null ; then echo "Error: aria2c could not be found. Please install aria2c (sudo apt install aria2)." exit 1 fi DOWNLOAD_DIR="$1" ROOT_DIR="${DOWNLOAD_DIR}/pdb_seqres" SOURCE_URL="ftp://ftp.wwpdb.org/pub/pdb/derived_data/pdb_seqres.txt" BASENAME=$(basename "${SOURCE_URL}") mkdir --parents "${ROOT_DIR}" aria2c "${SOURCE_URL}" --dir="${ROOT_DIR}" # Keep only protein sequences. grep --after-context=1 --no-group-separator '>.* mol:protein' "${ROOT_DIR}/pdb_seqres.txt" > "${ROOT_DIR}/pdb_seqres_filtered.txt" mv "${ROOT_DIR}/pdb_seqres_filtered.txt" "${ROOT_DIR}/pdb_seqres.txt" ================================================ FILE: scripts/download_small_bfd.sh ================================================ #!/bin/bash # # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Downloads and unzips the Small BFD database for AlphaFold. # # Usage: bash download_small_bfd.sh /path/to/download/directory set -e if [[ $# -eq 0 ]]; then echo "Error: download directory must be provided as an input argument." exit 1 fi if ! command -v aria2c &> /dev/null ; then echo "Error: aria2c could not be found. Please install aria2c (sudo apt install aria2)." exit 1 fi DOWNLOAD_DIR="$1" ROOT_DIR="${DOWNLOAD_DIR}/small_bfd" SOURCE_URL="https://storage.googleapis.com/alphafold-databases/reduced_dbs/bfd-first_non_consensus_sequences.fasta.gz" BASENAME=$(basename "${SOURCE_URL}") mkdir --parents "${ROOT_DIR}" aria2c "${SOURCE_URL}" --dir="${ROOT_DIR}" pushd "${ROOT_DIR}" gunzip "${ROOT_DIR}/${BASENAME}" popd ================================================ FILE: scripts/download_uniprot.sh ================================================ #!/bin/bash # # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Downloads, unzips and merges the SwissProt and TrEMBL databases for # AlphaFold-Multimer. # # Usage: bash download_uniprot.sh /path/to/download/directory set -e if [[ $# -eq 0 ]]; then echo "Error: download directory must be provided as an input argument." exit 1 fi if ! command -v aria2c &> /dev/null ; then echo "Error: aria2c could not be found. Please install aria2c (sudo apt install aria2)." exit 1 fi DOWNLOAD_DIR="$1" ROOT_DIR="${DOWNLOAD_DIR}/uniprot" TREMBL_SOURCE_URL="ftp://ftp.ebi.ac.uk/pub/databases/uniprot/current_release/knowledgebase/complete/uniprot_trembl.fasta.gz" TREMBL_BASENAME=$(basename "${TREMBL_SOURCE_URL}") TREMBL_UNZIPPED_BASENAME="${TREMBL_BASENAME%.gz}" SPROT_SOURCE_URL="ftp://ftp.ebi.ac.uk/pub/databases/uniprot/current_release/knowledgebase/complete/uniprot_sprot.fasta.gz" SPROT_BASENAME=$(basename "${SPROT_SOURCE_URL}") SPROT_UNZIPPED_BASENAME="${SPROT_BASENAME%.gz}" mkdir --parents "${ROOT_DIR}" aria2c "${TREMBL_SOURCE_URL}" --dir="${ROOT_DIR}" aria2c "${SPROT_SOURCE_URL}" --dir="${ROOT_DIR}" pushd "${ROOT_DIR}" gunzip "${ROOT_DIR}/${TREMBL_BASENAME}" gunzip "${ROOT_DIR}/${SPROT_BASENAME}" # Concatenate TrEMBL and SwissProt, rename to uniprot and clean up. cat "${ROOT_DIR}/${SPROT_UNZIPPED_BASENAME}" >> "${ROOT_DIR}/${TREMBL_UNZIPPED_BASENAME}" mv "${ROOT_DIR}/${TREMBL_UNZIPPED_BASENAME}" "${ROOT_DIR}/uniprot.fasta" rm "${ROOT_DIR}/${SPROT_UNZIPPED_BASENAME}" popd ================================================ FILE: scripts/download_uniref30.sh ================================================ #!/bin/bash # # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Downloads and unzips the Uniclust30 database for AlphaFold. # # Usage: bash download_uniclust30.sh /path/to/download/directory set -e if [[ $# -eq 0 ]]; then echo "Error: download directory must be provided as an input argument." exit 1 fi if ! command -v aria2c &> /dev/null ; then echo "Error: aria2c could not be found. Please install aria2c (sudo apt install aria2)." exit 1 fi DOWNLOAD_DIR="$1" ROOT_DIR="${DOWNLOAD_DIR}/uniref30" # Mirror of: # https://wwwuser.gwdg.de/~compbiol/uniclust/2021_03/UniRef30_2021_03.tar.gz SOURCE_URL="https://storage.googleapis.com/alphafold-databases/v2.3/UniRef30_2021_03.tar.gz" BASENAME=$(basename "${SOURCE_URL}") mkdir --parents "${ROOT_DIR}" aria2c "${SOURCE_URL}" --dir="${ROOT_DIR}" tar --extract --verbose --file="${ROOT_DIR}/${BASENAME}" \ --directory="${ROOT_DIR}" rm "${ROOT_DIR}/${BASENAME}" ================================================ FILE: scripts/download_uniref90.sh ================================================ #!/bin/bash # # Copyright 2021 DeepMind Technologies Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Downloads and unzips the UniRef90 database for AlphaFold. # # Usage: bash download_uniref90.sh /path/to/download/directory set -e if [[ $# -eq 0 ]]; then echo "Error: download directory must be provided as an input argument." exit 1 fi if ! command -v aria2c &> /dev/null ; then echo "Error: aria2c could not be found. Please install aria2c (sudo apt install aria2)." exit 1 fi DOWNLOAD_DIR="$1" ROOT_DIR="${DOWNLOAD_DIR}/uniref90" SOURCE_URL="ftp://ftp.uniprot.org/pub/databases/uniprot/uniref/uniref90/uniref90.fasta.gz" BASENAME=$(basename "${SOURCE_URL}") mkdir --parents "${ROOT_DIR}" aria2c "${SOURCE_URL}" --dir="${ROOT_DIR}" pushd "${ROOT_DIR}" gunzip "${ROOT_DIR}/${BASENAME}" popd ================================================ FILE: tools/batch_scripts/batch_alphafold.sh ================================================ #!/bin/bash for i in `seq -f "%03g" 2 1 5` do sed "2s/^.*$/#SBATCH --job-name=A501_${i}/g" template_alphafold.slurm > sub_alphafold.slurm sbatch sub_alphafold.slurm done ================================================ FILE: tools/batch_scripts/batch_feature.sh ================================================ #!/bin/bash for i in `seq -f "%03g" 2 1 5` do sed "2s/^.*$/#SBATCH --job-name=A501_${i}/g" template.slurm > sub_feature.slurm sbatch sub_feature.slurm done ================================================ FILE: tools/batch_scripts/move_batch.sh ================================================ #!/bin/bash for i in `seq -f "%03g" 18 1 20` do mv ./task_file/A501_${i}_* ./A501_result/A501_${i}/ done ================================================ FILE: tools/plddt.py ================================================ from __future__ import print_function import pickle import sys try: if sys.argv[1][-3:] == 'pkl': pkl_file = open(sys.argv[1],'rb') result_pkl = pickle.load(pkl_file) plddt_score = result_pkl['plddt'] print(sys.argv[1][:-4],end=", ") for i in range(len(plddt_score)): print("%.4f"%plddt_score[i],end="") if i != len(plddt_score)-1: print(", " ,end="") print('\n',end="") pkl_file.close() else: print("Usage: python3 plddt.py [AlphaFold predict output plddt file]\n") except: print("Usage: python3 plddt.py [AlphaFold predict output plddt file]\n")