Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Switched to Ctest for testing, allowing to run the tests on paralel (#87)

### Added
- Helper method to delete entries from `pmb.df` (#112)
- Code of conduct of our community `CODE_OF_CONDUCT.md`, adhering to the Contributor Covenant v2.1 (#104)
- New optional argument `backbone_vector` enabling to build molecules along an input vector using `pmb.create_molecule` and `pmb.create_pmb_object` (#99)
- New boolean flag `--ideal` as argparse argument of `samples/globular_protein.py` enabling to run the script without setting up interactions.
Expand All @@ -28,6 +29,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Unit testing for reaction methods. (#86)

### Fixed
- Warning handling and coverage in `setup_lj_interaction` (#112)
- Wrong parsing in `pmb.protein_sequence_parser` of input sequences provided as a list of aminoacids using the three letter code. (#101)
- Wrong setup of the rigid object in `pmb.enable_motion_of_rigid_object`, leading to crashes in `samples/globular_protein.py` when enabling the protein motion. (#101)
- The argparse argument `--move_protein` of `samples/globular_protein.py` is now a boolean flag instead of taking arbitrary float values. (#101)
Expand Down
22 changes: 17 additions & 5 deletions pyMBE.py
Original file line number Diff line number Diff line change
Expand Up @@ -1670,7 +1670,19 @@ def define_residue(self, name, central_bead, side_chains):
self.df.at [index,'pmb_type'] = 'residue'
self.df.at [index,'central_bead'] = central_bead
self.df.at [index,('side_chains','')] = side_chains
return
return

def delete_entries_in_df(self, entry_name):
"""
Deletes entries with name `entry_name` from the DataFrame if it exists.

Args:
entry_name (`str`): The name of the entry in the dataframe to delete.

"""
if entry_name in self.df["name"].values:
self.df = self.df[self.df["name"] != entry_name].reset_index(drop=True)


def destroy_pmb_object_in_system(self, name, espresso_system):
"""
Expand Down Expand Up @@ -3237,15 +3249,15 @@ def setup_lj_interactions(self, espresso_system, shift_potential=True, combining

"""
from itertools import combinations_with_replacement
import warnings
implemented_combining_rules = ['Lorentz-Berthelot']
compulsory_parameters_in_df = ['sigma','epsilon']
# Sanity check
if combining_rule not in implemented_combining_rules:
raise ValueError('In the current version of pyMBE, the only combinatorial rules implemented are ', implemented_combining_rules)
shift=0
if shift_potential:
shift="auto"
else:
shift=0
# List which particles have sigma and epsilon values defined in pmb.df and which ones don't
particles_types_with_LJ_parameters = []
non_parametrized_labels= []
Expand Down Expand Up @@ -3293,8 +3305,8 @@ def setup_lj_interactions(self, espresso_system, shift_potential=True, combining
new_value=lj_params,
non_standard_value=True)
if non_parametrized_labels and warnings:
print(f'WARNING: The following particles do not have a defined value of sigma or epsilon in pmb.df: {non_parametrized_labels}. No LJ interaction has been added in ESPResSo for those particles.')
warnings.warn(f'The following particles do not have a defined value of sigma or epsilon in pmb.df: {non_parametrized_labels}. No LJ interaction has been added in ESPResSo for those particles.',UserWarning)

return

def write_pmb_df (self, filename):
Expand Down
70 changes: 70 additions & 0 deletions testsuite/delete_entries_in_df.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#
# Copyright (C) 2025 pyMBE-dev team
#
# This file is part of pyMBE.
#
# pyMBE is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# pyMBE is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

import pyMBE

pmb = pyMBE.pymbe_library(seed=42)
reduced_unit_set = pmb.get_reduced_units()
particle_parameters={"S1":{"name": "S1",
"sigma":0.355*pmb.units.nm,
"epsilon":1*pmb.units('reduced_energy'),
"z":0},
"S2":{"name": "S2",
"sigma":0.355*pmb.units.nm,
"epsilon":1*pmb.units('reduced_energy'),
"z":1},
"S3":{"name": "S3",
"sigma":0.355*pmb.units.nm,
"epsilon":1*pmb.units('reduced_energy'),
"z":2}}

pmb.define_particles(parameters=particle_parameters)

generic_harmonic_constant = 400 * pmb.units('reduced_energy / reduced_length**2')
generic_bond_length = 0.355*pmb.units.nm
HARMONIC_parameters = {'r_0' : generic_bond_length,
'k' : generic_harmonic_constant}
pmb.define_bond(bond_type = 'harmonic',
bond_parameters = HARMONIC_parameters, particle_pairs = [["S1", "S2"]])

pmb.delete_entries_in_df(entry_name="S1-S2")
assert pmb.df[pmb.df["name"]=="S1-S2"].empty
pmb.delete_entries_in_df(entry_name="S1")
assert pmb.df[pmb.df["name"]=="S1"].empty

residue_parameters={"R1":{"name": "R1",
"central_bead": "S2",
"side_chains": []},
"R2":{"name": "R2",
"central_bead": "S2",
"side_chains": ["S2","S3"]}}

for parameter_set in residue_parameters.values():
pmb.define_residue(**parameter_set)

pmb.delete_entries_in_df(entry_name="R1")
assert pmb.df[pmb.df["name"]=="R1"].empty

molecule_parameters={"M1":{"name": "M1",
"residue_list": ["R2","R2","R2"]}}

for parameter_set in molecule_parameters.values():
pmb.define_molecule(**parameter_set)

pmb.delete_entries_in_df(entry_name="M1")
assert pmb.df[pmb.df["name"]=="M1"].empty
21 changes: 19 additions & 2 deletions testsuite/lj_tests.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#
# Copyright (C) 2024 pyMBE-dev team
# Copyright (C) 2024-2025 pyMBE-dev team
#
# This file is part of pyMBE.
#
Expand Down Expand Up @@ -112,15 +112,32 @@
"epsilon":pmb.units.Quantity(2,"reduced_energy"),
"cutoff":2*2**(1./6.)*pmb.units.nm,
"offset":2*pmb.units.nm}
X_input_parameters={"name":"X"}

pmb.define_particle(**A_input_parameters)
pmb.define_particle(**B_input_parameters)
pmb.define_particle(**C_input_parameters)
pmb.define_particle(**X_input_parameters)

# Create a dummy instance of an espresso system
import espressomd
espresso_system=espressomd.System(box_l = [50]*3)

# Setup LJ interactions
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter("always") # Capture all warnings, even those normally ignored
pmb.setup_lj_interactions(espresso_system=espresso_system)
assert any("The following particles do not have a defined value of sigma or epsilon" in str(warning.message) for warning in w), "Expected warning was not raised!"

pmb.delete_entries_in_df("X")

# ValueError if combining-rule other than Lorentz_-Berthelot is used
input_params = {"espresso_system":espresso_system, "combining_rule": "Geometric"}
np.testing.assert_raises(ValueError, pmb.setup_lj_interactions, **input_params)

# Initialized with shift=0
pmb.setup_lj_interactions(espresso_system=espresso_system, shift_potential=False)

# Setup LJ interactions shift="auto"
pmb.setup_lj_interactions(espresso_system=espresso_system)

# Check A-A LJ setup
Expand Down