00001 #include <biu/assertbiu.hh>
00002 #include "ell/rna/RNAFreeEnergy_TB.hh"
00003
00004 extern "C" {
00005 #include <ViennaRNA/fold_vars.h>
00006 #include <ViennaRNA/pair_mat.h>
00007
00008
00009 }
00010 extern "C" float energy_of_struct(const char *string, const char *structure);
00011 extern "C" void update_fold_params ();
00012 extern "C" int encode_char(char c);
00013 extern "C" short* make_pair_table(const char *structure);
00014 extern "C" int loop_energy(short * ptable, short *s, short *s1, int i);
00015
00016 void dummyCall() {
00017 make_pair_matrix();
00018 }
00019
00020 #include <cstring>
00021 #include <limits.h>
00022
00023 namespace ell
00024 {
00025
00026 const biu::Alphabet RNAFreeEnergy_TB::COMMON_ALPHABET("ACGU", 1);
00027 const biu::AllowedBasePairs RNAFreeEnergy_TB::COMMON_BPAIRS(
00028 &COMMON_ALPHABET, "AU,CG,GU");
00029 const double RNAFreeEnergy_TB::ENERGY_INF((double)UINT_MAX);
00030
00031 bool RNAFreeEnergy_TB::calculateEnergyChanges = true;
00032
00033
00034
00035 bool ViennaFoldParamsSet = false;
00036
00037
00039
00041
00042 RNAFreeEnergy_TB::RNAFreeEnergy_TB(const std::string& rnaSeqStr
00043 , const std::string& rnaStructBracketDotStr
00044 , const double energy_ )
00045 : biu::RNAStructure_TB(rnaSeqStr, rnaStructBracketDotStr, &COMMON_BPAIRS)
00046 , energy(ENERGY_INF)
00047 , seqVienna(NULL)
00048 , pairTable(NULL)
00049 {
00050
00051 setViennaFoldParams();
00052
00053 moleculeChanged();
00054
00055 if (energy_ != ENERGY_INF) {
00056 setEnergy(energy_);
00057 }
00058 }
00059
00060 RNAFreeEnergy_TB::RNAFreeEnergy_TB(biu::Sequence* rnaSeq
00061 , const biu::Structure* const rnaStructBracketDot
00062 , const bool seqIsShared
00063 , const double energy_ )
00064 : biu::RNAStructure_TB(rnaSeq, rnaStructBracketDot, &COMMON_BPAIRS, seqIsShared)
00065 , energy(ENERGY_INF)
00066 , seqVienna(NULL)
00067 , pairTable(NULL)
00068 {
00069
00070 setViennaFoldParams();
00071
00072 moleculeChanged();
00073
00074 if (energy_ != ENERGY_INF) {
00075 setEnergy(energy_);
00076 }
00077 }
00078
00079 RNAFreeEnergy_TB::RNAFreeEnergy_TB(const RNAFreeEnergy_TB& rnaFreeEnerg)
00080 : biu::RNAStructure_TB(rnaFreeEnerg)
00081 , energy(rnaFreeEnerg.energy)
00082 , seqVienna(NULL)
00083 , pairTable(NULL)
00084 {
00085 }
00086
00087 RNAFreeEnergy_TB::~RNAFreeEnergy_TB()
00088 {
00089 if (seqVienna != NULL) delete seqVienna;
00090 if (pairTable != NULL) delete pairTable;
00091 }
00092
00093 void
00094 RNAFreeEnergy_TB::applySingleMoveInPlace(const SingleMove& move) {
00095
00096
00097 if (calculateEnergyChanges && energy != ENERGY_INF) {
00098
00099 size_t around = move.first;
00100 while (around > 0) {
00101 around--;
00102 if ( validTreeStruc->at(around).pair != INVALID_INDEX ) {
00103 if ( validTreeStruc->at(around).pair > move.first ) {
00104 break;
00105 } else {
00106
00107 around = validTreeStruc->at(around).pair;
00108 }
00109 }
00110 }
00111 const bool nothingAround = move.first == 0 || (around == 0 && validTreeStruc->at(around).pair == INVALID_INDEX);
00112
00113 if (seqVienna == NULL || pairTable == NULL) {
00114 updateSeqVienna();
00115 }
00116
00117
00118 double aroundE = 0.0;
00119 double moveE = 0.0;
00120 double stackE = 0.0;
00121
00122
00123
00124
00125
00126
00127
00128
00129 if (validTreeStruc->at(move.first).pair == move.second) {
00130 if (around == 0)
00131
00132 stackE = loop_energy(pairTable, seqVienna, seqVienna, (nothingAround?0:around+1));
00133
00134
00135
00136
00137 moveE = loop_energy(pairTable, seqVienna, seqVienna, (move.first+1));
00138 deleteBond( move.first, move.second );
00139
00140 pairTable[move.first+1] = 0;
00141 pairTable[move.second+1] = 0;
00142 aroundE = loop_energy(pairTable, seqVienna, seqVienna, (nothingAround?0:around+1));
00143
00144 energy += double(aroundE - stackE - moveE) / 100.0;
00145 }
00146
00147 else {
00148
00149 assertbiu(isValidInsertMove( move.first, move.second ),
00150 "can't close bond with single move, because it is not valid");
00151 aroundE = loop_energy(pairTable, seqVienna, seqVienna, (nothingAround?0:around+1));
00152 insertBond( move.first, move.second );
00153
00154 pairTable[move.first+1] = (short)move.second+1;
00155 pairTable[move.second+1] = (short)move.first+1;
00156 moveE = loop_energy(pairTable, seqVienna, seqVienna, (move.first+1));
00157 stackE = loop_energy(pairTable, seqVienna, seqVienna, (nothingAround?0:around+1));
00158
00159 energy += double(moveE + stackE - aroundE) / 100.0;
00160 }
00161
00162
00163
00164
00165
00166
00167 assertbiu( energy_of_struct(
00168 COMMON_ALPHABET.getString(*rnaSeq).c_str()
00169 , bracketStructStr.c_str() ) - energy < 0.0001
00170 , "updated energy differs from direct calculation with Vienna RNA package");
00171
00172 }
00173
00174 else {
00175
00176 if (validTreeStruc->at(move.first).pair == move.second) {
00177 deleteBond( move.first, move.second );
00178
00179 if (pairTable != NULL) {
00180 pairTable[move.first+1] = 0;
00181 pairTable[move.second+1] = 0;
00182 }
00183 }
00184
00185 else {
00186 assertbiu(isValidInsertMove( move.first, move.second ),
00187 "can't close bond with single move, because it is not valid");
00188 insertBond( move.first, move.second );
00189
00190 if (pairTable != NULL) {
00191 pairTable[move.first+1] = (short)move.second+1;
00192 pairTable[move.second+1] = (short)move.first+1;
00193 }
00194 }
00195
00196
00197 moleculeChanged();
00198 }
00199 }
00200
00201 RNAFreeEnergy_TB&
00202 RNAFreeEnergy_TB::operator= (const RNAFreeEnergy_TB& rnaStruct2) {
00203
00204 if (this != &rnaStruct2) {
00205
00206 biu::RNAStructure_TB::operator=(rnaStruct2);
00207
00208
00209 energy = rnaStruct2.energy;
00210 if (seqVienna != NULL) delete seqVienna;
00211 seqVienna = NULL;
00212 if (pairTable != NULL) delete pairTable;
00213 pairTable = NULL;
00214 }
00215 return *this;
00216 }
00217
00218 void
00219 RNAFreeEnergy_TB
00220 ::updateSeqVienna()
00221 {
00222 const size_t length = bracketStructStr.size();
00223 if (seqVienna == NULL) {
00224 seqVienna = new short[length+2];
00225
00226
00227 seqVienna[0] = (short) length;
00228
00229 const std::string seq(COMMON_ALPHABET.getString(*rnaSeq));
00230 for (size_t i=1; i<=length; i++) {
00231 seqVienna[i] = (short) encode_char(seq.at(i-1));
00232
00233 }
00234
00235
00236 seqVienna[length+1] = seqVienna[1];
00237
00238
00239
00240 }
00241 if (pairTable == NULL) {
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252 pairTable = make_pair_table(bracketStructStr.c_str());
00253 }
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265 }
00266
00267
00270 void
00271 RNAFreeEnergy_TB
00272 ::setViennaFoldParams(void) {
00273
00274 dangles = 2;
00275
00276 update_fold_params();
00277 }
00278
00279
00280 }