예제 #1
0
    def testComputePBCVectors(self):
        """ Tests computing periodic box vectors """
        deg90 = 90 * degrees
        vecs = computePeriodicBoxVectors(1, 2, 3, deg90, deg90, deg90)
        a, b, c = vecs
        self.assertAlmostEqual(a[0] / nanometers, 1)
        self.assertAlmostEqual(a[1] / nanometers, 0)
        self.assertAlmostEqual(a[2] / nanometers, 0)
        self.assertAlmostEqual(b[0] / nanometers, 0)
        self.assertAlmostEqual(b[1] / nanometers, 2)
        self.assertAlmostEqual(b[2] / nanometers, 0)
        self.assertAlmostEqual(c[0] / nanometers, 0)
        self.assertAlmostEqual(c[1] / nanometers, 0)
        self.assertAlmostEqual(c[2] / nanometers, 3)

        # Make sure round-trip works
        la, lb, lc, al, be, ga = computeLengthsAndAngles(vecs)
        self.assertAlmostEqual(la, 1)
        self.assertAlmostEqual(lb, 2)
        self.assertAlmostEqual(lc, 3)
        self.assertAlmostEqual(al, math.pi / 2)
        self.assertAlmostEqual(be, math.pi / 2)
        self.assertAlmostEqual(ga, math.pi / 2)

        # Now test a truncated octahedron. Can't do a simple round-trip though,
        # due to the reduced form. So test the *second* round-trip, which should
        # yield the same measurements
        vecs = computePeriodicBoxVectors(4.24388485, 4.24388485, 4.24388485,
                                         109.4712190 * degrees,
                                         109.4712190 * degrees,
                                         109.4712190 * degrees)
        la, lb, lc, al, be, ga = computeLengthsAndAngles(vecs)
        vecs2 = computePeriodicBoxVectors(la, lb, lc, al, be, ga)
        la2, lb2, lc2, al2, be2, ga2 = computeLengthsAndAngles(vecs2)

        # Now make sure that the round-trip worked
        self.assertAlmostEqual(strip_units(la), strip_units(la2))
        self.assertAlmostEqual(strip_units(lb), strip_units(lb2))
        self.assertAlmostEqual(strip_units(lc), strip_units(lc2))
        self.assertAlmostEqual(strip_units(al), strip_units(al2))
        self.assertAlmostEqual(strip_units(be), strip_units(be2))
        self.assertAlmostEqual(strip_units(ga), strip_units(ga2))

        # Check that the vectors are the same
        a1, a2, a3 = vecs
        b1, b2, b3 = vecs2
        for x, y in zip(a1, b1):
            self.assertAlmostEqual(strip_units(x), strip_units(y))
        for x, y in zip(a2, b2):
            self.assertAlmostEqual(strip_units(x), strip_units(y))
        for x, y in zip(a3, b3):
            self.assertAlmostEqual(strip_units(x), strip_units(y))
예제 #2
0
    def testComputePBCVectors(self):
        """ Tests computing periodic box vectors """
        deg90 = 90 * degrees
        vecs = computePeriodicBoxVectors(1, 2, 3, deg90, deg90, deg90)
        a, b, c = vecs
        self.assertAlmostEqual(a[0]/nanometers, 1)
        self.assertAlmostEqual(a[1]/nanometers, 0)
        self.assertAlmostEqual(a[2]/nanometers, 0)
        self.assertAlmostEqual(b[0]/nanometers, 0)
        self.assertAlmostEqual(b[1]/nanometers, 2)
        self.assertAlmostEqual(b[2]/nanometers, 0)
        self.assertAlmostEqual(c[0]/nanometers, 0)
        self.assertAlmostEqual(c[1]/nanometers, 0)
        self.assertAlmostEqual(c[2]/nanometers, 3)

        # Make sure round-trip works
        la, lb, lc, al, be, ga = computeLengthsAndAngles(vecs)
        self.assertAlmostEqual(la, 1)
        self.assertAlmostEqual(lb, 2)
        self.assertAlmostEqual(lc, 3)
        self.assertAlmostEqual(al, math.pi / 2)
        self.assertAlmostEqual(be, math.pi / 2)
        self.assertAlmostEqual(ga, math.pi / 2)

        # Now test a truncated octahedron. Can't do a simple round-trip though,
        # due to the reduced form. So test the *second* round-trip, which should
        # yield the same measurements
        vecs = computePeriodicBoxVectors(4.24388485, 4.24388485, 4.24388485,
                109.4712190*degrees, 109.4712190*degrees, 109.4712190*degrees)
        la, lb, lc, al, be, ga = computeLengthsAndAngles(vecs)
        vecs2 = computePeriodicBoxVectors(la, lb, lc, al, be, ga)
        la2, lb2, lc2, al2, be2, ga2 = computeLengthsAndAngles(vecs2)

        # Now make sure that the round-trip worked
        self.assertAlmostEqual(strip_units(la), strip_units(la2))
        self.assertAlmostEqual(strip_units(lb), strip_units(lb2))
        self.assertAlmostEqual(strip_units(lc), strip_units(lc2))
        self.assertAlmostEqual(strip_units(al), strip_units(al2))
        self.assertAlmostEqual(strip_units(be), strip_units(be2))
        self.assertAlmostEqual(strip_units(ga), strip_units(ga2))

        # Check that the vectors are the same
        a1, a2, a3 = vecs
        b1, b2, b3 = vecs2
        for x, y in zip(a1, b1):
            self.assertAlmostEqual(strip_units(x), strip_units(y))
        for x, y in zip(a2, b2):
            self.assertAlmostEqual(strip_units(x), strip_units(y))
        for x, y in zip(a3, b3):
            self.assertAlmostEqual(strip_units(x), strip_units(y))
예제 #3
0
    def testReducePBCVectors(self):
        """ Checks that reducePeriodicBoxVectors properly reduces vectors """
        a = Vec3(4.24388485, 0.0, 0.0)
        b = Vec3(-1.4146281691908937, 4.001173048368583, 0.0)
        c = Vec3(-1.4146281691908937, -2.0005862820516203, 3.4651176446201674)
        vecs = reducePeriodicBoxVectors((a, b, c)*nanometers)
        vecs2 = computePeriodicBoxVectors(4.24388485, 4.24388485, 4.24388485,
                109.4712190*degrees, 109.4712190*degrees, 109.4712190*degrees)

        # Check that the vectors are the same
        a1, a2, a3 = vecs
        b1, b2, b3 = vecs2
        for x, y in zip(a1, b1):
            self.assertAlmostEqual(strip_units(x), strip_units(y))
        for x, y in zip(a2, b2):
            self.assertAlmostEqual(strip_units(x), strip_units(y))
        for x, y in zip(a3, b3):
            self.assertAlmostEqual(strip_units(x), strip_units(y))
예제 #4
0
    def testReducePBCVectors(self):
        """ Checks that reducePeriodicBoxVectors properly reduces vectors """
        a = Vec3(4.24388485, 0.0, 0.0)
        b = Vec3(-1.4146281691908937, 4.001173048368583, 0.0)
        c = Vec3(-1.4146281691908937, -2.0005862820516203, 3.4651176446201674)
        vecs = reducePeriodicBoxVectors((a, b, c) * nanometers)
        vecs2 = computePeriodicBoxVectors(4.24388485, 4.24388485, 4.24388485,
                                          109.4712190 * degrees,
                                          109.4712190 * degrees,
                                          109.4712190 * degrees)

        # Check that the vectors are the same
        a1, a2, a3 = vecs
        b1, b2, b3 = vecs2
        for x, y in zip(a1, b1):
            self.assertAlmostEqual(strip_units(x), strip_units(y))
        for x, y in zip(a2, b2):
            self.assertAlmostEqual(strip_units(x), strip_units(y))
        for x, y in zip(a3, b3):
            self.assertAlmostEqual(strip_units(x), strip_units(y))
예제 #5
0
    def __init__(self, file):
        """Load a PDBx/mmCIF file.

        The atom positions and Topology can be retrieved by calling
        getPositions() and getTopology().

        Parameters
        ----------
        file : string
            the name of the file to load.  Alternatively you can pass an open
            file object.
        """
        top = Topology()
        ## The Topology read from the PDBx/mmCIF file
        self.topology = top
        self._positions = []

        # Load the file.

        inputFile = file
        if isinstance(file, str):
            inputFile = open(file)
        reader = PdbxReader(inputFile)
        data = []
        reader.read(data)
        block = data[0]

        # Build the topology.

        atomData = block.getObj('atom_site')
        atomNameCol = atomData.getAttributeIndex('auth_atom_id')
        atomIdCol = atomData.getAttributeIndex('id')
        resNameCol = atomData.getAttributeIndex('auth_comp_id')
        resNumCol = atomData.getAttributeIndex('auth_seq_id')
        resInsertionCol = atomData.getAttributeIndex('pdbx_PDB_ins_code')
        chainIdCol = atomData.getAttributeIndex('auth_asym_id')
        elementCol = atomData.getAttributeIndex('type_symbol')
        altIdCol = atomData.getAttributeIndex('label_alt_id')
        modelCol = atomData.getAttributeIndex('pdbx_PDB_model_num')
        xCol = atomData.getAttributeIndex('Cartn_x')
        yCol = atomData.getAttributeIndex('Cartn_y')
        zCol = atomData.getAttributeIndex('Cartn_z')
        lastChainId = None
        lastResId = None
        atomTable = {}
        atomsInResidue = set()
        models = []
        for row in atomData.getRowList():
            atomKey = ((row[resNumCol], row[chainIdCol], row[atomNameCol]))
            model = ('1' if modelCol == -1 else row[modelCol])
            if model not in models:
                models.append(model)
                self._positions.append([])
            modelIndex = models.index(model)
            if row[altIdCol] != '.' and atomKey in atomTable and len(self._positions[modelIndex]) > atomTable[atomKey].index:
                # This row is an alternate position for an existing atom, so ignore it.

                continue
            if modelIndex == 0:
                # This row defines a new atom.

                if lastChainId != row[chainIdCol]:
                    # The start of a new chain.
                    chain = top.addChain(row[chainIdCol])
                    lastChainId = row[chainIdCol]
                    lastResId = None
                if lastResId != row[resNumCol] or lastChainId != row[chainIdCol] or (lastResId == '.' and row[atomNameCol] in atomsInResidue):
                    # The start of a new residue.
                    resId = (None if resNumCol == -1 else row[resNumCol])
                    resIC = ('' if resInsertionCol == -1 else row[resInsertionCol])
                    res = top.addResidue(row[resNameCol], chain, resId, resIC)
                    lastResId = row[resNumCol]
                    atomsInResidue.clear()
                element = None
                try:
                    element = elem.get_by_symbol(row[elementCol])
                except KeyError:
                    pass
                atom = top.addAtom(row[atomNameCol], element, res, row[atomIdCol])
                atomTable[atomKey] = atom
                atomsInResidue.add(row[atomNameCol])
            else:
                # This row defines coordinates for an existing atom in one of the later models.

                try:
                    atom = atomTable[atomKey]
                except KeyError:
                    raise ValueError('Unknown atom %s in residue %s %s for model %s' % (row[atomNameCol], row[resNameCol], row[resNumCol], model))
                if atom.index != len(self._positions[modelIndex]):
                    raise ValueError('Atom %s for model %s does not match the order of atoms for model %s' % (row[atomIdCol], model, models[0]))
            self._positions[modelIndex].append(Vec3(float(row[xCol]), float(row[yCol]), float(row[zCol]))*0.1)
        for i in range(len(self._positions)):
            self._positions[i] = self._positions[i]*nanometers
        ## The atom positions read from the PDBx/mmCIF file.  If the file contains multiple frames, these are the positions in the first frame.
        self.positions = self._positions[0]
        self.topology.createStandardBonds()
        self._numpyPositions = None

        # Record unit cell information, if present.

        cell = block.getObj('cell')
        if cell is not None and cell.getRowCount() > 0:
            row = cell.getRow(0)
            (a, b, c) = [float(row[cell.getAttributeIndex(attribute)])*0.1 for attribute in ('length_a', 'length_b', 'length_c')]
            (alpha, beta, gamma) = [float(row[cell.getAttributeIndex(attribute)])*math.pi/180.0 for attribute in ('angle_alpha', 'angle_beta', 'angle_gamma')]
            self.topology.setPeriodicBoxVectors(computePeriodicBoxVectors(a, b, c, alpha, beta, gamma))

        # Add bonds based on struct_conn records.

        connectData = block.getObj('struct_conn')
        if connectData is not None:
            res1Col = connectData.getAttributeIndex('ptnr1_label_seq_id')
            res2Col = connectData.getAttributeIndex('ptnr2_label_seq_id')
            atom1Col = connectData.getAttributeIndex('ptnr1_label_atom_id')
            atom2Col = connectData.getAttributeIndex('ptnr2_label_atom_id')
            asym1Col = connectData.getAttributeIndex('ptnr1_label_asym_id')
            asym2Col = connectData.getAttributeIndex('ptnr2_label_asym_id')
            typeCol = connectData.getAttributeIndex('conn_type_id')
            connectBonds = []
            for row in connectData.getRowList():
                type = row[typeCol][:6]
                if type in ('covale', 'disulf', 'modres'):
                    key1 = (row[res1Col], row[asym1Col], row[atom1Col])
                    key2 = (row[res2Col], row[asym2Col], row[atom2Col])
                    if key1 in atomTable and key2 in atomTable:
                        connectBonds.append((atomTable[key1], atomTable[key2]))
            if len(connectBonds) > 0:
                # Only add bonds that don't already exist.
                existingBonds = set(top.bonds())
                for bond in connectBonds:
                    if bond not in existingBonds and (bond[1], bond[0]) not in existingBonds:
                        top.addBond(bond[0], bond[1])
                        existingBonds.add(bond)
예제 #6
0
    def __init__(self, file):
        """Load a prmtop file."""
        ## The Topology read from the prmtop file
        self.topology = top = Topology()
        self.elements = []

        # Load the prmtop file

        prmtop = amber_file_parser.PrmtopLoader(file)
        self._prmtop = prmtop

        # Add atoms to the topology

        PDBFile._loadNameReplacementTables()
        lastResidue = None
        c = top.addChain()
        for index in range(prmtop.getNumAtoms()):
            resNumber = prmtop.getResidueNumber(index)
            if resNumber != lastResidue:
                lastResidue = resNumber
                resName = prmtop.getResidueLabel(iAtom=index).strip()
                if resName in PDBFile._residueNameReplacements:
                    resName = PDBFile._residueNameReplacements[resName]
                r = top.addResidue(resName, c)
                if resName in PDBFile._atomNameReplacements:
                    atomReplacements = PDBFile._atomNameReplacements[resName]
                else:
                    atomReplacements = {}
            atomName = prmtop.getAtomName(index).strip()
            if atomName in atomReplacements:
                atomName = atomReplacements[atomName]

            # Get the element from the prmtop file if available
            if prmtop.has_atomic_number:
                try:
                    element = elem.Element.getByAtomicNumber(int(prmtop._raw_data['ATOMIC_NUMBER'][index]))
                except KeyError:
                    element = None
            else:
                # Try to guess the element from the atom name.

                upper = atomName.upper()
                if upper.startswith('CL'):
                    element = elem.chlorine
                elif upper.startswith('NA'):
                    element = elem.sodium
                elif upper.startswith('MG'):
                    element = elem.magnesium
                elif upper.startswith('ZN'):
                    element = elem.zinc
                else:
                    try:
                        element = elem.get_by_symbol(atomName[0])
                    except KeyError:
                        element = None

            top.addAtom(atomName, element, r)
            self.elements.append(element)

        # Add bonds to the topology

        atoms = list(top.atoms())
        for bond in prmtop.getBondsWithH():
            top.addBond(atoms[bond[0]], atoms[bond[1]])
        for bond in prmtop.getBondsNoH():
            top.addBond(atoms[bond[0]], atoms[bond[1]])

        # Set the periodic box size.

        if prmtop.getIfBox():
            box = prmtop.getBoxBetaAndDimensions()
            top.setPeriodicBoxVectors(computePeriodicBoxVectors(*(box[1:4] + box[0:1]*3)))
예제 #7
0
    def __init__(self, file):
        """Load a prmtop file."""
        ## The Topology read from the prmtop file
        self.topology = top = Topology()
        self.elements = []

        # Load the prmtop file

        prmtop = amber_file_parser.PrmtopLoader(file)
        self._prmtop = prmtop

        # Add atoms to the topology

        PDBFile._loadNameReplacementTables()
        lastResidue = None
        c = top.addChain()
        for index in range(prmtop.getNumAtoms()):
            resNumber = prmtop.getResidueNumber(index)
            if resNumber != lastResidue:
                lastResidue = resNumber
                resName = prmtop.getResidueLabel(iAtom=index).strip()
                if resName in PDBFile._residueNameReplacements:
                    resName = PDBFile._residueNameReplacements[resName]
                r = top.addResidue(resName, c)
                if resName in PDBFile._atomNameReplacements:
                    atomReplacements = PDBFile._atomNameReplacements[resName]
                else:
                    atomReplacements = {}
            atomName = prmtop.getAtomName(index).strip()
            if atomName in atomReplacements:
                atomName = atomReplacements[atomName]

            # Get the element from the prmtop file if available
            if prmtop.has_atomic_number:
                try:
                    element = elem.Element.getByAtomicNumber(
                        int(prmtop._raw_data['ATOMIC_NUMBER'][index]))
                except KeyError:
                    element = None
            else:
                # Try to guess the element from the atom name.

                upper = atomName.upper()
                if upper.startswith('CL'):
                    element = elem.chlorine
                elif upper.startswith('NA'):
                    element = elem.sodium
                elif upper.startswith('MG'):
                    element = elem.magnesium
                elif upper.startswith('ZN'):
                    element = elem.zinc
                else:
                    try:
                        element = elem.get_by_symbol(atomName[0])
                    except KeyError:
                        element = None

            top.addAtom(atomName, element, r)
            self.elements.append(element)

        # Add bonds to the topology

        atoms = list(top.atoms())
        for bond in prmtop.getBondsWithH():
            top.addBond(atoms[bond[0]], atoms[bond[1]])
        for bond in prmtop.getBondsNoH():
            top.addBond(atoms[bond[0]], atoms[bond[1]])

        # Set the periodic box size.

        if prmtop.getIfBox():
            box = prmtop.getBoxBetaAndDimensions()
            top.setPeriodicBoxVectors(
                computePeriodicBoxVectors(*(box[1:4] + box[0:1] * 3)))
예제 #8
0
파일: pdbxfile.py 프로젝트: mrG7/openmm
    def __init__(self, file):
        """Load a PDBx/mmCIF file.

        The atom positions and Topology can be retrieved by calling getPositions() and getTopology().

        Parameters:
         - file (string) the name of the file to load.  Alternatively you can pass an open file object.
        """
        top = Topology()
        ## The Topology read from the PDBx/mmCIF file
        self.topology = top
        self._positions = []

        # Load the file.

        inputFile = file
        if isinstance(file, str):
            inputFile = open(file)
        reader = PdbxReader(inputFile)
        data = []
        reader.read(data)
        block = data[0]

        # Build the topology.

        atomData = block.getObj('atom_site')
        atomNameCol = atomData.getAttributeIndex('label_atom_id')
        atomIdCol = atomData.getAttributeIndex('id')
        resNameCol = atomData.getAttributeIndex('label_comp_id')
        resIdCol = atomData.getAttributeIndex('label_seq_id')
        resNumCol = atomData.getAttributeIndex('auth_seq_id')
        asymIdCol = atomData.getAttributeIndex('label_asym_id')
        chainIdCol = atomData.getAttributeIndex('label_entity_id')
        elementCol = atomData.getAttributeIndex('type_symbol')
        altIdCol = atomData.getAttributeIndex('label_alt_id')
        modelCol = atomData.getAttributeIndex('pdbx_PDB_model_num')
        xCol = atomData.getAttributeIndex('Cartn_x')
        yCol = atomData.getAttributeIndex('Cartn_y')
        zCol = atomData.getAttributeIndex('Cartn_z')
        lastChainId = None
        lastResId = None
        lastAsymId = None
        atomTable = {}
        atomsInResidue = set()
        models = []
        for row in atomData.getRowList():
            atomKey = ((row[resIdCol], row[asymIdCol], row[atomNameCol]))
            model = ('1' if modelCol == -1 else row[modelCol])
            if model not in models:
                models.append(model)
                self._positions.append([])
            modelIndex = models.index(model)
            if row[altIdCol] != '.' and atomKey in atomTable and len(
                    self._positions[modelIndex]) > atomTable[atomKey].index:
                # This row is an alternate position for an existing atom, so ignore it.

                continue
            if modelIndex == 0:
                # This row defines a new atom.

                if lastChainId != row[chainIdCol]:
                    # The start of a new chain.
                    chain = top.addChain(row[asymIdCol])
                    lastChainId = row[chainIdCol]
                    lastResId = None
                    lastAsymId = None
                if lastResId != row[resIdCol] or lastAsymId != row[
                        asymIdCol] or (lastResId == '.'
                                       and row[atomNameCol] in atomsInResidue):
                    # The start of a new residue.
                    res = top.addResidue(
                        row[resNameCol], chain,
                        None if resNumCol == -1 else row[resNumCol])
                    lastResId = row[resIdCol]
                    lastAsymId = row[asymIdCol]
                    atomsInResidue.clear()
                element = None
                try:
                    element = elem.get_by_symbol(row[elementCol])
                except KeyError:
                    pass
                atom = top.addAtom(row[atomNameCol], element, res,
                                   row[atomIdCol])
                atomTable[atomKey] = atom
                atomsInResidue.add(row[atomNameCol])
            else:
                # This row defines coordinates for an existing atom in one of the later models.

                try:
                    atom = atomTable[atomKey]
                except KeyError:
                    raise ValueError(
                        'Unknown atom %s in residue %s %s for model %s' %
                        (row[atomNameCol], row[resNameCol], row[resIdCol],
                         model))
                if atom.index != len(self._positions[modelIndex]):
                    raise ValueError(
                        'Atom %s for model %s does not match the order of atoms for model %s'
                        % (row[atomIdCol], model, models[0]))
            self._positions[modelIndex].append(
                Vec3(float(row[xCol]), float(row[yCol]), float(row[zCol])) *
                0.1)
        for i in range(len(self._positions)):
            self._positions[i] = self._positions[i] * nanometers
        ## The atom positions read from the PDBx/mmCIF file.  If the file contains multiple frames, these are the positions in the first frame.
        self.positions = self._positions[0]
        self.topology.createStandardBonds()
        self._numpyPositions = None

        # Record unit cell information, if present.

        cell = block.getObj('cell')
        if cell is not None and cell.getRowCount() > 0:
            row = cell.getRow(0)
            (a, b, c) = [
                float(row[cell.getAttributeIndex(attribute)]) * 0.1
                for attribute in ('length_a', 'length_b', 'length_c')
            ]
            (alpha, beta, gamma) = [
                float(row[cell.getAttributeIndex(attribute)]) * math.pi / 180.0
                for attribute in ('angle_alpha', 'angle_beta', 'angle_gamma')
            ]
            self.topology.setPeriodicBoxVectors(
                computePeriodicBoxVectors(a, b, c, alpha, beta, gamma))

        # Add bonds based on struct_conn records.

        connectData = block.getObj('struct_conn')
        if connectData is not None:
            res1Col = connectData.getAttributeIndex('ptnr1_label_seq_id')
            res2Col = connectData.getAttributeIndex('ptnr2_label_seq_id')
            atom1Col = connectData.getAttributeIndex('ptnr1_label_atom_id')
            atom2Col = connectData.getAttributeIndex('ptnr2_label_atom_id')
            asym1Col = connectData.getAttributeIndex('ptnr1_label_asym_id')
            asym2Col = connectData.getAttributeIndex('ptnr2_label_asym_id')
            typeCol = connectData.getAttributeIndex('conn_type_id')
            connectBonds = []
            for row in connectData.getRowList():
                type = row[typeCol][:6]
                if type in ('covale', 'disulf', 'modres'):
                    key1 = (row[res1Col], row[asym1Col], row[atom1Col])
                    key2 = (row[res2Col], row[asym2Col], row[atom2Col])
                    if key1 in atomTable and key2 in atomTable:
                        connectBonds.append((atomTable[key1], atomTable[key2]))
            if len(connectBonds) > 0:
                # Only add bonds that don't already exist.
                existingBonds = set(top.bonds())
                for bond in connectBonds:
                    if bond not in existingBonds and (
                            bond[1], bond[0]) not in existingBonds:
                        top.addBond(bond[0], bond[1])
                        existingBonds.add(bond)
예제 #9
0
    def init_simulation(self, complex_list):
        settings = AdvancedSettings.instance
        self.__forcefield = settings.get_forcefield()
        # Create topology
        topology = Topology()
        added_atoms = dict()
        positions = []
        PDBFile._loadNameReplacementTables()
        self.__complex_list = complex_list
        min_x = max_x = min_y = max_y = min_z = max_z = None
        Logs.debug("Create topology")
        for complex in complex_list:
            for molecule in complex.molecules:
                for chain in molecule.chains:
                    sim_chain = topology.addChain()
                    for residue in chain.residues:
                        residueName = residue.molecular.name
                        if residueName in PDBFile._atomNameReplacements:
                            atomReplacements = PDBFile._atomNameReplacements[residueName]
                        else:
                            atomReplacements = {}
                        sim_residue = topology.addResidue(residue.molecular.name, sim_chain)
                        for atom in residue.atoms:
                            molecular = atom.molecular
                            symbol = MDSimulationProcess.get_atom_symbol(molecular.name, len(residue._atoms))
                            atom_name = molecular.name
                            if atom_name in atomReplacements:
                                atom_name = atomReplacements[atom_name]
                            sim_atom = topology.addAtom(atom_name, symbol, sim_residue)
                            added_atoms[atom.index] = sim_atom
                            position = molecular.position
                            positions.append(Vec3(position.x * 0.1 * nanometer, position.y * 0.1 * nanometer, position.z * 0.1 * nanometer))
                            if min_x == None or position.x < min_x:
                                min_x = position.x
                            if max_x == None or position.x > max_x:
                                max_x = position.x
                            if min_y == None or position.y < min_y:
                                min_y = position.y
                            if max_y == None or position.y > max_y:
                                max_y = position.y
                            if min_z == None or position.z < min_z:
                                min_z = position.z
                            if max_z == None or position.z > max_z:
                                max_z = position.z

        topology.createStandardBonds()
        topology.createDisulfideBonds(positions)
        added_bonds = set(topology.bonds())
        for complex in complex_list:
            for molecule in complex.molecules:
                for chain in molecule.chains:
                    for residue in chain.residues:
                        for bond in residue.bonds:
                            if bond.index in added_bonds:
                                continue
                            atom1 = added_atoms[bond.atom1.index]
                            atom2 = added_atoms[bond.atom2.index]
                            type = MDSimulationProcess.get_bond_type(bond.molecular.kind)
                            topology.addBond(atom1, atom2, type)
                            added_bonds.add(bond.index)

        # topology.setPeriodicBoxVectors(computePeriodicBoxVectors(max_x - min_x, max_y - min_y, max_z - min_z, 90, 90, 90))
        topology.setPeriodicBoxVectors(computePeriodicBoxVectors(49.163, 45.981, 38.869, 90.00, 90.00, 90.00))

        # Create simulation parameters
        # nonbondedMethod = PME
        [templates, residues] = self.__forcefield.generateTemplatesForUnmatchedResidues(topology)
        for index, residue in enumerate(residues):
            template = templates[index]
            print("unmatched residue:", residue)
        # for index, template in enumerate(templates):
        #     residue = residues[index]
        #     residue_bonds = list(residue.internal_bonds())+list(residue.external_bonds())
        #     print("residue bonds:", residue_bonds)
        #     (unique_res_bonds, unique_tmp_bonds) = ForceField.findMissingBonds(residue, template)
        #     print("UNIQUE RESIDUE BONDS:", unique_res_bonds)
        #     print("UNIQUE TEMPLATE BONDS:", unique_tmp_bonds)
        #     print(f"RESIDUE {residue.name}:")
        #     if len(unique_res_bonds) > 0:
        #         print("Missing bonds:")
        #         for res_bond in unique_res_bonds:
        #             print(f"\n{res_bond}")
        #     print(f"TEMPLATE {template.name}:")
        #     if len(unique_tmp_bonds) > 0:
        #         print("Missing bonds:")
        #         for tmp_bond in unique_tmp_bonds:
        #             print(f"\n{tmp_bond}")
        #     print("-------------------------")
        #     for bond in unique_res_bonds:
        #         template.name += '[' + ForceField.getAtomID(bond[0]) + '<-->' + ForceField.getAtomID(bond[1]) + ']'
        #         if bond[0] in residue.atoms() and bond[1] in residue.atoms():
        #             template.addBondByName(bond[0].name, bond[1].name)
        #         else:
        #             template.addExternalBondByName(bond[0].name)

        #     if template.name not in self.__forcefield._templates:
        #         self.__forcefield.registerResidueTemplate(template)
        #         print(f"registering template {template.name}")
        #     else:
        #         print(f"redundant template {template.name} ********************")

        # system = self.__forcefield.createSystem(topology, nonbondedMethod = NoCutoff, nonbondedCutoff = 1 * nanometer, constraints = HBonds)
        system = settings.get_system(topology)

        # Set the simulation
        # integrator = LangevinIntegrator(300 * kelvin, 1 / picosecond, 0.002 * picosecond)
        integrator = settings.get_integrator()

        if settings.system_thermostat is not 'None':
            temp = settings.system_generation_temp
            col_rate = settings.integrator_collision_rate
            system.addForce(mm.AndersenThermostat(temp*kelvin, col_rate/picoseconds))

        # simulation = Simulation(topology, system, integrator)
        self.__simulation = settings.get_simulation(positions)
        # Set reporting
        settings.attach_reporter(MDReporter, self.simulation_result)

        self.__simulation.context.setPositions(positions)
        if settings.simulation_minimize:
            self.__plugin.send_notification(nanome.util.enums.NotificationTypes.message, "Minimizing...")
            self.__simulation.minimizeEnergy()

        if settings.system_random_init_vel:
            self.__simulation.context.setVelocitiesToTemperature(settings.system_generation_temp*kelvin)
            eq_steps = settings.simulation_equilibrium_steps
            if eq_steps:
                self.__plugin.send_notification(nanome.util.enums.NotificationTypes.message, "Equilibrating...")
                self.simulate(complex_list, eq_steps)