Skip to content

Commit fa65669

Browse files
committed
adding averaging
1 parent 218616c commit fa65669

5 files changed

Lines changed: 225 additions & 110 deletions

File tree

CodeEntropy/config/arg_config_manager.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,11 @@
6464
"help": "If set to False, disables the calculation of water entropy",
6565
"default": True,
6666
},
67+
"grouping": {
68+
"type": str,
69+
"help": "How to group molecules for averaging",
70+
"default": "each",
71+
},
6772
}
6873

6974

CodeEntropy/entropy.py

Lines changed: 50 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class EntropyManager:
1616
molecular dynamics trajectory.
1717
"""
1818

19-
def __init__(self, run_manager, args, universe, data_logger, level_manager):
19+
def __init__(self, run_manager, args, universe, data_logger, level_manager, group_molecules):
2020
"""
2121
Initializes the EntropyManager with required components.
2222
@@ -32,6 +32,7 @@ def __init__(self, run_manager, args, universe, data_logger, level_manager):
3232
self._universe = universe
3333
self._data_logger = data_logger
3434
self._level_manager = level_manager
35+
self._group_molecules = group_molecules
3536
self._GAS_CONST = 8.3144598484848
3637

3738
def execute(self):
@@ -53,24 +54,28 @@ def execute(self):
5354
self._universe,
5455
self._data_logger,
5556
self._level_manager,
57+
self._group_molecules,
5658
)
5759
ce = ConformationalEntropy(
5860
self._run_manager,
5961
self._args,
6062
self._universe,
6163
self._data_logger,
6264
self._level_manager,
65+
self._group_molecules,
6366
)
6467

6568
self._handle_water_entropy(start, end, step)
66-
reduced_atom, number_molecules, levels = self._initialize_molecules()
69+
reduced_atom, number_molecules, levels, groups = self._initialize_molecules()
70+
number_groups = len(groups)
71+
number_frames = len(reduced_atom.trajectory)
6772

6873
force_matrices, torque_matrices = (
6974
self._level_manager.build_covariance_matrices(
7075
self,
7176
reduced_atom,
72-
number_molecules,
7377
levels,
78+
groups,
7479
start,
7580
end,
7681
step,
@@ -84,6 +89,7 @@ def execute(self):
8489
reduced_atom,
8590
number_molecules,
8691
levels,
92+
groups,
8793
start,
8894
end,
8995
step,
@@ -95,16 +101,13 @@ def execute(self):
95101

96102
self._compute_entropies(
97103
reduced_atom,
98-
number_molecules,
99104
levels,
105+
groups,
100106
force_matrices,
101107
torque_matrices,
102108
states_ua,
103109
states_res,
104110
number_frames,
105-
start,
106-
end,
107-
step,
108111
ve,
109112
ce,
110113
)
@@ -152,21 +155,21 @@ def _initialize_molecules(self):
152155
"""
153156
reduced_atom = self._get_reduced_universe()
154157
number_molecules, levels = self._level_manager.select_levels(reduced_atom)
155-
return reduced_atom, number_molecules, levels
158+
grouping = self._args.grouping
159+
groups = self._group_molecules.grouping_molecules(reduced_atom, grouping)
160+
161+
return reduced_atom, number_molecules, levels, groups
156162

157163
def _compute_entropies(
158164
self,
159165
reduced_atom,
160-
number_molecules,
161166
levels,
167+
groups,
162168
force_matrices,
163169
torque_matrices,
164170
states_ua,
165171
states_res,
166172
number_frames,
167-
start,
168-
end,
169-
step,
170173
ve,
171174
ce,
172175
):
@@ -191,20 +194,15 @@ def _compute_entropies(
191194
states_ua (dict): Dictionary to store united-atom conformational states.
192195
states_res (list): List to store residue-level conformational states.
193196
number_frames (int): Total number of trajectory frames to process.
194-
start (int): Start frame index.
195-
end (int): End frame index.
196-
step (int): Step size for frame iteration.
197197
"""
198-
bin_width = self._args.bin_width
199-
200-
for mol_id in range(number_molecules):
201-
mol = self._get_molecule_container(reduced_atom, mol_id)
202-
for level in levels[mol_id]:
203-
highest = level == levels[mol_id][-1]
198+
for group_id in groups.keys():
199+
mol = self._get_molecule_container(reduced_atom, groups[group_id][0])
200+
for level in levels[groups[group_id][0]]:
201+
highest = level == levels[groups[group_id][0]][-1]
204202

205203
if level == "united_atom":
206204
self._process_united_atom_entropy(
207-
mol_id,
205+
group_id,
208206
mol,
209207
ve,
210208
ce,
@@ -218,18 +216,17 @@ def _compute_entropies(
218216

219217
elif level == "residue":
220218
self._process_vibrational_entropy(
221-
mol_id,
222-
mol,
219+
group_id,
220+
number_frames,
223221
ve,
224222
level,
225-
force_matrices["res"][mol_id],
226-
torque_matrices["res"][mol_id],
223+
force_matrices["res"][group_id],
224+
torque_matrices["res"][group_id],
227225
highest,
228226
)
229227

230228
self._process_conformational_entropy(
231-
mol_id,
232-
mol,
229+
group_id,
233230
ce,
234231
level,
235232
states_res,
@@ -238,12 +235,12 @@ def _compute_entropies(
238235

239236
elif level == "polymer":
240237
self._process_vibrational_entropy(
241-
mol_id,
242-
mol,
238+
group_id,
239+
number_frames,
243240
ve,
244241
level,
245-
force_matrices["poly"][mol_id],
246-
torque_matrices["poly"][mol_id],
242+
force_matrices["poly"][group_id],
243+
torque_matrices["poly"][group_id],
247244
highest,
248245
)
249246

@@ -317,7 +314,7 @@ def _get_molecule_container(self, universe, molecule_id):
317314

318315
def _process_united_atom_entropy(
319316
self,
320-
mol_id,
317+
group_id,
321318
mol_container,
322319
ve,
323320
ce,
@@ -347,7 +344,7 @@ def _process_united_atom_entropy(
347344

348345
for residue_id, residue in enumerate(mol_container.residues):
349346

350-
key = (mol_id, residue_id)
347+
key = (group_id, residue_id)
351348

352349
f_matrix = force_matrix[key]
353350
f_matrix = self._level_manager.filter_zero_rows_columns(f_matrix)
@@ -373,27 +370,27 @@ def _process_united_atom_entropy(
373370
S_conf += S_conf_res
374371

375372
self._data_logger.add_residue_data(
376-
mol_id, residue.resname, level, "Transvibrational", S_trans_res
373+
residue_id, residue.resname, level, "Transvibrational", S_trans_res
377374
)
378375
self._data_logger.add_residue_data(
379-
mol_id, residue.resname, level, "Rovibrational", S_rot_res
376+
residue_id, residue.resname, level, "Rovibrational", S_rot_res
380377
)
381378
self._data_logger.add_residue_data(
382-
mol_id, residue.resname, level, "Conformational", S_conf_res
379+
residue_id, residue.resname, level, "Conformational", S_conf_res
383380
)
384381

385382
self._data_logger.add_results_data(
386-
residue.resname, level, "Transvibrational", S_trans
383+
group_id, level, "Transvibrational", S_trans
387384
)
388385
self._data_logger.add_results_data(
389-
residue.resname, level, "Rovibrational", S_rot
386+
group_id, level, "Rovibrational", S_rot
390387
)
391388
self._data_logger.add_results_data(
392-
residue.resname, level, "Conformational", S_conf
389+
group_id, level, "Conformational", S_conf
393390
)
394391

395392
def _process_vibrational_entropy(
396-
self, mol_id, mol_container, ve, level, force_matrix, torque_matrix, highest
393+
self, group_id, number_frames, ve, level, force_matrix, torque_matrix, highest
397394
):
398395
"""
399396
Calculates vibrational entropy.
@@ -408,8 +405,6 @@ def _process_vibrational_entropy(
408405
highest (bool): Flag indicating if this is the highest granularity
409406
level.
410407
"""
411-
number_frames = len(mol_container.trajectory)
412-
413408
force_matrix = self._level_manager.filter_zero_rows_columns(force_matrix)
414409
force_matrix = force_matrix / number_frames
415410

@@ -422,16 +417,16 @@ def _process_vibrational_entropy(
422417
S_rot = ve.vibrational_entropy_calculation(
423418
torque_matrix, "torque", self._args.temperature, highest
424419
)
425-
residue = mol_container.residues[mol_id]
420+
426421
self._data_logger.add_results_data(
427-
residue.resname, level, "Transvibrational", S_trans
422+
group_id, level, "Transvibrational", S_trans
428423
)
429424
self._data_logger.add_results_data(
430-
residue.resname, level, "Rovibrational", S_rot
425+
group_id, level, "Rovibrational", S_rot
431426
)
432427

433428
def _process_conformational_entropy(
434-
self, mol_id, mol_container, ce, level, states, number_frames
429+
self, group_id, ce, level, states, number_frames
435430
):
436431
"""
437432
Computes conformational entropy at the residue level (whole-molecule dihedral
@@ -445,10 +440,10 @@ def _process_conformational_entropy(
445440
start, end, step (int): Frame bounds.
446441
n_frames (int): Number of frames used.
447442
"""
448-
S_conf = ce.conformational_entropy_calculation(states[mol_id], number_frames)
449-
residue = mol_container.residues[mol_id]
443+
S_conf = ce.conformational_entropy_calculation(states[group_id], number_frames)
444+
450445
self._data_logger.add_results_data(
451-
residue.resname, level, "Conformational", S_conf
446+
group_id, level, "Conformational", S_conf
452447
)
453448

454449
def _finalize_molecule_results(self):
@@ -599,12 +594,12 @@ class VibrationalEntropy(EntropyManager):
599594
vibrational modes and thermodynamic properties.
600595
"""
601596

602-
def __init__(self, run_manager, args, universe, data_logger, level_manager):
597+
def __init__(self, run_manager, args, universe, data_logger, level_manager, group_molecules):
603598
"""
604599
Initializes the VibrationalEntropy manager with all required components and
605600
defines physical constants used in vibrational entropy calculations.
606601
"""
607-
super().__init__(run_manager, args, universe, data_logger, level_manager)
602+
super().__init__(run_manager, args, universe, data_logger, level_manager, group_molecules)
608603
self._PLANCK_CONST = 6.62607004081818e-34
609604

610605
def frequency_calculation(self, lambdas, temp):
@@ -723,12 +718,12 @@ class ConformationalEntropy(EntropyManager):
723718
analysis using statistical mechanics principles.
724719
"""
725720

726-
def __init__(self, run_manager, args, universe, data_logger, level_manager):
721+
def __init__(self, run_manager, args, universe, data_logger, level_manager, group_molecules):
727722
"""
728723
Initializes the ConformationalEntropy manager with all required components and
729724
sets the gas constant used in conformational entropy calculations.
730725
"""
731-
super().__init__(run_manager, args, universe, data_logger, level_manager)
726+
super().__init__(run_manager, args, universe, data_logger, level_manager, group_molecules)
732727

733728
def assign_conformation(
734729
self, data_container, dihedral, number_frames, bin_width, start, end, step
@@ -760,7 +755,7 @@ def assign_conformation(
760755

761756
# get the values of the angle for the dihedral
762757
# dihedral angle values have a range from -180 to 180
763-
for timestep in data_container.trajectory[start:end:step]:
758+
for timestep in data_container.trajectory[start:end+1:step]:
764759
timestep_index = timestep.frame - start
765760
value = dihedral.value()
766761
# we want postive values in range 0 to 360 to make the peak assignment

0 commit comments

Comments
 (0)