diff --git a/.github/workflows/samples.yml b/.github/workflows/samples.yml
index 6f45ba6..3503e55 100644
--- a/.github/workflows/samples.yml
+++ b/.github/workflows/samples.yml
@@ -26,7 +26,7 @@ jobs:
uses: ./.github/actions/dependencies
with:
modules: |-
- ESPResSo/4.2.1-foss-2023a
+ ESPResSo/4.2.2-foss-2023a
- name: Run testsuite
run: |
module restore pymbe
diff --git a/.github/workflows/testsuite.yml b/.github/workflows/testsuite.yml
index 3c408d5..4fde10e 100644
--- a/.github/workflows/testsuite.yml
+++ b/.github/workflows/testsuite.yml
@@ -27,7 +27,7 @@ jobs:
uses: ./.github/actions/dependencies
with:
modules: |-
- ESPResSo/4.2.1-foss-2023a
+ ESPResSo/4.2.2-foss-2023a
extra-python-packages: |-
pdoc==14.3
pylint==3.0.3
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5b6075f..83d6d4e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -35,6 +35,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `lib.analysis.get_dt` now raises a ValueError if the two first two rows of the dataframe have the same values for the time, which break the subsequent code. (#95)
- Removed global state variables, instead they are now created by the constructor of `pyMBE.pymbe_library`. This prevents two instances of the pyMBE library to share the same memory address for their attributes. (#89)
- Required Python dependency versions compatible with ESPResSo 4.2 (#84)
+- NumPy 2, Pandas 2 and the development version of ESPResSo are now fully supported. (#106)
- Fixed several deprecated paths and function names in `tutorials/pyMBE_tutorial.ipynb`. (#77, #78, #79, #80, #81)
## [0.8.0] - 2024-06-18
diff --git a/README.md b/README.md
index b640914..ef3b6e5 100644
--- a/README.md
+++ b/README.md
@@ -14,14 +14,22 @@ pyMBE provides tools to facilitate building up molecules with complex architectu
## Dependencies
-- [ESPResSo](https://espressomd.org/wordpress/) =4.2.1
-- [Pint](https://pint.readthedocs.io/en/stable/) >=0.20.01
-- [Pandas](https://pandas.pydata.org/) >=1.5.3
-- [Pint-Pandas](https://pypi.org/project/Pint-Pandas/) >=0.3
-- [Numpy](https://numpy.org/) >=1.23
-- [SciPy](https://scipy.org/)
+- [ESPResSo](https://espressomd.org/wordpress/)
+- [Pint](https://pint.readthedocs.io/en/stable/)
+- [Pandas](https://pandas.pydata.org/)
+- [Pint-Pandas](https://pypi.org/project/Pint-Pandas/)
+- [Numpy](https://numpy.org/)
+- [SciPy](https://scipy.org/)
- [pdoc](https://pdoc.dev/) (for building the docs)
- [CMake](https://cmake.org/) (for running the testsuite)
+- any virtual environment manager: [venv](https://docs.python.org/3/library/venv.html),
+ [virtualenv](https://virtualenv.pypa.io/en/latest/),
+ [conda](https://docs.conda.io/projects/conda/en/latest/user-guide/getting-started.html#managing-python),
+ [miniconda](https://docs.anaconda.com/free/miniconda),
+ [micromamba](https://mamba.readthedocs.io/en/latest/user_guide/micromamba.html),
+ etc.
+
+Version requirements are documented in [`requirements.txt`](requirements.txt).
## Contents
@@ -50,33 +58,42 @@ git clone git@github.com:pyMBE-dev/pyMBE.git
```
Please, be aware that pyMBE is intended to be a supporting tool to setup simulations with ESPResSo.
-Thus, for most of its functionalities ESPResSo must also be available. Following the NEP29 guidelines, we recommend the users of pyMBE to use Python3.10+ when using our module.
+Thus, for most of its functionalities ESPResSo must also be available.
+pyMBE supports ESPResSo 4.2 and ESPResSo 4.3-dev.
+Following the NEP29 guidelines, we recommend using Python3.10+.
+Both NumPy 1 and NumPy 2 are supported.
-The pyMBE module uses its own Python virtual enviroment to avoid incompatibility issues when loading its requirements from other libraries.
-The Python module [`venv`](https://docs.python.org/3/library/venv.html) is needed to set up pyMBE.
-If `venv` is not in the Python distribution of the user, the user will need to first install 'venv' before setting up pyMBE.
-For Ubuntu users, this can be done as follows:
+The pyMBE module needs a Python virtual environment to avoid compatibility issues with its dependencies.
+Any virtual environment manager should work, but this readme will use `venv`, which can be installed on Ubuntu as follows:
```sh
sudo apt install python3-venv
```
-To set up pyMBE, the users need to install its virtual environment, install its Python dependencies and configure the path to the ESPResSo build folder as follows:
+To set up pyMBE, users need to configure a virtual environment. This is achieved by installing the Python dependencies and setting the path to the ESPResSo build folder, as follows:
```sh
-python3 -m venv pymbe # creates a local folder named pymbe, which contains the virtual environment
-source pymbe/bin/activate # activates the pymbe venv
-python3 maintainer/configure_venv.py --espresso_path=/home/user/espresso/build # please, adapt the espresso path accordingly
-python3 -m pip install -r requirements.txt
-python3 simulation_script.py # run the espresso simulation script
+python3 -m venv pymbe # create a local folder named pymbe containing the environment files
+source pymbe/bin/activate # activate the virtual environment
+python3 -m pip install -r requirements.txt "numpy<2.0" "pandas<2.0"
+python3 maintainer/configure_venv.py --espresso_path=/home/user/espresso/build # please adapt the espresso path accordingly
+python3 simulation_script.py # run a simulation script
deactivate # deactivate the virtual environment
```
+NumPy 2 users should adapt the pip command as follows:
+
+```sh
+python3 -m pip install -r requirements.txt "numpy>=2.1" "pandas>=2.0"
+```
+
We highlight that the path `/home/user/espresso/build` is just an example of a possible path to the ESPResSo build folder.
-The user should change this path to match the local absolute path were ESPResSo was installed.
+The user should change this path to match the local absolute path where ESPResSo was built.
+Also, ESPResSo must be built with the same NumPy version as the one installed in the environment to avoid API version mismatch.
For more details on how to install ESPResSo, please consult the [ESPResSo installation guide](https://espressomd.github.io/doc4.2.2/installation.html).
-The pyMBE virtual enviroment can be deactivated at any moment:
+The pyMBE virtual environment can be deactivated at any moment as follows:
+
```sh
deactivate
```
@@ -85,7 +102,7 @@ Cluster users who rely on module files to load dependencies should opt for the
following alternative:
```sh
-module load ESPResSo/4.2.1-foss-2022a # adapt module name
+module load ESPResSo/4.2.2-foss-2023a # adapt release if needed
python3 -m venv --system-site-packages pymbe
source pymbe/bin/activate
python3 maintainer/configure_venv.py
@@ -94,7 +111,7 @@ deactivate
module purge
```
-We highlight that the module files need to be loaded before every activation
+Please note the module files need to be loaded before every activation
of the virtual environment.
Now you can use pyMBE and ESPResSo by activating the virtual environment:
@@ -108,11 +125,11 @@ $ source pymbe/bin/activate
$ deactivate
```
-To use pyMBE in JupyterLab, register the virtual environment in a new kernel:
+To use pyMBE in JupyterLab, install extra dependencies and register the virtual environment in a new kernel:
```sh
source pymbe/bin/activate
-python3 -m pip install ipykernel "jupyterlab>=4.0.8" "PyOpenGL>=3.1.5"
+python3 -m pip install ipykernel "jupyterlab>=4.0.8" "PyOpenGL>=3.1.5" "ipympl>=0.9.3"
python3 -m ipykernel install --user --name=pyMBE
deactivate
```
@@ -129,24 +146,30 @@ jupyter kernelspec uninstall pymbe
The JupyterLab main menu will now show a new Python kernel called "pyMBE"
that uses the virtual environment.
-### Use pyMBE in your simulation scripts
+### Run simulation scripts
+
+You can run the branched polyampholyte sample with the following commands:
```sh
source pymbe/bin/activate
-python3 samples/peptide.py
+python3 samples/branched_polyampholyte.py --pH 6
+python3 samples/analyze_time_series.py --data_folder samples/time_series/branched_polyampholyte
+python3 samples/plot_branched_polyampholyte.py
deactivate
```
-### Run the tutorial of pyMBE
+### Run tutorials
-You can run the interactive tutorial of pyMBE with the command:
+You can run the interactive tutorials with the following commands:
```sh
source pymbe/bin/activate
-jupyter-lab tutorials/pyMBE_tutorial.ipynb
+jupyter-lab
deactivate
```
+In the Jupyter interface, open the `tutorials` folder and then the `pyMBE_tutorial` file.
+It will guide you through the creation of polyelectrolytes with pyMBE.
Be sure to use the pyMBE kernel instead of the default Python3 kernel.
The currently active kernel is usually displayed in the top right corner of the notebook.
diff --git a/lib/analysis.py b/lib/analysis.py
index 1a34c7d..fa3009c 100644
--- a/lib/analysis.py
+++ b/lib/analysis.py
@@ -50,7 +50,7 @@ def analyze_time_series(path_to_datafolder, filename_extension= ".csv", minus_se
path_to_datafolder(`str`): path to the folder with the files with the time series
filename_extension(`str`): extension of the file. Defaults to ".csv"
minus_separator(`bool`): switch to enable the minus as a separator. Defaults to False.
- ignore_files(`lst`): list of filenames to be ignored for the bining analysis.
+ ignore_files(`lst`): list of filenames to be ignored for the binning analysis.
Returns:
data(`Pandas.Dataframe`): Dataframe with the time averages of all the time series in the datafolder.
@@ -113,7 +113,7 @@ def block_analyze(full_data, n_blocks=16, time_col = "time", equil=0.1, columns
print(f"Warning: looks like a repeated time value was encountered {n_warnings} times")
drop_rows = int(full_data.shape[0]*equil) # calculate how many rows should be dropped as equilibration
- # drop the rows that will be discarded as equlibration
+ # drop the rows that will be discarded as equilibration
data = full_data.drop(range(0,drop_rows))
# drop the columns step, time and MC sweep
if time_col in data.columns :
diff --git a/lib/handy_functions.py b/lib/handy_functions.py
index 83dfa66..b20e0a6 100644
--- a/lib/handy_functions.py
+++ b/lib/handy_functions.py
@@ -32,6 +32,7 @@ def setup_electrostatic_interactions (units, espresso_system, kT, c_salt=None, s
verbose (`bool`): switch to activate/deactivate verbose. Defaults to True.
"""
import espressomd.electrostatics
+ import espressomd.version
import numpy as np
import scipy.constants
@@ -71,12 +72,18 @@ def setup_electrostatic_interactions (units, espresso_system, kT, c_salt=None, s
if tune_p3m:
espresso_system.time_step=0.01
- espresso_system.actors.add(coulomb)
+ if espressomd.version.friendly() == "4.2":
+ espresso_system.actors.add(coulomb)
+ else:
+ espresso_system.electrostatics.solver = coulomb
# save the optimal parameters and add them by hand
p3m_params = coulomb.get_params()
- espresso_system.actors.remove(coulomb)
+ if espressomd.version.friendly() == "4.2":
+ espresso_system.actors.remove(coulomb)
+ else:
+ espresso_system.electrostatics.solver = None
coulomb = espressomd.electrostatics.P3M(
prefactor = COULOMB_PREFACTOR.magnitude,
accuracy = accuracy,
@@ -94,7 +101,10 @@ def setup_electrostatic_interactions (units, espresso_system, kT, c_salt=None, s
r_cut = KAPPA.to('reduced_length').magnitude)
- espresso_system.actors.add(coulomb)
+ if espressomd.version.friendly() == "4.2":
+ espresso_system.actors.add(coulomb)
+ else:
+ espresso_system.electrostatics.solver = coulomb
if verbose:
print("\n Electrostatics successfully added to the system \n")
@@ -211,3 +221,20 @@ def do_snapshot_espresso_system(espresso_system, filename):
visualizer.screenshot(filename)
return
+
+def get_number_of_particles(espresso_system, ptype):
+ import espressomd.version
+ if espressomd.version.friendly() == "4.2":
+ args = (ptype,)
+ kwargs = {}
+ else:
+ args = ()
+ kwargs = {"type": ptype}
+ return espresso_system.number_of_particles(*args, **kwargs)
+
+def do_reaction(algorithm, steps):
+ import espressomd.version
+ if espressomd.version.friendly() == '4.2':
+ algorithm.reaction(reaction_steps=steps)
+ else:
+ algorithm.reaction(steps=steps)
diff --git a/pyMBE.py b/pyMBE.py
index b1fcdcb..534c7dc 100644
--- a/pyMBE.py
+++ b/pyMBE.py
@@ -1006,7 +1006,7 @@ def create_particle(self, name, espresso_system, number_of_particles, position=N
created_pid_list(`list` of `float`): List with the ids of the particles created into `espresso_system`.
"""
if number_of_particles <=0:
- return 0
+ return []
self.check_if_name_is_defined_in_df(name=name,
pmb_type_to_be_defined='particle')
# Copy the data of the particle `number_of_particles` times in the `df`
@@ -1015,6 +1015,7 @@ def create_particle(self, name, espresso_system, number_of_particles, position=N
number_of_copies=number_of_particles)
# Get information from the particle type `name` from the df
z = self.df.loc[self.df['name']==name].state_one.z.values[0]
+ z = 0. if z is None else z
es_type = self.df.loc[self.df['name']==name].state_one.es_type.values[0]
# Get a list of the index in `df` corresponding to the new particles to be created
index = np.where(self.df['name']==name)
@@ -1033,11 +1034,10 @@ def create_particle(self, name, espresso_system, number_of_particles, position=N
else:
bead_id = max (espresso_system.part.all().id) + 1
created_pid_list.append(bead_id)
-
+ kwargs = dict(id=bead_id, pos=particle_position, type=es_type, q=z)
if fix:
- espresso_system.part.add (id=bead_id, pos = particle_position, type = es_type, q = z,fix =[fix,fix,fix])
- else:
- espresso_system.part.add (id=bead_id, pos = particle_position, type = es_type, q = z)
+ kwargs["fix"] = 3 * [fix]
+ espresso_system.part.add(**kwargs)
self.add_value_to_df(key=('particle_id',''),index=df_index,new_value=bead_id, verbose=False)
return created_pid_list
diff --git a/requirements.txt b/requirements.txt
index f07ecbb..4cb76e9 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,4 +1,4 @@
-numpy>=1.23,<2.0
+numpy>=1.23
pandas>=1.5.3
pint>=0.20.01
pint-pandas>=0.3
diff --git a/samples/Beyer2024/README.md b/samples/Beyer2024/README.md
index 1a78224..096dede 100644
--- a/samples/Beyer2024/README.md
+++ b/samples/Beyer2024/README.md
@@ -9,6 +9,6 @@ where the previous line will run the script to produce Fig. 7a in Ref.[^1] The u
- globular_protein.py: for the globular protein benchmarks
- weak_polyelectrolyte_dialysis.py: for the weak polyelectrolyte dialysis benchmarks
-The optional argparse argument `--plot` controls if these scripts generate the corresponding plot or if the data is simply stored to file. We note that the format of the plots can differ from that of our publication [^1]. Theses scripts are part of the continous integration (CI) scheme of the pyMBE library and they are used to ensure that any stable version of the library reproduces the benchmarks.
+The optional argparse argument `--plot` controls if these scripts generate the corresponding plot or if the data is simply stored to file. We note that the format of the plots can differ from that of our publication [^1]. Theses scripts are part of the continous integration (CI) pipeline to ensure that future pyMBE releases still reproduce the benchmarks.
-[^1]: D. Beyer, P. B. Torres, S. P. Pineda, C. F. Narambuena, J. N. Grad, P. Košovan, P. M Blanco. J. Chem. Phys.(2024), 161 (2), 022502. doi: [10.1063/5.0216389](https://doi.org/10.1063/5.0216389).
\ No newline at end of file
+[^1]: D. Beyer, P. B. Torres, S. P. Pineda, C. F. Narambuena, J.-N. Grad, P. Košovan, P. M. Blanco. J. Chem. Phys.(2024), 161 (2), 022502. doi: [10.1063/5.0216389](https://doi.org/10.1063/5.0216389).
diff --git a/samples/Beyer2024/globular_protein.py b/samples/Beyer2024/globular_protein.py
index 4e9a312..9a7aec7 100644
--- a/samples/Beyer2024/globular_protein.py
+++ b/samples/Beyer2024/globular_protein.py
@@ -17,7 +17,7 @@
# along with this program. If not, see .
from pathlib import Path
-from tqdm import tqdm
+import tqdm
import espressomd
import argparse
import numpy as np
@@ -31,6 +31,7 @@
from lib.handy_functions import setup_electrostatic_interactions
from lib.handy_functions import minimize_espresso_system_energy
from lib.handy_functions import setup_langevin_dynamics
+from lib.handy_functions import do_reaction
from lib import analysis
# Here you can adjust the width of the panda columns displayed when running the code
pd.options.display.max_colwidth = 10
@@ -38,8 +39,6 @@
#This line allows you to see the complete amount of rows in the dataframe
pd.set_option('display.max_rows', None)
-valid_modes=["short-run","long-run", "test"]
-
parser = argparse.ArgumentParser(description='Script to run globular protein simulation in espressomd')
parser.add_argument('--pdb',
@@ -67,7 +66,8 @@
parser.add_argument('--mode',
type=str,
default= "short-run",
- help='sets for how long the simulation runs, valid modes are {valid_modes}')
+ choices=["short-run","long-run", "test"],
+ help='sets for how long the simulation runs')
parser.add_argument('--output',
type=str,
@@ -141,7 +141,6 @@
exist_ok=True)
espresso_system = espressomd.System(box_l=[Box_L.to('reduced_length').magnitude] * 3)
-espresso_system.virtual_sites = espressomd.virtual_sites.VirtualSitesRelative()
#Reads the VTF file of the protein model
path_to_cg=pmb.get_resource(args.path_to_cg)
@@ -240,22 +239,22 @@
number_of_particles=N_ions,
position=added_salt_ions_coords[N_ions:])
-#Here we calculated the ionisible groups
+#Here we calculated the ionisable groups
basic_groups = pmb.df.loc[(~pmb.df['particle_id'].isna()) & (pmb.df['acidity']=='basic')].name.to_list()
acidic_groups = pmb.df.loc[(~pmb.df['particle_id'].isna()) & (pmb.df['acidity']=='acidic')].name.to_list()
-list_ionisible_groups = basic_groups + acidic_groups
-total_ionisible_groups = len (list_ionisible_groups)
+list_ionisable_groups = basic_groups + acidic_groups
+total_ionisable_groups = len (list_ionisable_groups)
if verbose:
- print('The box length of the system is', Box_L.to('reduced_length'), Box_L.to('nm'))
- print('The ionisable groups in the protein are ', list_ionisible_groups)
- print ('The total amount of ionizable groups are:',total_ionisible_groups)
+ print(f"The box length of the system is {Box_L.to('reduced_length')} {Box_L.to('nm')}")
+ print(f"The ionisable groups in the protein are {list_ionisable_groups}")
+ print(f"The total amount of ionisable groups is {total_ionisable_groups}")
#Setup of the reactions in espresso
cpH, labels = pmb.setup_cpH(counter_ion=cation_name,
constant_pH= pH_value)
if verbose:
- print('The acid-base reaction has been sucessfully setup for ', labels)
+ print(f"The acid-base reaction has been sucessfully setup for {labels}")
type_map = pmb.get_type_map()
types = list (type_map.values())
@@ -265,7 +264,7 @@
non_interacting_type = max(type_map.values())+1
cpH.set_non_interacting_type (type=non_interacting_type)
if verbose:
- print('The non interacting type is set to ', non_interacting_type)
+ print(f"The non interacting type is set to {non_interacting_type}")
#Save the initial state
n_frame = 0
@@ -320,9 +319,9 @@
net_charge_amino_save[label] = []
time_series[label] = []
-for step in tqdm(range(N_samples),disable=not verbose):
+for step in tqdm.trange(N_samples, disable=not verbose):
espresso_system.integrator.run (steps = integ_steps)
- cpH.reaction(reaction_steps = total_ionisible_groups)
+ do_reaction(cpH, steps=total_ionisable_groups)
charge_dict=pmb.calculate_net_charge (espresso_system=espresso_system,
molecule_name=protein_name,
dimensionless=True)
diff --git a/samples/Beyer2024/peptide.py b/samples/Beyer2024/peptide.py
index 1e8eb7a..01ba6b1 100644
--- a/samples/Beyer2024/peptide.py
+++ b/samples/Beyer2024/peptide.py
@@ -27,11 +27,11 @@
import pyMBE
from lib import analysis
from lib import handy_functions as hf
+from lib.handy_functions import do_reaction
# Create an instance of pyMBE library
pmb = pyMBE.pymbe_library(seed=42)
-valid_modes=["short-run","long-run", "test"]
parser = argparse.ArgumentParser(description='Script to run the peptide test cases for pyMBE')
parser.add_argument('--sequence',
type=str,
@@ -44,7 +44,8 @@
parser.add_argument('--mode',
type=str,
default= "short-run",
- help='sets for how long the simulation runs, valid modes are {valid_modes}')
+ choices=["short-run","long-run", "test"],
+ help='sets for how long the simulation runs')
parser.add_argument('--output',
type=str,
required= False,
@@ -60,8 +61,6 @@
mode=args.mode
verbose=args.no_verbose
-if mode not in valid_modes:
- raise ValueError(f"Mode {mode} is not currently supported, valid modes are {valid_modes}")
LANGEVIN_SEED = 100
dt = 0.01
@@ -218,7 +217,7 @@
# Run LD
espresso_system.integrator.run(steps=MD_steps_per_sample)
# Run MC
- cpH.reaction(reaction_steps=len(sequence))
+ do_reaction(cpH, steps=len(sequence))
# Sample observables
charge_dict=pmb.calculate_net_charge(espresso_system=espresso_system,
molecule_name=sequence,
@@ -234,7 +233,7 @@
data_path = args.output
if data_path is None:
- data_path=pmb.get_resource(path="samples/Beyer2024")+"/time_series/peptides"
+ data_path=pmb.get_resource(path="samples/Beyer2024") / "time_series" / "peptides"
Path(data_path).mkdir(parents=True,
exist_ok=True)
diff --git a/samples/Beyer2024/weak_polyelectrolyte_dialysis.py b/samples/Beyer2024/weak_polyelectrolyte_dialysis.py
index 54cc003..41849d0 100644
--- a/samples/Beyer2024/weak_polyelectrolyte_dialysis.py
+++ b/samples/Beyer2024/weak_polyelectrolyte_dialysis.py
@@ -25,7 +25,7 @@
from pathlib import Path
import numpy as np
import pandas as pd
-from tqdm import tqdm
+import tqdm
from scipy import interpolate
import argparse
@@ -36,10 +36,11 @@
# Create an instance of pyMBE library
pmb = pyMBE.pymbe_library(seed=42)
-# Load some functions from the handy_scripts library for convinience
+# Load some functions from the handy_scripts library for convenience
from lib.handy_functions import setup_electrostatic_interactions
from lib.handy_functions import minimize_espresso_system_energy
from lib.handy_functions import setup_langevin_dynamics
+from lib.handy_functions import do_reaction
#######################################################
@@ -194,9 +195,9 @@
tune_skin=False)
if verbose:
print("Running warmup without electrostatics")
-for i in tqdm(range(100),disable=not verbose):
+for i in tqdm.trange(100, disable=not verbose):
espresso_system.integrator.run(steps=1000)
- grxmc.reaction(reaction_steps=1000)
+ do_reaction(grxmc, steps=1000)
setup_electrostatic_interactions(units=pmb.units,
espresso_system=espresso_system,
@@ -216,9 +217,9 @@
N_warmup_loops = 1000
else:
N_warmup_loops = 100
-for i in tqdm(range(N_warmup_loops),disable=not verbose):
+for i in tqdm.trange(N_warmup_loops, disable=not verbose):
espresso_system.integrator.run(steps=1000)
- grxmc.reaction(reaction_steps=100)
+ do_reaction(grxmc, steps=100)
# Main loop
@@ -234,9 +235,9 @@
N_production_loops = 5000
else:
N_production_loops = 100
-for i in tqdm(range(N_production_loops),disable=not verbose):
+for i in tqdm.trange(N_production_loops, disable=not verbose):
espresso_system.integrator.run(steps=1000)
- grxmc.reaction(reaction_steps=100)
+ do_reaction(grxmc, steps=100)
# Measure time
time_series["time"].append(espresso_system.time)
diff --git a/samples/README.md b/samples/README.md
index d5fbcc2..8b0382f 100644
--- a/samples/README.md
+++ b/samples/README.md
@@ -2,9 +2,9 @@
## Production scripts
Production scripts show examples on how to setup various systems with pyMBE and ESPResSo.
-These scripts sample the systems for a specific set of conditions and take as argparse arguments various inputs for the simulations (for example, the pH of the solution).
-When run, the production script collect the time series of various quantities and store them in CSV files for later postprocessing.
-Such CSV files are systematically named using the input argparse arguments, allowing to backtrace from which specific system are the corresponding time series.
+These scripts sample the systems for a specific set of conditions and take as command-line arguments various inputs for the simulations (for example, the pH of the solution).
+When run, the production scripts collect the time series of various quantities and store them in CSV files for future postprocessing.
+Such CSV files are systematically named using the input arguments, allowing to backtrace from which specific system are the corresponding time series.
Examples of production scripts are: `branched_polyampholyte.py`, `peptide_cpH.py`, `peptide_mixture_grxmc_ideal.py` and `salt_solution_gcmc.py`.
## Analysis scripts
@@ -17,7 +17,7 @@ Examples of analysis scripts are: `analyze_time_series.py`.
Plotting scripts show examples on how to plot data post-processed with the analysis scripts of pyMBE and on how to use the toolbox of pyMBE to calculate various analytical solutions.
Examples of plotting scripts are: `plot_branched_polyampholyte.py`, `plot_peptide_cpH.py`, and `plot_peptide_mixture_grxmc_ideal.py`.
-[^1]: Janke, W. (2002). Statistical analysis of simulations: Data correlations and error estimation. Quantum simulations of complex many-body systems: from theory to algorithms, 10, 423-445.
+[^1]: Janke, W. (2002). Statistical analysis of simulations: Data correlations and error estimation. In: Quantum simulations of complex many-body systems: from theory to algorithms, NIC Series volume 10, pp. 423-445. isbn: 3-00-009057-6. URL:
## Example on how to use the pipeline
The sample scripts are designed to be used in the following order: (i) production script, (ii) analysis script and (iii) plotting script. For example:
diff --git a/samples/branched_polyampholyte.py b/samples/branched_polyampholyte.py
index 31929a0..57b3d92 100644
--- a/samples/branched_polyampholyte.py
+++ b/samples/branched_polyampholyte.py
@@ -20,12 +20,16 @@
from pathlib import Path
import espressomd
import argparse
+import tqdm
import pandas as pd
from espressomd.io.writer import vtf
import pyMBE
-# Load some functions from the handy_scripts library for convinience
-from lib.handy_functions import setup_langevin_dynamics,minimize_espresso_system_energy,setup_electrostatic_interactions
+# Load some functions from the handy_scripts library for convenience
+from lib.handy_functions import setup_langevin_dynamics
+from lib.handy_functions import minimize_espresso_system_energy
+from lib.handy_functions import setup_electrostatic_interactions
+from lib.handy_functions import do_reaction
from lib.analysis import built_output_name
# Create an instance of pyMBE library
@@ -47,7 +51,7 @@
default=False,
action='store_true',
help='to run a short simulation for testing the script')
-parser.add_argument('--no_verbose', action='store_false', help="Switch to deactivate verbose",default=True)
+parser.add_argument('--no_verbose', action='store_false', help="Switch to deactivate verbosity",default=True)
args = parser.parse_args()
# The trajectories of the simulations will be stored using espresso built-up functions in separed files in the folder 'frames'
@@ -152,7 +156,7 @@
# Add all bonds to espresso system
pmb.add_bonds_to_espresso(espresso_system=espresso_system)
-# Create your molecules icph_ideal_tests.pynto the espresso system
+# Create your molecules into the espresso system
pmb.create_pmb_object(name="polyampholyte",
number_of_objects=N_polyampholyte_chains,
espresso_system=espresso_system,
@@ -169,20 +173,20 @@
c_salt=c_salt,
verbose=verbose)
-#List of ionisible groups
+#List of ionisable groups
basic_groups = pmb.df.loc[(~pmb.df['particle_id'].isna()) & (pmb.df['acidity']=='basic')].name.to_list()
acidic_groups = pmb.df.loc[(~pmb.df['particle_id'].isna()) & (pmb.df['acidity']=='acidic')].name.to_list()
-list_ionisible_groups = basic_groups + acidic_groups
-total_ionisible_groups = len (list_ionisible_groups)
+list_ionisable_groups = basic_groups + acidic_groups
+total_ionisable_groups = len(list_ionisable_groups)
if verbose:
- print("The box length of your system is", L.to('reduced_length'), L.to('nm'))
- print('The polyampholyte concentration in your system is ', calculated_polyampholyte_concentration.to('mol/L') , 'with', N_polyampholyte_chains, 'molecules')
- print('The ionisable groups in your polyampholyte are ', list_ionisible_groups)
+ print(f"The box length of your system is {L.to('reduced_length')}, {L.to('nm')}")
+ print(f"The polyampholyte concentration in your system is {calculated_polyampholyte_concentration.to('mol/L')} with {N_polyampholyte_chains} molecules")
+ print(f"The ionisable groups in your polyampholyte are {list_ionisable_groups}")
cpH, labels = pmb.setup_cpH(counter_ion=cation_name, constant_pH=pH_value)
if verbose:
- print('The acid-base reaction has been sucessfully setup for ', labels)
+ print(f"The acid-base reaction has been successfully set up for {labels}")
# Setup espresso to track the ionization of the acid/basic groups
type_map = pmb.get_type_map()
@@ -193,7 +197,7 @@
non_interacting_type = max(type_map.values())+1
cpH.set_non_interacting_type (type=non_interacting_type)
if verbose:
- print('The non interacting type is set to ', non_interacting_type)
+ print(f"The non interacting type is set to {non_interacting_type}")
if not ideal:
##Setup the potential energy
@@ -234,10 +238,10 @@
# Production loop
N_frame=0
-for step in range(N_samples):
+for step in tqdm.trange(N_samples):
espresso_system.integrator.run(steps=MD_steps_per_sample)
- cpH.reaction( reaction_steps = total_ionisible_groups)
+ do_reaction(cpH, steps=total_ionisable_groups)
# Get polyampholyte net charge
diff --git a/samples/peptide_cpH.py b/samples/peptide_cpH.py
index bf054fd..023ebdf 100644
--- a/samples/peptide_cpH.py
+++ b/samples/peptide_cpH.py
@@ -19,7 +19,7 @@
# Load espresso, pyMBE and other necessary libraries
import espressomd
import pandas as pd
-from tqdm import tqdm
+import tqdm
from espressomd.io.writer import vtf
from pathlib import Path
import pyMBE
@@ -28,8 +28,11 @@
# Create an instance of pyMBE library
pmb = pyMBE.pymbe_library(seed=42)
-# Load some functions from the handy_scripts library for convinience
-from lib.handy_functions import setup_electrostatic_interactions, minimize_espresso_system_energy,setup_langevin_dynamics
+# Load some functions from the handy_scripts library for convenience
+from lib.handy_functions import setup_electrostatic_interactions
+from lib.handy_functions import minimize_espresso_system_energy
+from lib.handy_functions import setup_langevin_dynamics
+from lib.handy_functions import do_reaction
from lib.analysis import built_output_name
parser = argparse.ArgumentParser(description='Sample script to run the pre-made peptide models with pyMBE')
@@ -50,7 +53,7 @@
default=False,
action='store_true',
help='to run a short simulation for testing the script')
-parser.add_argument('--no_verbose', action='store_false', help="Switch to deactivate verbose",default=True)
+parser.add_argument('--no_verbose', action='store_false', help="Switch to deactivate verbosity",default=True)
args = parser.parse_args()
# The trajectories of the simulations will be stored using espresso built-up functions in separed files in the folder 'frames'
@@ -153,20 +156,20 @@
vtf.writevsf(espresso_system, coordinates)
vtf.writevcf(espresso_system, coordinates)
-#List of ionisible groups
+#List of ionisable groups
basic_groups = pmb.df.loc[(~pmb.df['particle_id'].isna()) & (pmb.df['acidity']=='basic')].name.to_list()
acidic_groups = pmb.df.loc[(~pmb.df['particle_id'].isna()) & (pmb.df['acidity']=='acidic')].name.to_list()
-list_ionisible_groups = basic_groups + acidic_groups
-total_ionisible_groups = len (list_ionisible_groups)
+list_ionisable_groups = basic_groups + acidic_groups
+total_ionisable_groups = len(list_ionisable_groups)
if verbose:
- print("The box length of your system is", L.to('reduced_length'), L.to('nm'))
- print('The peptide concentration in your system is ', calculated_peptide_concentration.to('mol/L') , 'with', N_peptide_chains, 'peptides')
- print('The ionisable groups in your peptide are ', list_ionisible_groups)
+ print(f"The box length of your system is {L.to('reduced_length')} {L.to('nm')}")
+ print(f"The peptide concentration in your system is {calculated_peptide_concentration.to('mol/L')} with {N_peptide_chains} peptides")
+ print(f"The ionisable groups in your peptide are {list_ionisable_groups}")
cpH, labels = pmb.setup_cpH(counter_ion=cation_name, constant_pH=pH_value)
if verbose:
- print('The acid-base reaction has been sucessfully setup for ', labels)
+ print(f"The acid-base reaction has been successfully setup for {labels}")
# Setup espresso to track the ionization of the acid/basic groups in peptide
type_map =pmb.get_type_map()
@@ -220,12 +223,12 @@
# Main loop for performing simulations at different pH-values
N_frame=0
-for sample in tqdm(range(N_samples)):
+for sample in tqdm.trange(N_samples):
# LD sampling of the configuration space
espresso_system.integrator.run(steps=MD_steps_per_sample)
# cpH sampling of the reaction space
- cpH.reaction( reaction_steps = total_ionisible_groups) # rule of thumb: one reaction step per titratable group (on average)
+ do_reaction(cpH, steps=total_ionisable_groups) # rule of thumb: one reaction step per titratable group (on average)
# Get peptide net charge
charge_dict=pmb.calculate_net_charge(espresso_system=espresso_system,
@@ -235,7 +238,7 @@
time_series["charge"].append(charge_dict["mean"])
if sample % N_samples_print == 0:
N_frame+=1
- with open('frames/trajectory'+str(N_frame)+'.vtf', mode='w+t') as coordinates:
+ with open(f'frames/trajectory{N_frame}.vtf', mode='w+t') as coordinates:
vtf.writevsf(espresso_system, coordinates)
vtf.writevcf(espresso_system, coordinates)
diff --git a/samples/peptide_mixture_grxmc_ideal.py b/samples/peptide_mixture_grxmc_ideal.py
index a00a762..d0871f8 100644
--- a/samples/peptide_mixture_grxmc_ideal.py
+++ b/samples/peptide_mixture_grxmc_ideal.py
@@ -24,18 +24,19 @@
from espressomd.io.writer import vtf
import pyMBE
from lib.analysis import built_output_name
+from lib.handy_functions import do_reaction
# Create an instance of pyMBE library
pmb = pyMBE.pymbe_library(seed=42)
# Command line arguments
-valid_modes=["standard", "unified"]
parser = argparse.ArgumentParser(description='Script that runs a simulation of an ideal peptide mixture in the grand-reaction ensemble using pyMBE and ESPResSo.')
parser.add_argument('--mode',
type=str,
default= "standard",
- help='Set if the grand-reaction method is used with unified ions or not, valid modes are {valid_modes}')
+ choices=["standard", "unified"],
+ help='Set if the grand-reaction method is used with unified ions or not')
parser.add_argument('--test',
default=False,
action='store_true',
@@ -60,9 +61,6 @@
parser.add_argument('--no_verbose', action='store_false', help="Switch to deactivate verbose",default=True)
args = parser.parse_args()
-if args.mode not in valid_modes:
- raise ValueError(f"Mode {args.mode} is not currently supported, valid modes are {valid_modes}")
-
# The trajectories of the simulations will be stored using espresso built-up functions in separed files in the folder 'frames'
Path("./frames").mkdir(parents=True,
exist_ok=True)
@@ -228,8 +226,8 @@
#List of ionisable groups
basic_groups = pmb.df.loc[(~pmb.df['particle_id'].isna()) & (pmb.df['acidity']=='basic')].name.to_list()
acidic_groups = pmb.df.loc[(~pmb.df['particle_id'].isna()) & (pmb.df['acidity']=='acidic')].name.to_list()
-list_ionisible_groups = basic_groups + acidic_groups
-total_ionisible_groups = len (list_ionisible_groups)
+list_ionisable_groups = basic_groups + acidic_groups
+total_ionisable_groups = len (list_ionisable_groups)
# Get peptide net charge
if verbose:
print("The box length of your system is", L.to('reduced_length'), L.to('nm'))
@@ -285,7 +283,7 @@
N_frame=0
for step in range(N_samples):
espresso_system.integrator.run(steps=MD_steps_per_sample)
- grxmc.reaction(reaction_steps = total_ionisible_groups)
+ do_reaction(grxmc, steps=total_ionisable_groups)
time_series["time"].append(espresso_system.time)
# Get net charge of peptide1 and peptide2
charge_dict_peptide1=pmb.calculate_net_charge(espresso_system=espresso_system,
diff --git a/samples/plot_branched_polyampholyte.py b/samples/plot_branched_polyampholyte.py
index 59e03e9..7a2c68e 100644
--- a/samples/plot_branched_polyampholyte.py
+++ b/samples/plot_branched_polyampholyte.py
@@ -41,13 +41,10 @@
type=str,
required= False,
default="plot",
- help='mode to execute the script available options are: store_HH (stores the analytical HH solution, used for testing) and plot (produces the plots)')
+ choices=["plot", "store_HH"],
+ help='mode to execute the script; available options are: store_HH (stores the analytical HH solution, used for testing) and plot (produces the plots)')
args = parser.parse_args()
-valid_modes = ["plot","store_HH"]
-if args.mode not in valid_modes:
- raise ValueError(f"mode {args.mode} is not supported, supported modes are {valid_modes}. Please check the docs for more information.")
-
# Define the molecule (necessary to calculate the HH analytical solution with pyMBE)
# Acidic particle
diff --git a/samples/plot_peptide_cpH.py b/samples/plot_peptide_cpH.py
index 2e7f8bc..db9004c 100644
--- a/samples/plot_peptide_cpH.py
+++ b/samples/plot_peptide_cpH.py
@@ -45,17 +45,14 @@
type=str,
required= False,
default="plot",
- help='mode to execute the script available options are: store_HH (stores the analytical HH solution, used for testing) and plot (produces the plots)')
+ choices=["plot", "store_HH"],
+ help='mode to execute the script; available options are: store_HH (stores the analytical HH solution, used for testing) and plot (produces the plots)')
args = parser.parse_args()
-valid_modes = ["plot","store_HH"]
-if args.mode not in valid_modes:
- raise ValueError(f"mode {args.mode} is not supported, supported modes are {valid_modes}. Please check the docs for more information.")
-
# Define peptide parameters
sequence = args.sequence
# Define the peptide in the pyMBE dataframe and load the pka set
-# This is necesary to calculate the analytical solution from the Henderson-Hasselbach equation
+# This is necessary to calculate the analytical solution from the Henderson-Hasselbach equation
peptide = 'generic_peptide'
pmb.define_peptide (name=peptide,
sequence=sequence,
diff --git a/samples/plot_peptide_mixture_grxmc_ideal.py b/samples/plot_peptide_mixture_grxmc_ideal.py
index 32222ea..6aff771 100644
--- a/samples/plot_peptide_mixture_grxmc_ideal.py
+++ b/samples/plot_peptide_mixture_grxmc_ideal.py
@@ -57,16 +57,14 @@
type=str,
required= False,
default="plot",
- help='mode to execute the script available options are: store_HH (stores the analytical HH solution, used for testing) and plot (produces the plots)')
+ choices=["plot", "store_HH"],
+ help='mode to execute the script; available options are: store_HH (stores the analytical HH solution, used for testing) and plot (produces the plots)')
args = parser.parse_args()
+
# Create an instance of pyMBE library
pmb = pyMBE.pymbe_library(seed=42)
c_salt=args.csalt * pmb.units.mol/ pmb.units.L
-valid_modes = ["plot","store_HH"]
-if args.mode not in valid_modes:
- raise ValueError(f"mode {args.mode} is not supported, supported modes are {valid_modes}. Please check the docs for more information.")
-
# Define peptide parameters
sequence1 = args.sequence1
pep1_concentration = args.pep1_conc *pmb.units.mol/pmb.units.L
diff --git a/samples/salt_solution_gcmc.py b/samples/salt_solution_gcmc.py
index 4247aaf..35ea2b4 100644
--- a/samples/salt_solution_gcmc.py
+++ b/samples/salt_solution_gcmc.py
@@ -23,7 +23,7 @@
import pandas as pd
from scipy import interpolate
import argparse
-from tqdm import tqdm
+import tqdm
# Import pyMBE
import pyMBE
@@ -38,10 +38,12 @@
parser = argparse.ArgumentParser(description='Script that runs a simulation of a salt solution in the grand-canonical ensemble using pyMBE and ESPResSo.')
parser.add_argument("--c_salt_res",
type=float,
+ required=True,
help="Concentration of salt in the reservoir in mol/l.")
parser.add_argument('--mode',
type=str,
default= "ideal",
+ choices=["ideal", "interacting"],
help='Set if an ideal or interacting system is simulated.')
parser.add_argument('--output',
type=str,
@@ -57,17 +59,14 @@
inputs={"csalt": args.c_salt_res,
"mode": args.mode}
-mode=args.mode
-valid_modes=["ideal", "interacting"]
verbose=args.no_verbose
-if args.mode not in valid_modes:
- raise ValueError(f"Mode {mode} is not currently supported, valid modes are {valid_modes}")
-
#Import functions from handy_functions script
from lib.handy_functions import minimize_espresso_system_energy
from lib.handy_functions import setup_electrostatic_interactions
from lib.handy_functions import setup_langevin_dynamics
+from lib.handy_functions import get_number_of_particles
+from lib.handy_functions import do_reaction
@@ -140,9 +139,9 @@
if verbose:
print("Running warmup without electrostatics")
-for i in tqdm(range(100),disable=not verbose):
+for i in tqdm.trange(100, disable=not verbose):
espresso_system.integrator.run(steps=100)
- RE.reaction(reaction_steps=100)
+ do_reaction(RE, steps=100)
if args.mode == "interacting":
setup_electrostatic_interactions(units=pmb.units,
@@ -162,9 +161,9 @@
print("Running warmup with electrostatics")
N_warmup_loops = 100
-for i in tqdm(range(N_warmup_loops),disable=not verbose):
+for i in tqdm.trange(N_warmup_loops, disable=not verbose):
espresso_system.integrator.run(steps=100)
- RE.reaction(reaction_steps=100)
+ do_reaction(RE, steps=100)
# Main loop
print("Started production run.")
@@ -176,15 +175,15 @@
time_series[label]=[]
N_production_loops = 100
-for i in tqdm(range(N_production_loops),disable=not verbose):
+for i in tqdm.trange(N_production_loops, disable=not verbose):
espresso_system.integrator.run(steps=100)
- RE.reaction(reaction_steps=100)
+ do_reaction(RE, steps=100)
# Measure time
time_series["time"].append(espresso_system.time)
# Measure degree of ionization
- number_of_ion_pairs = espresso_system.number_of_particles(type_map[cation_name])
+ number_of_ion_pairs = get_number_of_particles(espresso_system, type_map[cation_name])
time_series["c_salt"].append((number_of_ion_pairs/(volume * pmb.N_A)).magnitude)
data_path = args.output
diff --git a/testsuite/define_and_create_molecules_unit_tests.py b/testsuite/define_and_create_molecules_unit_tests.py
index 435309b..79060a0 100644
--- a/testsuite/define_and_create_molecules_unit_tests.py
+++ b/testsuite/define_and_create_molecules_unit_tests.py
@@ -125,11 +125,12 @@
# Create an instance of an espresso system
espresso_system=espressomd.System(box_l = [10]*3)
particle_positions=[[0,0,0],[1,1,1]]
-pmb.create_particle(name="S1",
- espresso_system=espresso_system,
- number_of_particles=2,
- fix=True,
- position=particle_positions)
+retval = pmb.create_particle(name="S1",
+ espresso_system=espresso_system,
+ number_of_particles=2,
+ fix=True,
+ position=particle_positions)
+np.testing.assert_array_equal(retval, [0, 1])
particle_ids=pmb.get_particle_id_map(object_name="S1")["all"]
type_map=pmb.get_type_map()
@@ -153,12 +154,11 @@
print("*** Unit test: check that create_particle() does not create any particle for number_of_particles <= 0 ***")
starting_number_of_particles=len(espresso_system.part.all())
-pmb.create_particle(name="S1",
- espresso_system=espresso_system,
- number_of_particles=0)
-pmb.create_particle(name="S1",
- espresso_system=espresso_system,
- number_of_particles=-1)
+for number_of_particles in [0, -1]:
+ retval = pmb.create_particle(name="S1",
+ espresso_system=espresso_system,
+ number_of_particles=number_of_particles)
+ np.testing.assert_equal(len(retval), 0)
# If no particles have been created, only two particles should be in the system (from the previous test)
np.testing.assert_equal(actual=len(espresso_system.part.all()),
desired=starting_number_of_particles,
diff --git a/testsuite/globular_protein_unit_tests.py b/testsuite/globular_protein_unit_tests.py
index 60b0bdf..8f83125 100644
--- a/testsuite/globular_protein_unit_tests.py
+++ b/testsuite/globular_protein_unit_tests.py
@@ -147,7 +147,6 @@ def custom_deserializer(dct):
print("*** Unit test: check that create_protein() creates all the particles in the protein into the espresso_system with the properties defined in pmb.df ***")
espresso_system=espressomd.System(box_l = [Box_L.to('reduced_length').magnitude] * 3)
-espresso_system.virtual_sites = espressomd.virtual_sites.VirtualSitesRelative()
# Here we upload the pka set from the reference_parameters folder
path_to_pka=pmb.get_resource('parameters/pka_sets/Nozaki1967.json')
diff --git a/testsuite/setup_salt_ions_unit_tests.py b/testsuite/setup_salt_ions_unit_tests.py
index 1e98282..d2e8eba 100644
--- a/testsuite/setup_salt_ions_unit_tests.py
+++ b/testsuite/setup_salt_ions_unit_tests.py
@@ -18,6 +18,7 @@
import numpy as np
import espressomd
+from lib.handy_functions import get_number_of_particles
# Create an instance of pyMBE library
import pyMBE
pmb = pyMBE.pymbe_library(seed=42)
@@ -41,22 +42,22 @@
# Create an instance of an espresso system
espresso_system=espressomd.System (box_l = [L.to('reduced_length').magnitude]*3)
-espresso_system.setup_type_map(type_map.values())
+espresso_system.setup_type_map(type_list=type_map.values())
#### Unit tests for the added salt
def check_salt_concentration(espresso_system,cation_name,anion_name,c_salt,N_SALT_ION_PAIRS, verbose=False):
charge_number_map=pmb.get_charge_number_map()
type_map=pmb.get_type_map()
- espresso_system.setup_type_map(type_map.values())
+ espresso_system.setup_type_map(type_list=type_map.values())
c_salt_calculated = pmb.create_added_salt(espresso_system=espresso_system,
cation_name=cation_name,
anion_name=anion_name,
c_salt=c_salt,
verbose=verbose)
- np.testing.assert_equal(espresso_system.number_of_particles(type_map[cation_name]),N_SALT_ION_PAIRS*abs(charge_number_map[type_map[anion_name]]))
- np.testing.assert_equal(espresso_system.number_of_particles(type_map[anion_name]),N_SALT_ION_PAIRS*abs(charge_number_map[type_map[cation_name]]))
+ np.testing.assert_equal(get_number_of_particles(espresso_system, type_map[cation_name]),N_SALT_ION_PAIRS*abs(charge_number_map[type_map[anion_name]]))
+ np.testing.assert_equal(get_number_of_particles(espresso_system, type_map[anion_name]),N_SALT_ION_PAIRS*abs(charge_number_map[type_map[cation_name]]))
np.testing.assert_almost_equal(c_salt_calculated.m_as("mol/L"), c_salt.m_as("mol/L"))
espresso_system.part.clear()
print("*** Unit test: test that create_added_salt works for a 1:1 salt (NaCl-like). Should print the added salt concentration and number of ions ***")
@@ -90,13 +91,13 @@ def check_salt_concentration(espresso_system,cation_name,anion_name,c_salt,N_SAL
print("*** Unit test passed***")
print("*** Unit test: check that create_added_salt works for an input c_salt in [particle/lenght**3]. Should print the concentration and number of ions")
c_salt_part=c_salt_input*pmb.N_A
-espresso_system.setup_type_map(type_map.values())
+espresso_system.setup_type_map(type_list=type_map.values())
c_salt_calculated = pmb.create_added_salt(espresso_system=espresso_system,
cation_name="Na",
anion_name="Cl",
c_salt=c_salt_part)
-np.testing.assert_equal(espresso_system.number_of_particles(type_map["Na"]),N_SALT_ION_PAIRS)
-np.testing.assert_equal(espresso_system.number_of_particles(type_map["Cl"]),N_SALT_ION_PAIRS)
+np.testing.assert_equal(get_number_of_particles(espresso_system, type_map["Na"]),N_SALT_ION_PAIRS)
+np.testing.assert_equal(get_number_of_particles(espresso_system, type_map["Cl"]),N_SALT_ION_PAIRS)
np.testing.assert_almost_equal(c_salt_calculated.m_as("reduced_length**-3"), c_salt_part.m_as("reduced_length**-3"))
espresso_system.part.clear()
@@ -181,9 +182,9 @@ def test_counterions(molecule_name, cation_name, anion_name, espresso_system, ex
anion_name=anion_name,
espresso_system=espresso_system,
verbose=verbose)
- espresso_system.setup_type_map(type_map.values())
- np.testing.assert_equal(espresso_system.number_of_particles(type_map[cation_name]),expected_numbers[cation_name])
- np.testing.assert_equal(espresso_system.number_of_particles(type_map[anion_name]),expected_numbers[anion_name])
+ espresso_system.setup_type_map(type_list=type_map.values())
+ np.testing.assert_equal(get_number_of_particles(espresso_system, type_map[cation_name]),expected_numbers[cation_name])
+ np.testing.assert_equal(get_number_of_particles(espresso_system, type_map[anion_name]),expected_numbers[anion_name])
pmb.destroy_pmb_object_in_system(espresso_system=espresso_system,
name=molecule_name)
espresso_system.part.clear()
@@ -276,7 +277,7 @@ def test_counterions(molecule_name, cation_name, anion_name, espresso_system, ex
anion_name="Cl",
espresso_system=espresso_system,
verbose=False)
-espresso_system.setup_type_map(type_map.values())
-np.testing.assert_equal(espresso_system.number_of_particles(type_map["Na"]),0)
-np.testing.assert_equal(espresso_system.number_of_particles(type_map["Cl"]),0)
+espresso_system.setup_type_map(type_list=type_map.values())
+np.testing.assert_equal(get_number_of_particles(espresso_system, type_map["Na"]),0)
+np.testing.assert_equal(get_number_of_particles(espresso_system, type_map["Cl"]),0)
print("*** Unit test passed ***")
diff --git a/tutorials/lattice_builder.ipynb b/tutorials/lattice_builder.ipynb
index 6acc6c2..1238153 100644
--- a/tutorials/lattice_builder.ipynb
+++ b/tutorials/lattice_builder.ipynb
@@ -7,13 +7,7 @@
"source": [
"# Lattice builder\n",
"\n",
- "Show the basic functionality of the lattice builder by creating a hydrogel network based on the diamond lattice.\n",
- "\n",
- "To run the 3D viewer in a Jupyter notebook, the following dependency is required:\n",
- "\n",
- "```sh\n",
- "python3 -m pip install \"ipympl>=0.9.3\"\n",
- "```"
+ "Show the basic functionality of the lattice builder by creating a hydrogel network based on the diamond lattice."
]
},
{
diff --git a/tutorials/pyMBE_tutorial.ipynb b/tutorials/pyMBE_tutorial.ipynb
index 465a23e..70d173f 100644
--- a/tutorials/pyMBE_tutorial.ipynb
+++ b/tutorials/pyMBE_tutorial.ipynb
@@ -53,7 +53,7 @@
"\n",
"# Only necesary to produce the pictures used in this tutorial\n",
"from lib.handy_functions import do_snapshot_espresso_system\n",
- "from PIL import Image\n"
+ "from PIL import Image"
]
},
{
@@ -284,6 +284,7 @@
"metadata": {},
"source": [
"pyMBE can be used to easily construct coarse-grained models of simple polymers. Let us consider a coarse grained model for polydehydroalanaline (PDha) (figure below) in which its monomeric unit can be represented by three beads, as depicted in the schematics below: a backbone bead (grey), a bead for the carboxylic acid group (red) and a bead for the amino group (blue).\n",
+ "\n",
"\n"
]
},
@@ -1167,7 +1168,7 @@
" model = model)\n",
"\n",
"print('one letter code', pmb.protein_sequence_parser(sequence=sequence))\n",
- "print('defined peptide sequence ', sequence)\n"
+ "print('defined peptide sequence ', sequence)"
]
},
{