File size: 5,821 Bytes
3e62986
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/*
 * 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 <cstddef>
#include <cstdint>
#include <string>
#include <utility>
#include <vector>

#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<std::size_t> chain_ends,
              std::vector<std::size_t> 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<MmcifLayout> 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<std::size_t, std::size_t> 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<std::size_t, std::size_t> 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<std::size_t>& 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<std::size_t> chain_starts() const;

  // One past last atom index of each residue.
  const std::vector<std::size_t>& residues() const { return residue_ends_; }

  // Indices of the first atom of each residue.
  std::vector<std::size_t> residue_starts() const {
    std::vector<std::size_t> 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<const std::uint64_t> keep_indices);

 private:
  std::vector<std::size_t> chain_ends_;
  std::vector<std::size_t> residue_ends_;
  std::size_t model_offset_;
  std::size_t num_models_;
};

}  // namespace alphafold3

#endif  // ALPHAFOLD3_SRC_ALPHAFOLD3_STRUCTURE_PYTHON_MMCIF_LAYOUT_H_