Esempio n. 1
0
class RandomRotationTester(unittest.TestCase):
    """
    Test the RandomLigandRotationMove class.
    """
    def setUp(self):
        # Obtain topologies/positions
        prmtop = utils.get_data_filename('blues', 'tests/data/TOL-parm.prmtop')
        inpcrd = utils.get_data_filename('blues', 'tests/data/TOL-parm.inpcrd')
        structure = parmed.load_file(prmtop, xyz=inpcrd)

        self.atom_indices = utils.atomIndexfromTop('LIG', structure.topology)

        #Initialize the Move object
        self.move = RandomLigandRotationMove(structure, 'LIG', 3134)
        self.engine = MoveEngine(self.move)
        self.engine.selectMove()

        self.system_cfg = {
            'nonbondedMethod': app.NoCutoff,
            'constraints': app.HBonds
        }
        systems = SystemFactory(structure, self.move.atom_indices,
                                self.system_cfg)

        #Initialize the SimulationFactory object
        self.cfg = {
            'dt': 0.002 * unit.picoseconds,
            'friction': 1 * 1 / unit.picoseconds,
            'temperature': 300 * unit.kelvin,
            'nprop': 1,
            'nIter': 1,
            'nstepsMD': 1,
            'nstepsNC': 10,
            'alchemical_functions': {
                'lambda_sterics':
                'step(0.199999-lambda) + step(lambda-0.2)*step(0.8-lambda)*abs(lambda-0.5)*1/0.3 + step(lambda-0.800001)',
                'lambda_electrostatics':
                'step(0.2-lambda)- 1/0.2*lambda*step(0.2-lambda) + 1/0.2*(lambda-0.8)*step(lambda-0.8)'
            }
        }
        self.simulations = SimulationFactory(systems, self.engine, self.cfg)
        self.ncmc_sim = self.simulations.ncmc
        self.initial_positions = self.ncmc_sim.context.getState(
            getPositions=True).getPositions(asNumpy=True)

    def test_random_rotation(self):
        before_move = self.simulations.ncmc.context.getState(
            getPositions=True).getPositions(asNumpy=True)[self.atom_indices, :]
        self.simulations.ncmc.context = self.engine.runEngine(
            self.simulations.ncmc.context)
        after_move = self.simulations.ncmc.context.getState(
            getPositions=True).getPositions(asNumpy=True)[self.atom_indices, :]

        #Check that the ligand has been rotated
        pos_compare = np.not_equal(before_move, after_move).all()
        assert pos_compare
Esempio n. 2
0
class RandomRotationTester(unittest.TestCase):
    """
    Test the RandomLigandRotationMove class.
    """

    def setUp(self):
        # Obtain topologies/positions
        prmtop = utils.get_data_filename('blues', 'tests/data/TOL-parm.prmtop')
        inpcrd = utils.get_data_filename('blues', 'tests/data/TOL-parm.inpcrd')
        structure = parmed.load_file(prmtop, xyz=inpcrd)

        self.atom_indices = utils.atomIndexfromTop('LIG', structure.topology)

        #Initialize the Move object
        self.move = RandomLigandRotationMove(structure, 'LIG', 3134)
        self.engine = MoveEngine(self.move)
        self.engine.selectMove()

        self.system_cfg = {'nonbondedMethod': app.NoCutoff, 'constraints': app.HBonds}
        systems = SystemFactory(structure, self.move.atom_indices, self.system_cfg)

        #Initialize the SimulationFactory object
        self.cfg = {
            'dt': 0.002 * unit.picoseconds,
            'friction': 1 * 1 / unit.picoseconds,
            'temperature': 300 * unit.kelvin,
            'nprop': 1,
            'nIter': 1,
            'nstepsMD': 1,
            'nstepsNC': 10,
            'alchemical_functions': {
                'lambda_sterics':
                'step(0.199999-lambda) + step(lambda-0.2)*step(0.8-lambda)*abs(lambda-0.5)*1/0.3 + step(lambda-0.800001)',
                'lambda_electrostatics':
                'step(0.2-lambda)- 1/0.2*lambda*step(0.2-lambda) + 1/0.2*(lambda-0.8)*step(lambda-0.8)'
            }
        }
        self.simulations = SimulationFactory(systems, self.engine, self.cfg)
        self.ncmc_sim = self.simulations.ncmc
        self.initial_positions = self.ncmc_sim.context.getState(getPositions=True).getPositions(asNumpy=True)

    def test_random_rotation(self):
        before_move = self.simulations.ncmc.context.getState(getPositions=True).getPositions(
            asNumpy=True)[self.atom_indices, :]
        self.simulations.ncmc.context = self.engine.runEngine(self.simulations.ncmc.context)
        after_move = self.simulations.ncmc.context.getState(getPositions=True).getPositions(
            asNumpy=True)[self.atom_indices, :]

        #Check that the ligand has been rotated
        pos_compare = np.not_equal(before_move, after_move).all()
        assert pos_compare
Esempio n. 3
0
def sidechain_example(yaml_file):
    # Parse a YAML configuration, return as Dict
    cfg = Settings(yaml_file).asDict()
    structure = cfg['Structure']

    #Select move type
    sidechain = SideChainMove(structure, [1])
    #Iniitialize object that selects movestep
    sidechain_mover = MoveEngine(sidechain)

    #Generate the openmm.Systems outside SimulationFactory to allow modifications
    systems = SystemFactory(structure, sidechain.atom_indices, cfg['system'])

    #Generate the OpenMM Simulations
    simulations = SimulationFactory(systems, sidechain_mover, cfg['simulation'], cfg['md_reporters'],
                                    cfg['ncmc_reporters'])

    # Run BLUES Simulation
    blues = BLUESSimulation(simulations, cfg['simulation'])
    blues.run()

    #Analysis
    import mdtraj as md
    import numpy as np

    traj = md.load_netcdf('vacDivaline-test/vacDivaline.nc', top='tests/data/vacDivaline.prmtop')
    indicies = np.array([[0, 4, 6, 8]])
    dihedraldata = md.compute_dihedrals(traj, indicies)
    with open("vacDivaline-test/dihedrals.txt", 'w') as output:
        for value in dihedraldata:
            output.write("%s\n" % str(value)[1:-1])
Esempio n. 4
0
    def setUp(self):
        # Obtain topologies/positions
        prmtop = utils.get_data_filename('blues',
                                         'tests/data/eqToluene.prmtop')
        inpcrd = utils.get_data_filename('blues', 'tests/data/eqToluene.pdb')
        structure = parmed.load_file(prmtop, xyz=inpcrd)

        #Initialize the Move object
        self.move = WaterTranslationMove(
            structure,
            protein_selection='(index 1656) or (index 1657)',
            radius=0.9 * unit.nanometer)
        self.atom_indices = self.move.atom_indices

        self.engine = MoveEngine(self.move)
        self.engine.selectMove()

        self.system_cfg = {
            'nonbondedMethod': app.NoCutoff,
            'constraints': app.HBonds
        }
        systems = SystemFactory(structure, self.move.atom_indices,
                                self.system_cfg)

        #Initialize the SimulationFactory object
        self.cfg = {
            'dt': 0.002 * unit.picoseconds,
            'friction': 1 * 1 / unit.picoseconds,
            'temperature': 300 * unit.kelvin,
            'nprop': 1,
            'nIter': 1,
            'nstepsMD': 1,
            'nstepsNC': 100,
            'alchemical_functions': {
                'lambda_sterics':
                'step(0.199999-lambda) + step(lambda-0.2)*step(0.8-lambda)*abs(lambda-0.5)*1/0.3 + step(lambda-0.800001)',
                'lambda_electrostatics':
                'step(0.2-lambda)- 1/0.2*lambda*step(0.2-lambda) + 1/0.2*(lambda-0.8)*step(lambda-0.8)'
            }
        }
        self.simulations = SimulationFactory(systems, self.engine, self.cfg)
        self.ncmc_sim = self.simulations.ncmc
        self.initial_positions = self.ncmc_sim.context.getState(
            getPositions=True).getPositions(asNumpy=True)
Esempio n. 5
0
    def setUp(self):
        # Obtain topologies/positions
        prmtop = utils.get_data_filename('blues',
                                         'tests/data/vacDivaline.prmtop')
        inpcrd = utils.get_data_filename('blues',
                                         'tests/data/vacDivaline.inpcrd')
        self.struct = parmed.load_file(prmtop, xyz=inpcrd)

        self.sidechain = SideChainMove(self.struct, [1])
        self.engine = MoveEngine(self.sidechain)
        self.engine.selectMove()

        self.system_cfg = {
            'nonbondedMethod': app.NoCutoff,
            'constraints': app.HBonds
        }
        self.systems = SystemFactory(self.struct, self.sidechain.atom_indices,
                                     self.system_cfg)

        self.cfg = {
            'dt': 0.002 * unit.picoseconds,
            'friction': 1 * 1 / unit.picoseconds,
            'temperature': 300 * unit.kelvin,
            'nIter': 1,
            'nstepsMD': 1,
            'nstepsNC': 4,
            'alchemical_functions': {
                'lambda_sterics':
                'step(0.199999-lambda) + step(lambda-0.2)*step(0.8-lambda)*abs(lambda-0.5)*1/0.3 + step(lambda-0.800001)',
                'lambda_electrostatics':
                'step(0.2-lambda)- 1/0.2*lambda*step(0.2-lambda) + 1/0.2*(lambda-0.8)*step(lambda-0.8)'
            }
        }

        self.simulations = SimulationFactory(self.systems, self.engine,
                                             self.cfg)
Esempio n. 6
0
def ligrot_example(yaml_file):
    # Parse a YAML configuration, return as Dict
    cfg = Settings(yaml_file).asDict()
    structure = cfg['Structure']

    #Select move type
    ligand = RandomLigandRotationMove(structure, 'LIG')
    #Iniitialize object that selects movestep
    ligand_mover = MoveEngine(ligand)

    #Generate the openmm.Systems outside SimulationFactory to allow modifications
    systems = SystemFactory(structure, ligand.atom_indices, cfg['system'])

    #Freeze atoms in the alchemical system to speed up alchemical calculation
    systems.alch = systems.freeze_radius(structure, systems.alch, **cfg['freeze'])

    #Generate the OpenMM Simulations
    simulations = SimulationFactory(systems, ligand_mover, cfg['simulation'], cfg['md_reporters'],
                                    cfg['ncmc_reporters'])

    # Run BLUES Simulation
    blues = BLUESSimulation(simulations, cfg['simulation'])
    blues.run()
Esempio n. 7
0
def runEthyleneTest(N):
    filename = 'ethylene-test_%s' % N
    print('Running %s...' % filename)
    seed = np.random.randint(low=1, high=5000)
    #print('Seed', seed)
    # filename = 'ethylene-test_%s' % N
    # print(filename)

    # Set Simulation parameters
    sim_cfg = {
        'platform': 'CPU',
        'nprop': 1,
        'propLambda': 0.3,
        'dt': 1 * unit.femtoseconds,
        'friction': 1 / unit.picoseconds,
        'temperature': 200 * unit.kelvin,
        'nIter': 100,
        'nstepsMD': 20,
        'nstepsNC': 20,
        'propSteps': 20,
        'moveStep': 10
    }

    totalSteps = int(sim_cfg['nIter'] * sim_cfg['nstepsMD'])
    reportInterval = 5
    alchemical_atoms = [2, 3, 4, 5, 6, 7]
    alchemical_functions = {
        'lambda_sterics':
        'min(1, (1/0.3)*abs(lambda-0.5))',
        'lambda_electrostatics':
        'step(0.2-lambda) - 1/0.2*lambda*step(0.2-lambda) + 1/0.2*(lambda-0.8)*step(lambda-0.8)'
    }

    md_reporters = {'traj_netcdf': {'reportInterval': reportInterval}}

    # Load a Parmed Structure for the Topology and create our openmm.Simulation
    structure_pdb = utils.get_data_filename(
        'blues', 'tests/data/ethylene_structure.pdb')
    structure = parmed.load_file(structure_pdb)

    # Initialize our move proposal class
    rot_move = RandomLigandRotationMove(structure, 'LIG')
    mover = MoveEngine(rot_move)

    # Load our OpenMM System and create Integrator
    system_xml = utils.get_data_filename('blues',
                                         'tests/data/ethylene_system.xml')
    with open(system_xml, 'r') as infile:
        xml = infile.read()
        system = openmm.XmlSerializer.deserialize(xml)
    integrator = openmm.LangevinIntegrator(sim_cfg['temperature'],
                                           sim_cfg['friction'], sim_cfg['dt'])
    integrator.setRandomNumberSeed(seed)

    alch_integrator = openmm.LangevinIntegrator(sim_cfg['temperature'],
                                                sim_cfg['friction'],
                                                sim_cfg['dt'])
    alch_integrator.setRandomNumberSeed(seed)

    alch_system = SystemFactory.generateAlchSystem(system, alchemical_atoms)
    ncmc_integrator = AlchemicalExternalLangevinIntegrator(
        nsteps_neq=sim_cfg['nstepsNC'],
        alchemical_functions=alchemical_functions,
        splitting="H V R O R V H",
        temperature=sim_cfg['temperature'],
        timestep=sim_cfg['dt'])
    # ncmc_integrator.setRandomNumberSeed(seed)

    # Pack our systems into a single object
    systems = SystemFactory(structure, alchemical_atoms)
    systems.md = system
    systems.alch = alch_system

    # Make our reporters
    md_reporter_cfg = ReporterConfig(filename, md_reporters)
    md_reporters_list = md_reporter_cfg.makeReporters()

    # Pack our simulations into a single object
    simulations = SimulationFactory(systems, mover)

    simulations.md = SimulationFactory.generateSimFromStruct(
        structure, system, integrator, 'CPU')
    simulations.md = SimulationFactory.attachReporters(simulations.md,
                                                       md_reporters_list)

    simulations.alch = SimulationFactory.generateSimFromStruct(
        structure, system, alch_integrator, 'CPU')

    simulations.ncmc = SimulationFactory.generateSimFromStruct(
        structure, alch_system, ncmc_integrator, 'CPU')

    ethylene_sim = BLUESSimulation(simulations, sim_cfg)
    ethylene_sim.run()
Esempio n. 8
0
from blues.moves import MoveEngine
from blues.simulation import *
import json
from blues.settings import *
from blues.simulation import *
import json
from blues.settings import *

# Parse a YAML configuration, return as Dict
cfg = Settings('sidechain_cudayaml').asDict()
structure = cfg['Structure']

#Select move type
sidechain = SideChainMove(structure, [1])
#Iniitialize object that selects movestep
sidechain_mover = MoveEngine(sidechain)

#Generate the openmm.Systems outside SimulationFactory to allow modifications
systems = SystemFactory(structure, sidechain.atom_indices, cfg['system'])

#Generate the OpenMM Simulations
simulations = SimulationFactory(systems, sidechain_mover, cfg['simulation'],
                                cfg['md_reporters'], cfg['ncmc_reporters'])

# Run BLUES Simulation
blues = BLUESSimulation(simulations, cfg['simulation'])
blues.run()

#Analysis
import mdtraj as md
import numpy as np
Esempio n. 9
0
import json
from blues.settings import Settings

# Parse a YAML configuration, return as Dict
opt = Settings('water_cuda.yaml').asDict()
structure = opt['Structure']
print(json.dumps(opt, sort_keys=True, indent=2, skipkeys=True, default=str))

# Select move type
water = WaterTranslationMove(structure,
                             water_name='WAT',
                             protein_selection='index 9',
                             radius=2 * unit.nanometers)

# Initialize object that selects movestep
water_mover = MoveEngine(water)

#Generate the openmm.Systems outside SimulationFactory to allow modifications
systems = SystemFactory(structure, water.atom_indices, opt['system'])

# Restrain atoms in the MD and alchemical system
systems.md = systems.restrain_positions(structure, systems.md,
                                        **opt['restraints'])
systems.alch = systems.restrain_positions(structure, systems.alch,
                                          **opt['restraints'])

# Generate the OpenMM Simulations
simulations = SimulationFactory(systems, water_mover, opt['simulation'],
                                opt['md_reporters'], opt['ncmc_reporters'])

blues = BLUESSimulation(simulations, opt['simulation'])
Esempio n. 10
0
from blues.simulation import *
import json
from blues.settings import Settings

opt = Settings('example.yaml').asDict()
structure = opt['Structure']
#restart = parmed.amber.Rst7('NPT_MD.rst7')
#structure.positions = restart.positions
#structure.box = restart.box
print(json.dumps(opt, sort_keys=True, indent=2, skipkeys=True, default=str))

#Select move type
ligand = WaterTranslationMove(structure, water_name='WAT')

#Iniitialize object that selects movestep
ligand_mover = MoveEngine(ligand)

#Generate the openmm.Systems outside SimulationFactory to allow modifications
systems = SystemFactory(structure, ligand.atom_indices, opt['system'])

# Uncomment this section freeze atoms in the system
# Used for MD or BLUES production runs of the C60 buckyball and the water box with dividing graphene sheets
#systems.md = systems.freeze_atoms(structure, systems.md, **opt['freeze'])
#systems.alch = systems.freeze_atoms(structure, systems.alch, **opt['freeze'])

# Uncomment this section to restrain atoms in the MD and alchemical system
# Used for MD and BLUES production runs of MUP-1 and HSP90 protein-ligand systems to restrain all of the alpha carbons and the ligands
#systems.md = systems.restrain_positions(structure, systems.md, **opt['restraints'])
#systems.alch = systems.restrain_positions(structure, systems.alch, **opt['restraints'])

#Generate the OpenMM Simulations
Esempio n. 11
0
class WaterTranslationTester(unittest.TestCase):
    """
    Test the RandomLigandRotationMove class.
    """
    def setUp(self):
        # Obtain topologies/positions
        prmtop = utils.get_data_filename('blues',
                                         'tests/data/eqToluene.prmtop')
        inpcrd = utils.get_data_filename('blues', 'tests/data/eqToluene.pdb')
        structure = parmed.load_file(prmtop, xyz=inpcrd)

        #Initialize the Move object
        self.move = WaterTranslationMove(
            structure,
            protein_selection='(index 1656) or (index 1657)',
            radius=0.9 * unit.nanometer)
        self.atom_indices = self.move.atom_indices

        self.engine = MoveEngine(self.move)
        self.engine.selectMove()

        self.system_cfg = {
            'nonbondedMethod': app.NoCutoff,
            'constraints': app.HBonds
        }
        systems = SystemFactory(structure, self.move.atom_indices,
                                self.system_cfg)

        #Initialize the SimulationFactory object
        self.cfg = {
            'dt': 0.002 * unit.picoseconds,
            'friction': 1 * 1 / unit.picoseconds,
            'temperature': 300 * unit.kelvin,
            'nprop': 1,
            'nIter': 1,
            'nstepsMD': 1,
            'nstepsNC': 100,
            'alchemical_functions': {
                'lambda_sterics':
                'step(0.199999-lambda) + step(lambda-0.2)*step(0.8-lambda)*abs(lambda-0.5)*1/0.3 + step(lambda-0.800001)',
                'lambda_electrostatics':
                'step(0.2-lambda)- 1/0.2*lambda*step(0.2-lambda) + 1/0.2*(lambda-0.8)*step(lambda-0.8)'
            }
        }
        self.simulations = SimulationFactory(systems, self.engine, self.cfg)
        self.ncmc_sim = self.simulations.ncmc
        self.initial_positions = self.ncmc_sim.context.getState(
            getPositions=True).getPositions(asNumpy=True)

    def test_water_translation_before(self):
        self.original_com_position = self.move.traj.xyz[0][
            self.move.protein_atoms[0]]

        before_move = self.simulations.ncmc.context.getState(
            getPositions=True).getPositions(asNumpy=True)[self.atom_indices, :]
        #new_context = self.engine.runEngine(self.simulations.ncmc.context)
        new_context = self.move.beforeMove(self.simulations.ncmc.context)
        after_move = new_context.getState(getPositions=True).getPositions(
            asNumpy=True)[self.atom_indices, :]

        #Check that the ligand has been rotated
        pos_compare = np.not_equal(before_move, after_move).all()
        self.move.traj.xyz[0][
            self.move.protein_atoms[0]] = self.original_com_position
        assert pos_compare

    def test_water_translation_move(self):
        #before_move = self.simulations.ncmc.context.getState(getPositions=True).getPositions(
        #    asNumpy=True)[self.atom_indices, :]
        self.original_com_position = self.ncmc_sim.context.getState(
            getPositions=True).getPositions(
                asNumpy=True)[self.move.protein_atoms[0]]

        com_protein_before = self.move.traj.xyz[0,
                                                self.move.protein_atoms[0], :]
        self.simulations.ncmc.context = self.move.beforeMove(
            self.simulations.ncmc.context)
        before_move = self.simulations.ncmc.context.getState(
            getPositions=True).getPositions(asNumpy=True)[self.atom_indices, :]
        self.simulations.ncmc.context = self.engine.runEngine(
            self.simulations.ncmc.context)
        after_move = self.simulations.ncmc.context.getState(
            getPositions=True).getPositions(asNumpy=True)[self.atom_indices, :]
        #Check that the ligand has been rotated
        pos_compare = np.not_equal(before_move, after_move).all()
        assert pos_compare

        #check distance
        com_protein_after = self.move.traj.xyz[0,
                                               self.move.protein_atoms[0], :]
        #check that the center of mass refereence has changed
        assert np.not_equal(self.original_com_position,
                            com_protein_after).all()

        #check that the new water position is within the specified radius
        pairs = self.move.traj.topology.select_pairs(
            np.array(self.move.atom_indices[0]).flatten(),
            np.array(self.move.protein_atoms[0]).flatten())
        water_distance = md.compute_distances(self.move.traj,
                                              pairs,
                                              periodic=True)
        water_dist = np.linalg.norm(water_distance)
        assert np.less_equal(water_dist, self.move.radius._value)
        self.move.traj.xyz[0][
            self.move.protein_atoms[0]] = self.original_com_position

    def test_water_translation_after(self):
        before_move = self.simulations.ncmc.context.getState(
            getPositions=True).getPositions(asNumpy=True)[self.atom_indices, :]
        self.simulations.ncmc.context = self.engine.runEngine(
            self.simulations.ncmc.context)
        new_context = self.move.beforeMove(self.simulations.ncmc.context)
        new_context = self.move.move(self.simulations.ncmc.context)
        after_move = self.simulations.ncmc.context.getState(
            getPositions=True).getPositions(asNumpy=True)
        #Check that the move treats inbound water correctly
        assert self.simulations.ncmc.context._integrator.getGlobalVariableByName(
            'protocol_work') == 0
        after_move[self.move.atom_indices] = after_move[
            self.move.atom_indices] + [self.move.radius._value, 0, 0
                                       ] * self.move.radius.unit

        self.simulations.ncmc.context.setPositions(after_move)
        new_context = self.move.afterMove(self.simulations.ncmc.context)
        #Check that the move would be rejected in case it's out of bounds
        assert self.simulations.ncmc.context._integrator.getGlobalVariableByName(
            'protocol_work') >= 999999
Esempio n. 12
0
def engine(move):
    engine = MoveEngine(move)
    return engine
Esempio n. 13
0
class SideChainTester(unittest.TestCase):
    """
    Test the SmartDartMove.move() function.
    """
    def setUp(self):
        # Obtain topologies/positions
        prmtop = utils.get_data_filename('blues',
                                         'tests/data/vacDivaline.prmtop')
        inpcrd = utils.get_data_filename('blues',
                                         'tests/data/vacDivaline.inpcrd')
        self.struct = parmed.load_file(prmtop, xyz=inpcrd)

        self.sidechain = SideChainMove(self.struct, [1])
        self.engine = MoveEngine(self.sidechain)
        self.engine.selectMove()

        self.system_cfg = {
            'nonbondedMethod': app.NoCutoff,
            'constraints': app.HBonds
        }
        self.systems = SystemFactory(self.struct, self.sidechain.atom_indices,
                                     self.system_cfg)

        self.cfg = {
            'dt': 0.002 * unit.picoseconds,
            'friction': 1 * 1 / unit.picoseconds,
            'temperature': 300 * unit.kelvin,
            'nIter': 1,
            'nstepsMD': 1,
            'nstepsNC': 4,
            'alchemical_functions': {
                'lambda_sterics':
                'step(0.199999-lambda) + step(lambda-0.2)*step(0.8-lambda)*abs(lambda-0.5)*1/0.3 + step(lambda-0.800001)',
                'lambda_electrostatics':
                'step(0.2-lambda)- 1/0.2*lambda*step(0.2-lambda) + 1/0.2*(lambda-0.8)*step(lambda-0.8)'
            }
        }

        self.simulations = SimulationFactory(self.systems, self.engine,
                                             self.cfg)

    def test_getRotBondAtoms(self):
        vals = [v for v in self.sidechain.rot_atoms[1].values()][0]
        assert len(vals) == 11
        #Ensure it selects 1 rotatable bond in Valine
        assert len(self.sidechain.rot_bonds) == 1

    def test_sidechain_move(self):
        atom_indices = [v for v in self.sidechain.rot_atoms[1].values()][0]
        before_move = self.simulations.ncmc.context.getState(
            getPositions=True).getPositions(asNumpy=True)[atom_indices, :]
        self.simulations.ncmc.context = self.engine.runEngine(
            self.simulations.ncmc.context)
        after_move = self.simulations.ncmc.context.getState(
            getPositions=True).getPositions(asNumpy=True)[atom_indices, :]

        #Check that our system has run dynamics
        # Integrator must step for context to update positions
        # Remove the first two atoms in check as these are the anchor atoms and are not rotated.
        pos_compare = np.not_equal(before_move, after_move)[2:, :].all()
        assert pos_compare