Skip to content

Commit 8d2a923

Browse files
include backbone vector in create_molecule (#99)
* include backbone vector in create_molecule * include backbone vector in create molecule * Test for backbone vector in create_molecule() * backbone_vector added in the docstring and node_map/chain_map removed from setup_df * Add somesh to the list of authors, update changelog, include backbone_vector to pmb.create_pmb_objetct --------- Co-authored-by: pm-blanco <pablb@ntnu.no>
1 parent f73b582 commit 8d2a923

File tree

4 files changed

+57
-9
lines changed

4 files changed

+57
-9
lines changed

AUTHORS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ The following people have contributed to pyMBE (Github username, Name, current a
1212
- pinedaps, Sebastian P. Pineda (Charles University, Czech Republic)
1313

1414
## Tier-1 Contributors
15+
- 1234somesh, Somesh Kurahatti (University of Stuttgart, Germany)
1516
- amartise, Albert Martinez-Serra (Royal College of Surgeons, Ireland)
1617
- mariusaarsten, Marius Aarsten (Norwegian University of Science and Tecnology, Norway)
1718
- Zitzeronion, Stefan Zitz (Research Center Pharmaceutical Engineering, Austria)

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1717
- Switched to Ctest for testing, allowing to run the tests on paralel (#87)
1818

1919
### Added
20+
- New optional argument `backbone_vector` enabling to build molecules along an input vector using `pmb.create_molecule` and `pmb.create_pmb_object` (#99)
21+
- Unit testing for reaction methods (#86)
2022
- New boolean flag `--ideal` as argparse argument of `samples/globular_protein.py` enabling to run the script without setting up interactions.
2123
- Unit tests for `pmb.create_protein`, `pmb.enable_motion_of_rigid_object`, `pmb.protein_sequence_parser`, `pmb.define_protein`, `pmb.read_protein_vtf_in_df` (#101)
2224
- Library `lattice.py`, a general builder for crystaline lattices. This library is part of on-going project to support hydrogels in pyMBE. (#93)

pyMBE.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -873,15 +873,16 @@ def create_counterions(self, object_name, cation_name, anion_name, espresso_syst
873873
print(f'Ion type: {name} created number: {counterion_number[name]}')
874874
return counterion_number
875875

876-
def create_molecule(self, name, number_of_molecules, espresso_system, list_of_first_residue_positions=None, use_default_bond=False):
876+
def create_molecule(self, name, number_of_molecules, espresso_system, list_of_first_residue_positions=None, backbone_vector=None, use_default_bond=False):
877877
"""
878878
Creates `number_of_molecules` molecule of type `name` into `espresso_system` and bookkeeps them into `pmb.df`.
879879
880880
Args:
881881
name(`str`): Label of the molecule type to be created. `name` must be defined in `pmb.df`
882882
espresso_system(`espressomd.system.System`): Instance of a system object from espressomd library.
883883
number_of_molecules(`int`): Number of molecules of type `name` to be created.
884-
list_of_first_residue_positions(`list`, optional): List of coordinates where the central bead of the first_residue_position will be created, random by default
884+
list_of_first_residue_positions(`list`, optional): List of coordinates where the central bead of the first_residue_position will be created, random by default.
885+
backbone_vector(`list` of `float`): Backbone vector of the molecule, random by default. Central beads of the residues in the `residue_list` are placed along this vector.
885886
use_default_bond(`bool`, optional): Controls if a bond of type `default` is used to bond particle with undefined bonds in `pymbe.df`
886887
887888
Returns:
@@ -926,7 +927,8 @@ def create_molecule(self, name, number_of_molecules, espresso_system, list_of_fi
926927
for item in list_of_first_residue_positions:
927928
residue_position = [np.array(list_of_first_residue_positions[pos_index])]
928929
# Generate an arbitrary random unit vector
929-
backbone_vector = self.generate_random_points_in_a_sphere(center=[0,0,0],
930+
if backbone_vector is None:
931+
backbone_vector = self.generate_random_points_in_a_sphere(center=[0,0,0],
930932
radius=1,
931933
n_samples=1,
932934
on_surface=True)[0]
@@ -1039,7 +1041,7 @@ def create_particle(self, name, espresso_system, number_of_particles, position=N
10391041
self.add_value_to_df(key=('particle_id',''),index=df_index,new_value=bead_id, verbose=False)
10401042
return created_pid_list
10411043

1042-
def create_pmb_object(self, name, number_of_objects, espresso_system, position=None, use_default_bond=False):
1044+
def create_pmb_object(self, name, number_of_objects, espresso_system, position=None, use_default_bond=False, backbone_vector=None):
10431045
"""
10441046
Creates all `particle`s associated to `pmb object` into `espresso` a number of times equal to `number_of_objects`.
10451047
@@ -1049,6 +1051,7 @@ def create_pmb_object(self, name, number_of_objects, espresso_system, position=N
10491051
espresso_system(`espressomd.system.System`): Instance of an espresso system object from espressomd library.
10501052
position(`list`): Coordinates where the particles should be created.
10511053
use_default_bond(`bool`,optional): Controls if a `default` bond is used to bond particles with undefined bonds in `pmb.df`. Defaults to `False`.
1054+
backbone_vector(`list` of `float`): Backbone vector of the molecule, random by default. Central beads of the residues in the `residue_list` are placed along this vector.
10521055
10531056
Note:
10541057
- If no `position` is given, particles will be created in random positions. For bonded particles, they will be created at a distance equal to the bond length.
@@ -1066,13 +1069,15 @@ def create_pmb_object(self, name, number_of_objects, espresso_system, position=N
10661069
self.create_residue(name=name,
10671070
espresso_system=espresso_system,
10681071
central_bead_position=position,
1069-
use_default_bond=use_default_bond)
1072+
use_default_bond=use_default_bond,
1073+
backbone_vector=backbone_vector)
10701074
elif pmb_type == 'molecule':
10711075
self.create_molecule(name=name,
10721076
number_of_molecules=number_of_objects,
10731077
espresso_system=espresso_system,
10741078
use_default_bond=use_default_bond,
1075-
list_of_first_residue_positions=position)
1079+
list_of_first_residue_positions=position,
1080+
backbone_vector=backbone_vector)
10761081
return
10771082

10781083
def create_protein(self, name, number_of_proteins, espresso_system, topology_dict):
@@ -1855,7 +1860,7 @@ def find_bond_key(self, particle_name1, particle_name2, use_default_bond=False):
18551860
bond_keys = [particle_name1 +'-'+ particle_name2, particle_name2 +'-'+ particle_name1 ]
18561861
bond_defined=False
18571862
for bond_key in bond_keys:
1858-
if bond_key in self.df.values:
1863+
if bond_key in self.df["name"].values:
18591864
bond_defined=True
18601865
correct_key=bond_key
18611866
break
@@ -3221,7 +3226,7 @@ def setup_df (self):
32213226
'': object},
32223227
'l0': {
32233228
'': float},
3224-
}
3229+
}
32253230

32263231
self.df = pd.DataFrame(columns=pd.MultiIndex.from_tuples([(col_main, col_sub) for col_main, sub_cols in columns_dtypes.items() for col_sub in sub_cols.keys()]))
32273232

testsuite/define_and_create_molecules_unit_tests.py

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,13 +325,18 @@
325325
# Additional unit tests for define_molecule are in create_molecule_position_test
326326
print("*** Unit test: check that create_molecule() creates a simple molecule into the espresso_system with the properties defined in pmb.df ***")
327327

328-
pmb.create_molecule(name="M2",
328+
backbone_vector = np.array([1,3,-4])
329+
magnitude = np.linalg.norm(backbone_vector)
330+
backbone_vector = backbone_vector/magnitude
331+
molecule_info_M2 = pmb.create_molecule(name="M2",
329332
number_of_molecules=2,
330333
espresso_system=espresso_system,
334+
backbone_vector = backbone_vector,
331335
use_default_bond=True)
332336

333337
particle_ids=pmb.get_particle_id_map(object_name="M2")["all"]
334338

339+
335340
residue_ids={9: 2, 10: 3, 11: 3, 12: 3, 13: 4, 14: 4, 15: 4, 16: 4, # First molecule
336341
17: 5, 18: 6, 19: 6, 20: 6, 21: 7, 22: 7, 23: 7, 24: 7} # Second molecule
337342

@@ -412,6 +417,41 @@
412417
verbose=True)
413418

414419
print("*** Unit test passed ***")
420+
421+
print("*** Unit test: check the backbone vector of the molecule in espresso and the given input backbone vector are same ***")
422+
423+
424+
central_bead_positions = []
425+
426+
for residue_name in molecule_parameters["M2"]["residue_list"]:
427+
428+
mol_id = pmb.df[pmb.df["name"]=="M2"]["molecule_id"].values[0]
429+
res_id = pmb.df[(pmb.df["molecule_id"]==mol_id) & (pmb.df['name']==residue_name)]["residue_id"].values[0]
430+
central_bead_id = molecule_info_M2[mol_id][res_id]['central_bead_id']
431+
central_bead_pos = espresso_system.part.by_id(central_bead_id).pos
432+
central_bead_positions.append(central_bead_pos)
433+
434+
if len(central_bead_positions) == len(molecule_parameters["M2"]["residue_list"]):
435+
436+
backbone_direction_1 = central_bead_positions[1] - central_bead_positions[0]
437+
backbone_direction_2 = central_bead_positions[2] - central_bead_positions[1]
438+
backbone_direction_1 /= np.linalg.norm(backbone_direction_1)
439+
backbone_direction_2 /= np.linalg.norm(backbone_direction_2)
440+
np.testing.assert_almost_equal(
441+
actual = backbone_direction_1,
442+
desired = backbone_vector,
443+
verbose = True)
444+
np.testing.assert_almost_equal(
445+
actual = backbone_direction_2,
446+
desired = backbone_vector,
447+
verbose = True)
448+
449+
else:
450+
451+
raise ValueError("Expected 3 central bead positions for residues R1, R2, and R3")
452+
453+
print("*** Unit test passed ***")
454+
415455
print("*** Unit test: check that create_molecule() does not create any molcule for number_of_molecules <= 0 ***")
416456

417457
starting_number_of_particles=len(espresso_system.part.all())

0 commit comments

Comments
 (0)