wuxing0105's picture
Add files using upload-large-folder tool
62d3300 verified
Raw
History Blame Contribute Delete
5.49 kB
/*
* 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_