// $Id: ContextBasePairModel.h 1365 2024-06-28 20:00:02Z ge $
/// \file ContexBasePairModel.h
/// \brief contains the Gibbs Free Energy function class
///
/// $Revision: 1365 $
/// \author Gerald Weber <gweberbh@gmail.com>
#ifndef GBC_CONTEXTBASEPAIRMODEL_H
#define GBC_CONTEXTBASEPAIRMODEL_H "$Id: ContextBasePairModel.h 1365 2024-06-28 20:00:02Z ge $"
#include "NeighbourSequence.h"
#include "Duplex.h"
#include <valarray>
#include <fstream>
#include "ParameterMap.h"
#include <boost/regex.hpp>
#include "IndividualNearestNeighbours.h"

using namespace gbc;
namespace gbc
  {
  /// \brief Calculate Gibbs Free Energies and Melting Temperatures
  ///
  /// This implements DNA melting temperature calculations based on the independent nearest neighbour model (INN)
  /// See santalucia96, santalucia98, gray97, gray97b
  class ContextBasePairModel: public IndividualNearestNeighbours
    {
    public:
      typedef IndividualNearestNeighbours                  base_type;
      typedef typename sequenceinfo_type::duplex_ref_type  duplex_ref_type;
      typedef std::set<std::string>                        context_bp_map_type;
      // typedef sequenceinfo_type::duplex_ref_type           base_model_type;

    ContextBasePairModel(void) {}
    
    virtual void  set_TM_parameters(void) 
      {
      //This block is crucial for the parameter minimization, each time this function is called we reset the parameters to the ones used in the parameter file
      //Note that this loads all parameters in the files even when not strictly required
      populate_enthalpy_tables<context_bp_map_type>("^..(\\^[^_]+$|$)");

      set_symmetry_parameters();
      
      set_salt_parameters();
      
      }
      
    inline std::set<std::string> get_nn(void) {return Sequence_info->Basepair_set.string_set();}
      
    /// \returns Enthalpy in Kcal/mol
    /// \returns Entropy in cal/(mol.K)
    virtual inline void calculate_total_enthalpy_and_entropy(void)
      {
      Sequence_enthalpy = value_type();
      Sequence_entropy  = value_type();
      Sequence_terminal_enthalpy = value_type();
      Sequence_terminal_entropy  = value_type();
      
      if (empty_enthalpy_tables()) alloc_enthalpy_tables(Sequence_info->Basepair_set);
      
      if (Debug) CERR_DEBUG(DINN_SIED) "Sequence " << Sequence_info->Exact_duplex << std::endl;
      
      attribute_sequence_enthalpy_tables(Sequence_info->Basepair_set);

      apply_symmetry_factors();
      
      Sequence_info->enthalpy.predicted=Sequence_enthalpy;
      Sequence_info->entropy.predicted=Sequence_entropy;
      
      if (Debug)  CERR_DEBUG(DINN_TDHDSDG) << "Total DH = " << Sequence_enthalpy << " Total DS = " << Sequence_entropy 
        << " Total DG = " << gibbs_free_energy(Sequence_enthalpy,Sequence_entropy) << std::endl;
      }
      
    };

  };

#endif
