
.. _program_listing_file_cif++_compound.hpp:

Program Listing for File compound.hpp
=====================================

|exhale_lsh| :ref:`Return to documentation for file <file_cif++_compound.hpp>` (``cif++/compound.hpp``)

.. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS

.. code-block:: cpp

   /*-
    * 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++/datablock.hpp"
   #include "cif++/exports.hpp"
   #include "cif++/point.hpp"
   
   #include <cstdint>
   #include <filesystem>
   #include <map>
   #include <memory>
   #include <string>
   #include <string_view>
   #include <vector>
   
   
   
   namespace cif
   {
   
   // --------------------------------------------------------------------
   
   class compound_factory_impl;
   class datablock;
   class file;
   enum atom_type : uint8_t;
   
   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;                                                    
   
       [[nodiscard]] 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
   
       [[nodiscard]] std::string id() const { return m_id; }                   
       [[nodiscard]] std::string name() const { return m_name; }               
       [[nodiscard]] std::string type() const { return m_type; }               
       [[nodiscard]] std::string formula() const { return m_formula; }         
       [[nodiscard]] float formula_weight() const { return m_formula_weight; } 
       [[nodiscard]] int formal_charge() const { return m_formal_charge; }     
   
       [[nodiscard]] const std::vector<compound_atom> &atoms() const { return m_atoms; } 
       [[nodiscard]] const std::vector<compound_bond> &bonds() const { return m_bonds; } 
   
       [[nodiscard]] compound_atom get_atom_by_atom_id(const std::string &atom_id) const; 
   
       [[nodiscard]] bool atoms_bonded(const std::string &atomId_1, const std::string &atomId_2) const; 
       [[nodiscard]] float bond_length(const std::string &atomId_1, const std::string &atomId_2) const; 
   
       [[nodiscard]] bool is_water() const 
       {
           return m_id == "HOH" or m_id == "H2O" or m_id == "WAT";
       }
   
       [[nodiscard]] bool is_peptide() const;
   
       [[nodiscard]] bool is_base() const;
   
       [[nodiscard]] char one_letter_code() const { return m_one_letter_code; };
   
       [[nodiscard]] std::string parent_id() const { return m_parent_id; };
   
     private:
       friend class compound_factory_impl;
       friend class local_compound_factory_impl;
   
       compound(datablock &db);
   
       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:
       compound_factory(const compound_factory &) = delete;
       compound_factory &operator=(const compound_factory &) = delete;
   
   
       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)")]]
       [[nodiscard]] bool
       is_known_peptide(const std::string &res_name) const;
   
       [[deprecated("use is_base or is_std_base instead)")]]
       [[nodiscard]] bool
       is_known_base(const std::string &res_name) const;
   
       [[nodiscard]] bool is_peptide(std::string_view res_name) const;
   
       [[nodiscard]] bool is_base(std::string_view res_name) const;
   
       [[nodiscard]] bool is_std_peptide(std::string_view res_name) const;
   
       [[nodiscard]] bool is_std_base(std::string_view res_name) const;
   
       [[nodiscard]] bool is_monomer(std::string_view res_name) const;
   
       [[nodiscard]] bool is_std_monomer(std::string_view res_name) const
       {
           return is_std_base(res_name) or is_std_peptide(res_name);
       }
   
       [[nodiscard]] bool is_water(std::string_view res_name) const
       {
           return res_name == "HOH" or res_name == "H2O" or res_name == "WAT";
       }
   
       [[nodiscard]] bool exists(std::string_view res_name) const;
   
       const compound *create(std::string_view id);
   
       ~compound_factory() = default;
   
       CIFPP_EXPORT static const std::map<std::string, char> kAAMap, 
           kBaseMap;                                                 
   
       void report_missing_compound(std::string_view compound_id);
   
       [[nodiscard]] bool get_report_missing() const { return m_report_missing; }
   
       void set_report_missing(bool report)
       {
           m_report_missing = report;
       }
   
     private:
       compound_factory();
   
       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;
       bool m_report_missing = true;
   };
   
   // --------------------------------------------------------------------
   
   
   class compound_source
   {
     public:
       compound_source(const file &file)
       {
           compound_factory::instance().push_dictionary(file);
       }
   
       ~compound_source()
       {
           compound_factory::instance().pop_dictionary();
       }
   };
   
   } // namespace cif
