Program Listing for File compound.hpp

Return to documentation for file (cif++/compound.hpp)

/*-
 * SPDX-License-Identifier: BSD-2-Clause
 *
 * Copyright (c) 2020-2022 NKI/AVL, Netherlands Cancer Institute
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#pragma once

#include "cif++/atom_type.hpp"
#include "cif++/datablock.hpp"
#include "cif++/exports.hpp"
#include "cif++/point.hpp"
#include "cif++/utilities.hpp"

#include <map>
#include <set>
#include <tuple>
#include <vector>



namespace cif
{

// --------------------------------------------------------------------

class compound;
struct compound_atom;
class compound_factory_impl;

enum class bond_type
{
    sing,
    doub,
    trip,
    quad,
    arom,
    poly,
    delo,
    pi,
};

std::string bond_type_to_string(bond_type bondType);

bond_type parse_bond_type_from_string(const std::string &bondType);

enum class stereo_config_type : uint8_t
{
    N = 'N',
    R = 'R',
    S = 'S'
};

std::string to_string(stereo_config_type stereo_config);

stereo_config_type parse_stereo_config_from_string(const std::string &stereo_config);


struct compound_atom
{
    std::string id;
    atom_type type_symbol;
    int charge = 0;
    bool aromatic = false;
    bool leaving_atom = false;
    stereo_config_type stereo_config = stereo_config_type::N;
    float x,
        y,
        z;

    point get_location() const
    {
        return { x, y, z };
    }
};


struct compound_bond
{
    std::string atom_id[2];
    bond_type type;
    bool aromatic = false,
        stereo_config = false;
};


class compound
{
  public:
    // accessors

    std::string id() const { return m_id; }
    std::string name() const { return m_name; }
    std::string type() const { return m_type; }
    std::string formula() const { return m_formula; }
    float formula_weight() const { return m_formula_weight; }
    int formal_charge() const { return m_formal_charge; }

    const std::vector<compound_atom> &atoms() const { return m_atoms; }
    const std::vector<compound_bond> &bonds() const { return m_bonds; }

    compound_atom get_atom_by_atom_id(const std::string &atom_id) const;

    bool atoms_bonded(const std::string &atomId_1, const std::string &atomId_2) const;
    float bond_length(const std::string &atomId_1, const std::string &atomId_2) const;

    bool is_water() const
    {
        return m_id == "HOH" or m_id == "H2O" or m_id == "WAT";
    }

    bool is_peptide() const;

    bool is_base() const;

    char one_letter_code() const { return m_one_letter_code; };
    std::string parent_id() const { return m_parent_id; };

  private:
    friend class compound_factory_impl;
    friend class local_compound_factory_impl;

    compound(cif::datablock &db);
    compound(cif::datablock &db, int);

    std::string m_id;
    std::string m_name;
    std::string m_type;
    std::string m_formula;
    char m_one_letter_code = 0;
    std::string m_parent_id;
    float m_formula_weight = 0;
    int m_formal_charge = 0;
    std::vector<compound_atom> m_atoms;
    std::vector<compound_bond> m_bonds;
};

// --------------------------------------------------------------------
// Factory class for compound and Link objects


class compound_factory
{
  public:

    static void init(bool useThreadLocalInstanceOnly);

    static compound_factory &instance();

    static void clear();

    void set_default_dictionary(const std::filesystem::path &inDictFile);

    void push_dictionary(const std::filesystem::path &inDictFile);

    void push_dictionary(const file &file);

    void pop_dictionary();

    [[deprecated("use is_peptide or is_std_peptide instead)")]]
    bool is_known_peptide(const std::string &res_name) const;

    [[deprecated("use is_base or is_std_base instead)")]]
    bool is_known_base(const std::string &res_name) const;

    bool is_peptide(std::string_view res_name) const;

    bool is_base(std::string_view res_name) const;

    bool is_std_peptide(std::string_view res_name) const;

    bool is_std_base(std::string_view res_name) const;

    bool is_monomer(std::string_view res_name) const;

    bool is_std_monomer(std::string_view res_name) const
    {
        return is_std_base(res_name) or is_std_peptide(res_name);
    }

    bool is_water(std::string_view res_name) const
    {
        return res_name == "HOH" or res_name == "H2O" or res_name == "WAT";
    }

    const compound *create(std::string_view id);

    ~compound_factory();

    CIFPP_EXPORT static const std::map<std::string, char> kAAMap,
        kBaseMap;

    void report_missing_compound(std::string_view compound_id);

  private:
    compound_factory();

    compound_factory(const compound_factory &) = delete;
    compound_factory &operator=(const compound_factory &) = delete;

    static std::unique_ptr<compound_factory> s_instance;
    static thread_local std::unique_ptr<compound_factory> tl_instance;
    static bool s_use_thread_local_instance;

    std::shared_ptr<compound_factory_impl> m_impl;
};

// --------------------------------------------------------------------

class compound_source
{
  public:
    compound_source(const cif::file &file)
    {
        cif::compound_factory::instance().push_dictionary(file);
    }

    ~compound_source()
    {
        cif::compound_factory::instance().pop_dictionary();
    }
};

} // namespace cif