/* * Copyright 2024 DeepMind Technologies Limited * * AlphaFold 3 source code is licensed under CC BY-NC-SA 4.0. To view a copy of * this license, visit https://creativecommons.org/licenses/by-nc-sa/4.0/ * * To request access to the AlphaFold 3 model parameters, follow the process set * out at https://github.com/google-deepmind/alphafold3. You may only use these * if received directly from Google. Use is subject to terms of use available at * https://github.com/google-deepmind/alphafold3/blob/main/WEIGHTS_TERMS_OF_USE.md */ #ifndef ALPHAFOLD3_SRC_ALPHAFOLD3_STRUCTURE_PYTHON_MMCIF_LAYOUT_H_ #define ALPHAFOLD3_SRC_ALPHAFOLD3_STRUCTURE_PYTHON_MMCIF_LAYOUT_H_ #include #include #include #include #include #include "absl/status/statusor.h" #include "absl/strings/string_view.h" #include "absl/types/span.h" #include "alphafold3/parsers/cpp/cif_dict_lib.h" namespace alphafold3 { // Holds the layout of a parsed mmCIF file. class MmcifLayout { public: MmcifLayout(std::vector chain_ends, std::vector residues, std::size_t model_offset, std::size_t num_models) : chain_ends_(std::move(chain_ends)), residue_ends_(std::move(residues)), model_offset_(model_offset), num_models_(num_models) {} // Reads a layout from a valid parsed mmCIF. If a valid model_id is provided // the offsets will select that model from the mmCIF. // If no model_id is specified, we calculate the layout of the first model // only. Therefore it is a requirement that each model has identical atom // layouts. An error is returned if the atom counts do not between models. static absl::StatusOr Create(const CifDict& mmcif, absl::string_view model_id = ""); std::string ToDebugString() const; // Returns the start index and one past the last residue index of a given // chain. A chain_index of n refers to the n-th chain in the mmCIF. The // returned residue indices are 0-based enumerations of residues in the // _atom_site records, and therefore do not include missing residues. std::pair residue_range( std::size_t chain_index) const { if (chain_index > 0) { return {chain_ends_[chain_index - 1], chain_ends_[chain_index]}; } else { return {0, chain_ends_[0]}; } } // Returns the start index and one past the last index of a given residue. // A residue_index of n refers to the n-th residue in the mmCIF, not // including residues that are unresolved (i.e. only using _atom_site). std::pair atom_range( std::size_t residue_index) const { if (residue_index > 0) { return {residue_ends_[residue_index - 1], residue_ends_[residue_index]}; } else { return {model_offset_, residue_ends_[residue_index]}; } } // If model_id was provided during construction then this is 1, otherwise // it is the number of models present in the mmCIF. std::size_t num_models() const { return num_models_; } // The number of atoms in the chosen model. std::size_t num_atoms() const { return residue_ends_.empty() ? 0 : residue_ends_.back() - model_offset_; } // The number of chains in the chosen model. std::size_t num_chains() const { return chain_ends_.size(); } // The number of residues in the chosen model, not counting unresolved // residues. std::size_t num_residues() const { return residue_ends_.size(); } // Returns the first atom index that is part of the specified chain. // The chain is specified using chain_index, which is a 0-based // enumeration of the chains in the _atom_site table. std::size_t atom_site_from_chain_index(std::size_t chain_index) const { if (chain_index == 0) { return model_offset_; } return atom_site_from_residue_index(chain_ends_[chain_index - 1]); } // Returns the first atom index that is part of the specified residue. // The residue is specified using residue_index, which is a 0-based // enumeration of the residues in the _atom_site table. std::size_t atom_site_from_residue_index(std::size_t residues_index) const { if (residues_index == 0) { return model_offset_; } return residue_ends_[residues_index - 1]; } // One past last residue index of each chain. The residue index does not // include unresolved residues and is a simple 0-based enumeration of the // residues in _atom_site table. const std::vector& chains() const { return chain_ends_; } // Indices of the first atom of each chain. Note that this returns atom // indices (like residue_starts()), not residue indices (like chains()). std::vector chain_starts() const; // One past last atom index of each residue. const std::vector& residues() const { return residue_ends_; } // Indices of the first atom of each residue. std::vector residue_starts() const { std::vector residue_starts; if (!residue_ends_.empty()) { residue_starts.reserve(residue_ends_.size()); residue_starts.push_back(model_offset_); residue_starts.insert(residue_starts.end(), residue_ends_.begin(), residue_ends_.end() - 1); } return residue_starts; } // The first atom index that is part of the specified model. std::size_t model_offset() const { return model_offset_; } void Filter(absl::Span keep_indices); private: std::vector chain_ends_; std::vector residue_ends_; std::size_t model_offset_; std::size_t num_models_; }; } // namespace alphafold3 #endif // ALPHAFOLD3_SRC_ALPHAFOLD3_STRUCTURE_PYTHON_MMCIF_LAYOUT_H_