Skip to content

Commit b8fde4c

Browse files
nffarukpengxd
andcommitted
Split logging of rotamer potential and entropy, incremental suffixes to distinguish multiple rotamer types
Co-authored-by: pengxd <pengxda@gmail.com> Co-authored-by: Nabil Faisal Faruk <nffaruk@uchicago.edu>
1 parent bb84a39 commit b8fde4c

File tree

3 files changed

+137
-11
lines changed

3 files changed

+137
-11
lines changed

examples/nse_run_complex.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ def mp_recalc_pe((config_fn, frame)):
141141
is_unbound = False # Whether using the unbound or bound conformations of the substituents
142142
default_pe = False # Whether only using the folding forcefield
143143
do_analysis = True
144-
do_ana_only = False
144+
do_ana_only = True
145145
n_rep = 3 # Number of simulation replicates
146146
pool_size = 4 # Number of subprocesses for multiprocessing. Used for SCWRLing and post-sim energy re-evaluation.
147147
seed = 1 # Random seed to use for sims

py/upside_config.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1154,6 +1154,7 @@ def arg_maybe(nm):
11541154
g._v_attrs.tol = 1e-3
11551155
g._v_attrs.damping = damping
11561156
g._v_attrs.iteration_chunk_size = 2
1157+
g._v_attrs.log_suffix = 0
11571158

11581159
pg = t.create_group(g, "pair_interaction")
11591160

@@ -1351,6 +1352,7 @@ def add_docking_terms(config_fn, rot_param, env_param_dict):
13511352
# placement_scalar (rotamer 1body energies), hbond_coverage, and hbond_coverage_hydrophobe. Remove hbond args
13521353
inter_args = g_new._v_attrs.arguments[:][:2]
13531354
g_new._v_attrs.arguments = inter_args
1355+
g_new._v_attrs.log_suffix = 1
13541356
g_new.pair_interaction._v_attrs.l_start = chain_first_residue[rl_chains[0]-1]
13551357
g_new.pair_interaction.interaction_param[:] = rot_param[:]
13561358

src/rotamer.cpp

Lines changed: 134 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,26 @@ struct NodeHolder {
300300
for(int no: range(N_ROT)) en += b[no] * logf((1e-10f+b[no])*rcp(1e-10f+pr[no]));
301301
return en;
302302
}
303+
304+
// add by pengxd to split the potential and entropy
305+
template <int N_ROT, int EType>
306+
float node_entropy(int nn) {
307+
auto b = load_vec<N_ROT>(cur_belief,nn);
308+
b *= rcp(sum(b));
309+
auto pr = load_vec<N_ROT>(prob,nn);
310+
311+
float en = 0;
312+
if (EType == 0) {
313+
// average energy
314+
en = energy_offset[nn];
315+
for(int no: range(N_ROT)) en -= b[no] * logf( 1e-10f+pr[no] );
316+
}
317+
else {
318+
// entropy
319+
for(int no: range(N_ROT)) en += b[no] * logf( 1e-10f+b[no] );
320+
}
321+
return en;
322+
}
303323
};
304324

305325
constexpr static int simd_width = 4;
@@ -450,6 +470,33 @@ struct EdgeHolder {
450470
return en;
451471
}
452472

473+
// add by pengxd to split the potential and entropy
474+
template<int N_ROT1, int N_ROT2, int EType>
475+
float edge_entropy(int ne) {
476+
auto b1 = load_vec<N_ROT1>(nodes1.cur_belief, edge_indices1[ne]); // really marginal
477+
auto b2 = load_vec<N_ROT2>(nodes2.cur_belief, edge_indices2[ne]);
478+
479+
auto p = load_vec<N_ROT1* N_ROT2 >(marginal, ne);
480+
auto pr = load_vec<N_ROT1*ru(N_ROT2)>(prob, ne);
481+
482+
float en = 0.f;
483+
for(int no1: range(N_ROT1)) {
484+
for(int no2: range(N_ROT2)) {
485+
int i = no1*N_ROT2 + no2;
486+
if (EType == 0) {
487+
// average potential energy
488+
en -= p[i] * logf( 1e-10f+pr[no1*ru(N_ROT2)+no2] );
489+
}
490+
else {
491+
// the mutual information
492+
en += p[i] * logf( (1e-10f+p[i]) * rcp(1e-10f+b1[no1]*b2[no2]) );
493+
}
494+
}
495+
}
496+
497+
return en;
498+
}
499+
453500
template <int N_ROT1, int N_ROT2>
454501
void update_beliefs() {
455502
constexpr const int w1 = (N_ROT1+3)/4;
@@ -598,6 +645,7 @@ struct RotamerSidechain: public PotentialNode {
598645
int max_iter;
599646
float tol;
600647
int iteration_chunk_size;
648+
int log_suffix;
601649

602650
bool energy_fresh_relative_to_derivative;
603651

@@ -627,14 +675,30 @@ struct RotamerSidechain: public PotentialNode {
627675
energy_cap (-4.),
628676
energy_cap_width( 1.),
629677

630-
damping (read_attribute<float>(grp, ".", "damping")),
631-
max_iter(read_attribute<int >(grp, ".", "max_iter")),
632-
tol (read_attribute<float>(grp, ".", "tol")),
678+
damping (read_attribute<float>(grp, ".", "damping")),
679+
max_iter (read_attribute<int >(grp, ".", "max_iter")),
680+
tol (read_attribute<float>(grp, ".", "tol")),
633681
iteration_chunk_size(read_attribute<int>(grp, ".", "iteration_chunk_size")),
682+
log_suffix (read_attribute<int> (grp, ".", "log_suffix", 0)),
634683

635684
energy_fresh_relative_to_derivative(false),
636685
n_bad_solve(0)
637686
{
687+
688+
// Increment the suffix if another group exists
689+
// default_logger not created during python library call of engine, so must check for it first
690+
if(default_logger) {
691+
bool suff_exists = true;
692+
while(suff_exists) {
693+
if(h5_exists(default_logger->logging_group.get(), ("rotamer_free_energy_" + to_string(log_suffix)).c_str())) {
694+
log_suffix++;
695+
} else {
696+
suff_exists = false;
697+
}
698+
}
699+
}
700+
// printf("log_suffix %i\n", log_suffix);
701+
638702
for(int i: range(UPPER_ROT)) node_holders_matrix[i] = nullptr;
639703
node_holders_matrix[1] = &nodes1;
640704
node_holders_matrix[3] = &nodes3;
@@ -654,21 +718,41 @@ struct RotamerSidechain: public PotentialNode {
654718
" elements but the " + to_string(i) + "-th (0-indexed) probability node has only " +
655719
to_string(prob_nodes[i]->n_elem) + " elements.");
656720

657-
if(logging(LOG_DETAILED))
658-
default_logger->add_logger<long>("rotamer_bad_solves_cumulative", {1},
659-
[&](long* buffer) {buffer[0]=n_bad_solve;});
660-
661721
if(logging(LOG_DETAILED)) {
662-
default_logger->add_logger<float>("rotamer_free_energy", {nodes1.n_elem+nodes3.n_elem+nodes6.n_elem},
722+
string log_name = "rotamer_bad_solves_cumulative_" + to_string(log_suffix);
723+
default_logger->add_logger<long>(log_name.c_str(), {1},
724+
[&](long* buffer) {buffer[0]=n_bad_solve;});
725+
}
726+
if(logging(LOG_BASIC)) {
727+
// add by pengxd to deal with multi-rotamer
728+
string log_name = "rotamer_free_energy_" + to_string(log_suffix);
729+
default_logger->add_logger<float>(log_name.c_str(), {nodes1.n_elem+nodes3.n_elem+nodes6.n_elem},
663730
[&](float* buffer) {
664731
auto en = residue_free_energies();
665732
copy(begin(en), end(en), buffer);});
666733

667-
for(int npn: range(n_prob_nodes))
668-
default_logger->add_logger<float>(("rotamer_1body_energy" + to_string(npn)).c_str(),
734+
// add by pengxd to split the potential and entropy
735+
log_name = "rotamer_potential_" + to_string(log_suffix);
736+
default_logger->add_logger<float>(log_name.c_str(), {nodes1.n_elem+nodes3.n_elem+nodes6.n_elem},
737+
[&](float* buffer) {
738+
auto en = residue_entropy<0>();
739+
copy(begin(en), end(en), buffer);});
740+
741+
// add by pengxd to split the potential and entropy
742+
log_name = "rotamer_entropy_" + to_string(log_suffix);
743+
default_logger->add_logger<float>(log_name.c_str(), {nodes1.n_elem+nodes3.n_elem+nodes6.n_elem},
744+
[&](float* buffer) {
745+
auto en = residue_entropy<1>();
746+
copy(begin(en), end(en), buffer);});
747+
748+
// add by pengxd to deal with multi-rotamer
749+
for(int npn: range(n_prob_nodes)) {
750+
log_name = "rotamer_1body_energy_" + to_string(log_suffix);
751+
default_logger->add_logger<float>((log_name + to_string(npn)).c_str(),
669752
{nodes1.n_elem+nodes3.n_elem+nodes6.n_elem}, [npn,this](float* buffer) {
670753
auto en = this->rotamer_1body_energy(npn);
671754
copy(begin(en), end(en), buffer);});
755+
}
672756
}
673757
}
674758

@@ -903,6 +987,46 @@ struct RotamerSidechain: public PotentialNode {
903987
return arrange_energies(e1,e3,e6);
904988
}
905989

990+
// add by pengxd to split the potential and entropy
991+
template<int EType>
992+
vector<float> residue_entropy() {
993+
vector<float> e1(nodes1.n_elem, 0.f);
994+
vector<float> e3(nodes3.n_elem, 0.f);
995+
vector<float> e6(nodes6.n_elem, 0.f);
996+
997+
for(int nn: range(nodes1 .n_elem)) {float en = nodes1.node_entropy<1,EType>(nn); e1[nn] += en;}
998+
for(int nn: range(nodes3 .n_elem)) {float en = nodes3.node_entropy<3,EType>(nn); e3[nn] += en;}
999+
for(int nn: range(nodes6 .n_elem)) {float en = nodes6.node_entropy<6,EType>(nn); e6[nn] += en;}
1000+
1001+
if (EType == 0) {
1002+
for(int ne: range(edges11.nodes_to_edge.n_edge)) {
1003+
float en = -logf(edges11.prob(0,ne));
1004+
e1[edges11.edge_indices1[ne]] += 0.5*en;
1005+
e1[edges11.edge_indices2[ne]] += 0.5*en;
1006+
}
1007+
}
1008+
1009+
for(int ne: range(edges33.nodes_to_edge.n_edge)) {
1010+
float en = edges33.edge_entropy<3,3,EType>(ne);
1011+
e3[edges33.edge_indices1[ne]] += 0.5*en;
1012+
e3[edges33.edge_indices2[ne]] += 0.5*en;
1013+
}
1014+
1015+
for(int ne: range(edges36.nodes_to_edge.n_edge)) {
1016+
float en = edges36.edge_entropy<3,6,EType>(ne);
1017+
e3[edges36.edge_indices1[ne]] += 0.5*en;
1018+
e6[edges36.edge_indices2[ne]] += 0.5*en;
1019+
}
1020+
1021+
for(int ne: range(edges66.nodes_to_edge.n_edge)) {
1022+
float en = edges66.edge_entropy<6,6,EType>(ne);
1023+
e6[edges66.edge_indices1[ne]] += 0.5*en;
1024+
e6[edges66.edge_indices2[ne]] += 0.5*en;
1025+
}
1026+
1027+
return arrange_energies(e1,e3,e6);
1028+
}
1029+
9061030
vector<float> rotamer_1body_energy(int prob_node_index) {
9071031
vector<float> e1(nodes1.n_elem, 0.f);
9081032
vector<float> e3(nodes3.n_elem, 0.f);

0 commit comments

Comments
 (0)