File size: 5,493 Bytes
62d3300 | 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 148 149 150 | /*
* 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
*/
// A C++ implementation of a CIF parser. For the format specification see
// https://www.iucr.org/resources/cif/spec/version1.1/cifsyntax
#ifndef ALPHAFOLD3_SRC_ALPHAFOLD3_PARSERS_PYTHON_CIF_DICT_LIB_H_
#define ALPHAFOLD3_SRC_ALPHAFOLD3_PARSERS_PYTHON_CIF_DICT_LIB_H_
#include <cstddef>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "absl/container/flat_hash_map.h"
#include "absl/container/node_hash_map.h"
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "absl/types/span.h"
namespace alphafold3 {
class CifDict {
public:
// Use absl::node_hash_map since it guarantees pointer stability.
using Dict = absl::node_hash_map<std::string, std::vector<std::string>>;
CifDict() = default;
explicit CifDict(Dict dict)
: dict_(std::make_shared<const Dict>(std::move(dict))) {}
// Converts a CIF string into a dictionary mapping each CIF field to a list of
// values that field contains.
static absl::StatusOr<CifDict> FromString(absl::string_view cif_string);
// Converts the CIF into into a string that is a valid CIF file.
absl::StatusOr<std::string> ToString() const;
// Extracts loop associated with a prefix from mmCIF data as a list.
// Reference for loop_ in mmCIF:
// http://mmcif.wwpdb.org/docs/tutorials/mechanics/pdbx-mmcif-syntax.html
// Args:
// prefix: Prefix shared by each of the data items in the loop.
// e.g. '_entity_poly_seq.', where the data items are _entity_poly_seq.num,
// _entity_poly_seq.mon_id. Should include the trailing period.
//
// Returns a list of dicts; each dict represents 1 entry from an mmCIF loop.
// Lifetime of string_views tied to this.
absl::StatusOr<
std::vector<absl::flat_hash_map<absl::string_view, absl::string_view>>>
ExtractLoopAsList(absl::string_view prefix) const;
// Extracts loop associated with a prefix from mmCIF data as a dictionary.
// Args:
// prefix: Prefix shared by each of the data items in the loop.
// e.g. '_entity_poly_seq.', where the data items are _entity_poly_seq.num,
// _entity_poly_seq.mon_id. Should include the trailing period.
// index: Which item of loop data should serve as the key.
//
// Returns a dict of dicts; each dict represents 1 entry from an mmCIF loop,
// indexed by the index column.
// Lifetime of string_views tied to this.
absl::StatusOr<absl::flat_hash_map<
absl::string_view,
absl::flat_hash_map<absl::string_view, absl::string_view>>>
ExtractLoopAsDict(absl::string_view prefix, absl::string_view index) const;
// Returns value at key if present or an empty list.
absl::Span<const std::string> operator[](absl::string_view key) const {
auto it = dict_->find(key);
if (it != dict_->end()) {
return it->second;
}
return {};
}
// Returns boolean of whether dict contains key.
bool Contains(absl::string_view key) const { return dict_->contains(key); }
// Returns number of values for the given key if present, 0 otherwise.
size_t ValueLength(absl::string_view key) const {
return (*this)[key].size();
}
// Returns the size of the underlying dictionary.
std::size_t Length() { return dict_->size(); }
// Creates a copy of this CifDict object that will contain the original values
// but only if not updated by the given dictionary.
// E.g. if the CifDict = {a: [a1, a2], b: [b1]} and other = {a: [x], c: [z]},
// you will get {a: [x], b: [b1], c: [z]}.
CifDict CopyAndUpdate(Dict other) const {
other.insert(dict_->begin(), dict_->end());
return CifDict(std::move(other));
}
// Returns the value of the special CIF data_ field.
absl::string_view GetDataName() const {
// The data_ element has to be present by construction.
if (auto it = dict_->find("data_");
it != dict_->end() && !it->second.empty()) {
return it->second.front();
} else {
return "";
}
}
const std::shared_ptr<const Dict>& dict() const { return dict_; }
private:
std::shared_ptr<const Dict> dict_;
};
// Tokenizes a CIF string into a list of string tokens. This is more involved
// than just a simple split on whitespace as CIF allows comments and quoting.
absl::StatusOr<std::vector<std::string>> Tokenize(absl::string_view cif_string);
// Tokenizes a single line of a CIF string.
absl::StatusOr<std::vector<absl::string_view>> SplitLine(
absl::string_view line);
// Parses a CIF string with multiple data records and returns a mapping from
// record names to CifDict objects. For instance, the following CIF string:
//
// data_001
// _foo bar
//
// data_002
// _foo baz
//
// will be parsed as:
// {'001': CifDict({'_foo': ['bar']}),
// '002': CifDict({'_foo': ['baz']})}
absl::StatusOr<absl::flat_hash_map<std::string, CifDict>> ParseMultiDataCifDict(
absl::string_view cif_string);
} // namespace alphafold3
#endif // ALPHAFOLD3_SRC_ALPHAFOLD3_PARSERS_PYTHON_CIF_DICT_LIB_H_
|