// Action_NativeContacts::WriteContacts() void Action_NativeContacts::WriteContacts(contactListType& ContactsIn, bool isNative) { if (ContactsIn.empty()) return; // Map of residue pairs to total contact values. typedef std::map<Cpair, resContact> resContactMap; resContactMap ResContacts; std::pair<resContactMap::iterator, bool> ret; // Normalize native contacts. Place them into an array where they will // be sorted. Sum up total contact over residue pairs. std::vector<contactType> sortedList; for (contactListType::iterator it = ContactsIn.begin(); it != ContactsIn.end(); ++it) { it->second.Finalize(); sortedList.push_back( it->second ); ret = ResContacts.insert( Rpair(Cpair(it->second.Res1(),it->second.Res2()), resContact(it->second.Nframes(), it->second.DataPtr())) ); if (!ret.second) // residue pair exists, update it. ret.first->second.Increment( it->second.Nframes(), it->second.DataPtr() ); } std::sort( sortedList.begin(), sortedList.end() ); // Place residue pairs into an array to be sorted. std::vector<Rpair> ResList; for (resContactMap::const_iterator it = ResContacts.begin(); it != ResContacts.end(); ++it) { ResList.push_back( *it ); if (Rseries_ != NO_RESSERIES) { const char* resDsAspect; std::string lprefix = ""; if (isNative) resDsAspect = "NCRES"; else { resDsAspect = "NNRES"; lprefix = "nn_"; } // Ensure r1 < r2 so we can calculate a unique index for residue pairs // that can match between native/non-native contacts int r1, r2; if (it->first.second < it->first.first) { r1 = it->first.second; r2 = it->first.first; } else { r1 = it->first.first; r2 = it->first.second; } int ridx = (r2 * CurrentParm_->Nres()) + r1; std::string legend(lprefix + CurrentParm_->TruncResNameNum(r1) + "_" + CurrentParm_->TruncResNameNum(r2)); MetaData md(numnative_->Meta().Name(), resDsAspect, ridx); md.SetLegend( legend ); DataSet_integer* ds = (DataSet_integer*)masterDSL_->AddSet(DataSet::INTEGER, md); if (ds != 0) { ds->Allocate(DataSet::SizeArray(1, nframes_)); if (seriesRout_ != 0) seriesRout_->AddDataSet( ds ); // All series will be the same size thanks to UpdateSeries() for (unsigned int f = 0; f != nframes_; f++) { int total_present = 0; for (DSarray::const_iterator set = it->second.Sets().begin(); set != it->second.Sets().end(); ++set) total_present += (*(*set))[f]; if (Rseries_ == RES_PRESENT && total_present > 0) total_present = 1; ds->AddElement( total_present ); } } } } std::sort( ResList.begin(), ResList.end(), res_cmp() ); // Print out total fraction frames for residue pairs. const char* ctitle; if (isNative) ctitle = "Contacts"; else ctitle = "nnContacts"; rfile_->Printf("%-8s %8s %10s %10s\n", "#Res1", "#Res2", "TotalFrac", ctitle); //for (resContactMap::const_iterator it = ResContacts.begin(); it != ResContacts.end(); ++it) for (std::vector<Rpair>::const_iterator it = ResList.begin(); it != ResList.end(); ++it) rfile_->Printf("%-8i %8i %10g %10i\n", it->first.first+1, it->first.second+1, (double)it->second.Nframes()/(double)nframes_, it->second.Ncontacts()); // Print out sorted atom contacts. cfile_->Printf("%-8s %20s %8s %8s %8s %8s\n", "#", "Contact", "Nframes", "Frac.", "Avg", "Stdev"); unsigned int num = 1; for (std::vector<contactType>::const_iterator NC = sortedList.begin(); NC != sortedList.end(); ++NC, ++num) { double fracPresent = (double)NC->Nframes() / (double)nframes_; cfile_->Printf("%8u %20s %8i %8.3g %8.3g %8.3g\n", num, NC->id(), NC->Nframes(), fracPresent, NC->Avg(), NC->Stdev()); } }