赞
踩
大家如果在github上面下载ACPYPE (https://github.com/t-/acpype),放入到LINUX上面安装后,百分百报错,出现的问题如下:
[root@pdynamo test]# ../acpype.py -i FFF.pdb
============================================================================
| ACPYPE: AnteChamber PYthon Parser interfacE v. 0 0 Rev: 0 (c) 2020 AWSdS |
============================================================================
==> ... charge set to 0
==> ... converting pdb input file to mol2 input file
==> * Babel OK *
==> Executing Antechamber...
==> * Antechamber OK *
++++++++++start_quote+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
/bin/sh: -c: line 0: syntax error near unexpected token `('
/bin/sh: -c: line 0: `which: no parmchk in (/usr/local/bin:/home/peter/Amber/amber18/bin:/home/peter/gmx2019.4/bin:/home/peter/fftw-3.3.8/bin:/home/peter/openmpi-3.1.3/bin:/home/peter/intel/compilers_and_libraries_2019.5.281/linux/bin/intel64:/home/peter/intel/compilers_and_libraries_2019.5.281/linux/bin:/home/peter/intel/compilers_and_libraries_2019.5.281/linux/mpi/intel64/libfabric/bin:/home/peter/intel/compilers_and_libraries_2019.5.281/linux/mpi/intel64/bin:/home/peter/intel/compilers_and_libraries_2019.5.281/linux/bin:/home/peter/intel/compilers_and_libraries_2019.5.281/linux/bin/intel64:/home/peter/intel/compilers_and_libraries_2019.5.281/linux/bin:/home/peter/intel/compilers_and_libraries_2019.5.281/linux/mpi/intel64/libfabric/bin:/home/peter/intel/compilers_and_libraries_2019.5.281/linux/mpi/intel64/bin:/home/peter/intel/compilers_and_libraries_2019.5.281/linux/bin/intel64:/home/peter/intel/compilers_and_libraries_2019.5.281/linux/bin:/home/peter/intel/compilers_and_libraries_2019.5.281/linux/mpi/intel64/libfabric/bin:/home/peter/intel/compilers_and_libraries_2019.5.281/linux/mpi/intel64/bin:/home/peter/intel/debugger_2019/gdb/intel64/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/home/peter/Amber/amber18/bin:/root/bin) -i FFF_bcc_gaff.mol2 -f mol2 -o FFF_AC.frcmod'
++++++++++end_quote+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ERROR: Parmchk failed
ERROR: Tleap failed
==> ... trying Sleap
==> Executing Sleap...
++++++++++start_quote+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++end_quote+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++start_quote+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
/bin/sh: -c: line 0: syntax error near unexpected token `('
/bin/sh: -c: line 0: `which: no sleap in (/usr/local/bin:/home/peter/Amber/amber18/bin:/home/peter/gmx2019.4/bin:/home/peter/fftw-3.3.8/bin:/home/peter/openmpi-3.1.3/bin:/home/peter/intel/compilers_and_libraries_2019.5.281/linux/bin/intel64:/home/peter/intel/compilers_and_libraries_2019.5.281/linux/bin:/home/peter/intel/compilers_and_libraries_2019.5.281/linux/mpi/intel64/libfabric/bin:/home/peter/intel/compilers_and_libraries_2019.5.281/linux/mpi/intel64/bin:/home/peter/intel/compilers_and_libraries_2019.5.281/linux/bin:/home/peter/intel/compilers_and_libraries_2019.5.281/linux/bin/intel64:/home/peter/intel/compilers_and_libraries_2019.5.281/linux/bin:/home/peter/intel/compilers_and_libraries_2019.5.281/linux/mpi/intel64/libfabric/bin:/home/peter/intel/compilers_and_libraries_2019.5.281/linux/mpi/intel64/bin:/home/peter/intel/compilers_and_libraries_2019.5.281/linux/bin/intel64:/home/peter/intel/compilers_and_libraries_2019.5.281/linux/bin:/home/peter/intel/compilers_and_libraries_2019.5.281/linux/mpi/intel64/libfabric/bin:/home/peter/intel/compilers_and_libraries_2019.5.281/linux/mpi/intel64/bin:/home/peter/intel/debugger_2019/gdb/intel64/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/home/peter/Amber/amber18/bin:/root/bin) -f sleap.in'
++++++++++end_quote+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ERROR: Sleap failed
==> Removing temporary files...
ACPYPE FAILED: [Errno 2] No such file or directory: 'FFF_AC.prmtop'
Total time of execution: 3m 8s
其原因是这个源文件有毛病,请大家把底下这个复制,然后覆盖acpepy.py这个文件,直接就好用。
这个文件感谢计算化学领域国内最强的卢天大神提供:http://bbs.keinsci.com/thread-14021-1-1.html
- #!/usr/bin/env python
-
- from __future__ import print_function
- from datetime import datetime
- from shutil import copy2
- from shutil import rmtree
- import traceback
- import signal
- import time
- import optparse
- import math
- import os
- import pickle
- import sys
- import subprocess as sub
- import re
-
- """
- Requirements: Python 2.6 or higher or Python 3.x
- Antechamber (from AmberTools preferably)
- OpenBabel (optional, but strongly recommended)
- This code is released under GNU General Public License V3.
- <<< NO WARRANTY AT ALL!!! >>>
- It was inspired by:
- - amb2gmx.pl (Eric Sorin, David Mobley and John Chodera)
- and depends on Antechamber and Openbabel
- - YASARA Autosmiles:
- http://www.yasara.org/autosmiles.htm (Elmar Krieger)
- - topolbuild (Bruce Ray)
- - xplo2d (G.J. Kleywegt)
- For Antechamber, please cite:
- 1. Wang, J., Wang, W., Kollman P. A.; Case, D. A. "Automatic atom type and
- bond type perception in molecular mechanical calculations". Journal of
- Molecular Graphics and Modelling , 25, 2006, 247260.
- 2. Wang, J., Wolf, R. M.; Caldwell, J. W.; Kollman, P. A.; Case, D. A.
- "Development and testing of a general AMBER force field". Journal of
- Computational Chemistry, 25, 2004, 1157-1174.
- If you use this code, I am glad if you cite:
- SOUSA DA SILVA, A. W. & VRANKEN, W. F.
- ACPYPE - AnteChamber PYthon Parser interfacE.
- BMC Research Notes 2012, 5:367 doi:10.1186/1756-0500-5-367
- http://www.biomedcentral.com/1756-0500/5/367
- Alan Wilter Sousa da Silva, D.Sc.
- Bioinformatician, UniProt, EMBL-EBI
- Hinxton, Cambridge CB10 1SD, UK.
- >>http://www.ebi.ac.uk/~awilter<<
- alanwilter _at_ gmail _dot_ com
- """
-
- svnId = '$Id$'
- try:
- svnRev, svnDate, svnTime = svnId.split()[2:5]
- except:
- svnRev, svnDate, svnTime = '0', '0', '0'
- year = datetime.today().year
- tag = "%s %s Rev: %s" % (svnDate, svnTime, svnRev)
-
- lineHeader = \
- '''
- | ACPYPE: AnteChamber PYthon Parser interfacE v. %s (c) %s AWSdS |
- ''' % (tag, year)
- frameLine = (len(lineHeader) - 2) * '='
- header = '%s%s%s' % (frameLine, lineHeader, frameLine)
-
- # TODO:
- # Howto Charmm and Amber with NAMD
- # Howto build topology for a modified amino acid
- # CYANA topology files
-
- # List of Topology Formats created by acpype so far:
- outTopols = ['gmx', 'cns', 'charmm']
- qDict = {'mopac': 0, 'divcon': 1, 'sqm': 2}
-
- # Residues that are not solute, to be avoided when balancing charges in
- # amb2gmx mode
- ionOrSolResNameList = ['Cl-', 'Na+', 'K+', 'CIO', 'Cs+', 'IB', 'Li+', 'MG2',
- 'Rb+', 'WAT', 'MOH', 'NMA']
-
- # leapAmberFile = 'leaprc.ff99SB' # 'leaprc.ff10' and 'leaprc.ff99bsc0' has extra Atom Types not in parm99.dat
- leapAmberFile = 'leaprc.protein.ff14SB' # 'leaprc.ff14SB'
-
- # "qm_theory='AM1', grms_tol=0.0002, maxcyc=999, tight_p_conv=1, scfconv=1.d-10,"
- # "AM1 ANALYT MMOK GEO-OK PRECISE"
-
- cal = 4.184
- Pi = 3.141593
- qConv = 18.222281775 # 18.2223
- radPi = 57.295780 # 180/Pi
- maxDist = 3.0
- minDist = 0.5
- maxDist2 = maxDist ** 2 # squared Ang.
- minDist2 = minDist ** 2 # squared Ang.
- diffTol = 0.01
-
- dictAmbAtomType2AmbGmxCode = \
- {'BR': '1', 'C': '2', 'CA': '3', 'CB': '4', 'CC': '5', 'CK': '6', 'CM': '7', 'CN': '8', 'CQ': '9',
- 'CR': '10', 'CT': '11', 'CV': '12', 'CW': '13', 'C*': '14', 'Ca': '15', 'F': '16', 'H': '17',
- 'HC': '18', 'H1': '19', 'H2': '20', 'H3': '21', 'HA': '22', 'H4': '23', 'H5': '24', 'HO': '25',
- 'HS': '26', 'HW': '27', 'HP': '28', 'I': '29', 'Cl': '30', 'Na': '31', 'IB': '32', 'Mg': '33',
- 'N': '34', 'NA': '35', 'NB': '36', 'NC': '37', 'N2': '38', 'N3': '39', 'N*': '40', 'O': '41',
- 'OW': '42', 'OH': '43', 'OS': '44', 'O2': '45', 'P': '46', 'S': '47', 'SH': '48', 'CU': '49',
- 'FE': '50', 'K': '51', 'Rb': '52', 'Cs': '53', 'Li': '56', 'Zn': '57', 'Sr': '58', 'Ba': '59',
- 'MCH3A': 'MCH3A', 'MCH3B': 'MCH3B', 'MNH2': 'MNH2', 'MNH3': 'MNH3', 'MW': 'MW'}
-
- dictOplsAtomType2OplsGmxCode = \
- {'Ac3+': ['697'], 'Am3+': ['699'], 'Ar': ['Ar', '097'], 'Ba2+': ['414'],
- 'Br': ['722', '730'], 'Br-': ['402'],
- 'CT': ['064', '076', '122', '135', '136', '137', '138', '139', '148', '149', '152', '157', '158', '159', '161', '173', '174', '175', '181', '182', '183', '184', '206', '207', '208', '209', '210', '211', '212', '213', '214', '215', '216', '217', '218', '219', '220', '223', '224', '225', '229', '230', '242', '243', '244', '256', '257', '258', '259', '273', '274', '275', '276', '291', '292', '293', '294', '297', '305', '306', '307', '308', '331', '371', '373', '375', '391', '396', '421', '431', '443', '448', '453', '455', '458', '461', '468', '476', '482', '484', '486', '490', '491', '492', '498', '499', '505', '515', '516', '645', '670', '671', '672', '673', '674', '675', '676', '677', '678', '679', '680', '681', '701', '725', '747', '748', '755', '756', '757', '758', '762', '764', '765', '766', '774', '775', '776', '782', '783', '903', '904', '905', '906', '907', '908', '912', '913', '914', '915', '942', '943', '944', '945', '951', '957', '959', '960', '961', '962', '963', '964'],
- 'CA': ['053', '145', '147', '166', '199', '221', '228', '260', '263', '266', '302', '312', '315', '317', '336', '351', '362', '380', '457', '460', '463', '472', '488', '521', '522', '523', '528', '532', '533', '538', '539', '551', '582', '590', '591', '592', '593', '604', '605', '606', '607', '608', '609', '610', '611', '612', '625', '644', '647', '648', '649', '650', '651', '652', '714', '716', '718', '720', '724', '727', '729', '731', '735', '736', '737', '738', '739', '742', '752', '768', '916', '917', '918'],
- 'C3': ['007', '010', '036', '039', '063', '065', '067', '068', '069', '070', '080', '088', '090', '092', '096', '106', '107', '109', '126', '132', '415', '418', '425', '429'],
- 'C': ['001', '017', '026', '058', '095', '131', '231', '234', '235', '247', '252', '267', '320', '322', '334', '366', '378', '470', '471', '772', '952'],
- 'C2': ['005', '009', '015', '016', '019', '022', '027', '028', '031', '034', '037', '056', '057', '061', '071', '081', '089', '091', '093', '110'],
- 'CT_2': ['223B', '224B', '225B', '246', '283', '284', '285', '292B', '293B', '295', '298', '299', '906B', '912B'],
- 'CM': ['141', '142', '143', '227', '323', '324', '337', '338', '381', '382', '517', '518', '708'],
- 'CW': ['508', '514', '543', '552', '561', '567', '575', '583', '588', '637'],
- 'CB': ['050', '349', '350', '364', '365', '501', '595', '623', '624'],
- 'CH': ['006', '008', '014', '025', '029', '030', '060', '073'],
- 'CZ': ['261', '423', '754', '925', '927', '928', '929', '931'],
- 'CO': ['189', '191', '193', '195', '197', '198'],
- 'C_2': ['232', '233', '277', '280', '465'],
- 'CR': ['506', '509', '558', '572', '634'],
- 'CQ': ['347', '531', '621', '642'],
- 'CV': ['507', '560', '574', '636'],
- 'CY': ['711', '712', '713', '733'],
- 'CS': ['544', '568', '589'],
- 'CK': ['353', '627'], 'CN': ['502', '594'], 'CP': ['043', '048'], 'CU': ['550', '581'],
- 'CT_3': ['245', '296'], 'C=': ['150', '178'], 'CD': ['011', '075'],
- 'C4': ['066'], 'C7': ['077'], 'C8': ['074'], 'C9': ['072'], 'CX': ['510'],
- 'C!': ['145B'], 'C*': ['500'], 'C+': ['700'], 'C_3': ['271'],
- 'CC': ['045'], 'CF': ['044'], 'CG': ['049'], 'CT_4': ['160'],
- 'Ca2+': ['412'],
- 'Cl': ['123', '151', '226', '264'],
- 'Cl-': ['401', '709'],
- 'Cs+': ['410'], 'Cu2+': ['Cu2+'], 'Eu3+': ['705'],
- 'F': ['164', '719', '721', '726', '728', '786', '956', '965'],
- 'F-': ['400'], 'Fe2+': ['Fe2+'], 'Gd3+': ['706'],
- 'HA': ['146', '316', '318', '389', '524', '525', '526', '529', '534', '535', '536', '540', '541', '546', '547', '554', '555', '556', '563', '564', '565', '569', '570', '576', '577', '578', '584', '585', '586', '597', '598', '599', '600', '601', '602', '613', '614', '615', '616', '617', '618', '619', '629', '630', '631', '638', '639', '640', '643', '653', '654', '655', '656', '715', '717', '740', '741', '746'],
- 'HC': ['140', '144', '153', '156', '165', '176', '185', '190', '192', '194', '196', '255', '279', '282', '329', '330', '332', '344', '372', '374', '376', '392', '416', '419', '422', '426', '430', '432', '444', '449', '454', '456', '459', '462', '469', '477', '483', '485', '487', '702', '710', '759', '763', '777', '778', '779', '784', '911', '926', '930', '950', '958'],
- 'H': ['004', '013', '041', '047', '128', '240', '241', '250', '254', '314', '325', '327', '339', '342', '343', '357', '358', '360', '367', '369', '383', '385', '387', '388', '428', '479', '481', '504', '513', '545', '553', '562', '596', '632', '744', '745', '909', '910'],
- 'H3': ['021', '052', '055', '104', '105', '289', '290', '301', '304', '310', '941', '955'],
- 'HO': ['024', '079', '155', '163', '168', '170', '172', '188', '270', '435'],
- 'HS': ['033', '086', '087', '204', '205'],
- 'HW': ['112', '114', '117', '119', '796'],
- 'H4': ['345', '390'], 'H5': ['355', '359'],
- 'He': ['130'], 'I': ['732'], 'I-': ['403'], 'K+': ['408'], 'Kr': ['098'],
- 'LP': ['433', '797'], 'La3+': ['703'], 'Li+': ['404', '406'],
- 'MCH3A': ['MCH3A'], 'MCH3B': ['MCH3B'], 'MNH2': ['MNH2'], 'MNH3': ['MNH3'],
- 'MW': ['MW', '115'], 'Mg2+': ['411'],
- 'NA': ['040', '046', '319', '321', '333', '354', '361', '377', '379', '503', '512', '542', '548', '557', '587', '628'],
- 'NC': ['311', '335', '346', '348', '363', '520', '527', '530', '537', '603', '620', '622', '641', '646'],
- 'N': ['003', '012', '094', '237', '238', '239', '249', '251', '265', '478', '480', '787'],
- 'N3': ['020', '101', '102', '103', '286', '287', '288', '309', '427', '940', '953'],
- 'N2': ['051', '054', '300', '303', '313', '341', '356', '368', '386', '743'],
- 'NB': ['042', '352', '511', '549', '559', '573', '580', '626', '635'],
- 'N*': ['319B', '333B', '354B', '377B'],
- 'NT': ['127', '900', '901', '902'],
- 'NZ': ['262', '424', '750', '753'],
- 'NO': ['760', '767'], 'NY': ['749', '751'],
- 'Na+': ['405', '407'], 'Nd3+': ['704'], 'Ne': ['129'],
- 'OS': ['062', '108', '179', '180', '186', '395', '442', '447', '452', '467', '473', '566', '571', '579', '773'],
- 'O': ['002', '059', '236', '248', '253', '326', '328', '340', '370', '384', '771', '788'],
- 'OH': ['023', '078', '154', '162', '167', '169', '171', '187', '268', '420', '434'],
- 'O2': ['018', '125', '272', '394', '441', '446', '451', '954'],
- 'OW': ['111', '113', '116', '118', '795'],
- 'O_2': ['278', '281', '466'],
- 'OY': ['475', '494', '497'],
- 'OL': ['120'], 'ON': ['761'], 'OU': ['437'], 'O_3': ['269'],
- 'P': ['393', '440', '445', '450', '785'],
- 'P+': ['781'], 'Rb+': ['409'],
- 'S': ['035', '038', '084', '085', '124', '202', '203', '222', '633'],
- 'SH': ['032', '082', '083', '200', '201', '417', '734'],
- 'SI': ['SI'], 'SY': ['474'], 'SY2': ['493'], 'SZ': ['496'], 'Sr2+': ['413'],
- 'Th4+': ['698'], 'U': ['436'], 'Xe': ['099'], 'Yb3+': ['707'], 'Zn2+': ['Zn2+']}
-
- # reverse dictOplsAtomType2OplsGmxCode
- oplsCode2AtomTypeDict = {}
- for k, v in list(dictOplsAtomType2OplsGmxCode.items()):
- for code in v:
- oplsCode2AtomTypeDict[code] = k
- # if code in oplsCode2AtomTypeDict.keys():
- # oplsCode2AtomTypeDict[code].append(k)
- # else:
- # oplsCode2AtomTypeDict[code] = [k]
-
- # Cross dictAmbAtomType2AmbGmxCode with dictOplsAtomType2OplsGmxCode & add H1,HP,H2
- dictAtomTypeAmb2OplsGmxCode = {'H1': ['140', '1.00800'], 'HP': ['140', '1.00800'], 'H2': ['140', '1.00800']}
- dictOplsMass = {'SY2': ['32.06000'], 'Zn2+': ['65.37000'], 'CQ': ['12.01100'], 'CP': ['12.01100'], 'Nd3+': ['144.24000'], 'Br-': ['79.90400'], 'Cu2+': ['63.54600'], 'Br': ['79.90400'], 'H': ['1.00800'], 'P': ['30.97376'], 'Sr2+': ['87.62000'], 'ON': ['15.99940'], 'OL': ['0.00000'], 'OH': ['15.99940'], 'OY': ['15.99940'], 'OW': ['15.99940'], 'OU': ['15.99940'], 'OS': ['15.99940'], 'Am3+': ['243.06000'], 'HS': ['1.00800'], 'HW': ['1.00800'], 'HO': ['1.00800'], 'HC': ['1.00800'], 'HA': ['1.00800'], 'O2': ['15.99940'], 'Ca2+': ['40.08000'], 'Th4+': ['232.04000'], 'He': ['4.00260'], 'C': ['12.01100'], 'Cs+': ['132.90540'], 'O': ['15.99940'], 'Gd3+': ['157.25000'], 'S': ['32.06000'], 'P+': ['30.97376'], 'La3+': ['138.91000'], 'H3': ['1.00800'], 'H4': ['1.00800'], 'MNH2': ['0.00000'], 'MW': ['0.00000'], 'NB': ['14.00670'], 'K+': ['39.09830'], 'Ne': ['20.17970'], 'Rb+': ['85.46780'], 'C+': ['12.01100'], 'C*': ['12.01100'], 'NO': ['14.00670'], 'CT_4': ['12.01100'], 'NA': ['14.00670'], 'C!': ['12.01100'], 'NC': ['14.00670'], 'NZ': ['14.00670'], 'CT_2': ['12.01100'], 'CT_3': ['12.01100'], 'NY': ['14.00670'], 'C9': ['14.02700'], 'C8': ['13.01900'], 'C=': ['12.01100'], 'Yb3+': ['173.04000'], 'C3': ['15.03500', '12.01100'], 'C2': ['14.02700'], 'C7': ['12.01100'], 'C4': ['16.04300'], 'CK': ['12.01100'], 'Cl-': ['35.45300'], 'N*': ['14.00670'], 'CH': ['13.01900'], 'CO': ['12.01100'], 'CN': ['12.01100'], 'CM': ['12.01100'], 'F': ['18.99840'], 'CC': ['12.01100'], 'CB': ['12.01100'], 'CA': ['12.01100'], 'CG': ['12.01100'], 'CF': ['12.01100'], 'N': ['14.00670'], 'CZ': ['12.01100'], 'CY': ['12.01100'], 'CX': ['12.01100'], 'Ac3+': ['227.03000'], 'CS': ['12.01100'], 'CR': ['12.01100'], 'N2': ['14.00670'], 'N3': ['14.00670'], 'CW': ['12.01100'], 'CV': ['12.01100'], 'CU': ['12.01100'], 'CT': ['12.01100'], 'SZ': ['32.06000'], 'SY': ['32.06000'], 'Cl': ['35.45300'], 'NT': ['14.00670'], 'O_2': ['15.99940'], 'Xe': ['131.29300'], 'SI': ['28.08000'], 'SH': ['32.06000'], 'Eu3+': ['151.96000'], 'F-': ['18.99840'], 'MNH3': ['0.00000'], 'H5': ['1.00800'], 'C_3': ['12.01100'], 'C_2': ['12.01100'], 'I-': ['126.90450'], 'LP': ['0.00000'], 'I': ['126.90450'], 'Na+': ['22.98977'], 'Li+': ['6.94100'], 'U': ['0.00000'], 'MCH3A': ['0.00000'], 'MCH3B': ['0.00000'], 'CD': ['13.01900', '12.01100'], 'O_3': ['15.99940'], 'Kr': ['83.79800'], 'Fe2+': ['55.84700'], 'Ar': ['39.94800'], 'Mg2+': ['24.30500'], 'Ba2+': ['137.33000']}
- for ambKey in dictAmbAtomType2AmbGmxCode:
- if ambKey in dictOplsAtomType2OplsGmxCode:
- dictAtomTypeAmb2OplsGmxCode[ambKey] = dictOplsAtomType2OplsGmxCode[ambKey] + list(dictOplsMass[ambKey])
-
- # learnt from 22 residues test.
- dictAtomTypeAmb2OplsGmxCode = {'HS': ['204', '1.008'], 'HP': ['140', '1.008'], 'HO': ['155', '168', '1.008'], 'HC': ['140', '1.008'], 'HA': ['146', '1.008'], 'O2': ['272', '15.9994'], 'C*': ['500', '12.011'], 'NA': ['503', '512', '14.0067'], 'NB': ['511', '14.0067'], 'CB': ['501', '12.011'], 'C': ['235', '271', '12.011'], 'CN': ['502', '12.011'], 'CM': ['302', '12.011'], 'CC': ['507', '508', '510', '12.011'], 'H': ['240', '241', '290', '301', '304', '310', '504', '513', '1.008'], 'CA': ['145', '166', '12.011'], 'O': ['236', '15.9994'], 'N': ['237', '238', '239', '14.0067'], 'S': ['202', '32.06'], 'CR': ['506', '509', '12.011'], 'N2': ['300', '303', '14.0067'], 'N3': ['287', '309', '14.0067'], 'CW': ['508', '510', '514', '12.011'], 'CV': ['507', '12.011'], 'CT': ['135', '136', '137', '149', '157', '158', '206', '209', '210', '223B', '224B', '245', '246', '274', '283', '284', '285', '292', '292B', '293B', '296', '307', '308', '505', '12.011'], 'OH': ['154', '167', '15.9994'], 'H1': ['140', '1.008'], 'H4': ['146', '1.008'], 'H5': ['146', '1.008'], 'SH': ['200', '32.06']}
-
- # learnt from 22 residues test.
- dictAtomTypeGaff2OplsGmxCode = {'cc': ['500', '506', '507', '508', '514', '12.011'], 'ca': ['145', '166', '501', '502', '12.011'], 'h1': ['140', '1.008'], 'h4': ['146', '1.008'], 'h5': ['146', '1.008'], 'cz': ['302', '12.011'], 'c2': ['509', '510', '12.011'], 'nh': ['300', '303', '14.0067'], 'ha': ['146', '1.008'], 'na': ['503', '512', '14.0067'], 'nc': ['511', '14.0067'], 'nd': ['511', '14.0067'], 'hx': ['140', '1.008'], 'hs': ['204', '1.008'], 'hn': ['240', '241', '290', '301', '304', '310', '504', '513', '1.008'], 'ho': ['155', '168', '1.008'], 'c3': ['135', '136', '137', '149', '157', '158', '206', '209', '210', '223B', '224B', '245', '246', '274', '283', '284', '285', '292', '292B', '293B', '296', '307', '308', '505', '12.011'], 'hc': ['140', '1.008'], 'cd': ['500', '506', '507', '508', '514', '12.011'], 'c': ['235', '271', '12.011'], 'oh': ['154', '167', '15.9994'], 'ss': ['202', '32.06'], 'o': ['236', '272', '15.9994'], 'n': ['237', '238', '239', '14.0067'], 'sh': ['200', '32.06'], 'n4': ['287', '309', '14.0067']}
-
- # draft
- atomTypeAmber2oplsDict = {'HS': ['HS'], 'HP': ['HC'], 'HO': ['HO'], 'HC': ['HC'],
- 'HA': ['HA'], 'O2': ['O2'], 'C*': ['C*'], 'NA': ['NA'],
- 'NB': ['NB'], 'CB': ['CB'], 'CN': ['CN'], 'CV': ['CV'],
- 'CM': ['CA'], 'CA': ['CA'], 'CR': ['CR'], 'OH': ['OH'],
- 'H1': ['HC'], 'H4': ['HA'], 'N2': ['N2'], 'N3': ['N3'],
- 'H5': ['HA'], 'SH': ['SH'], 'N': ['N'], 'S': ['S'], 'O': ['O'],
- 'C': ['C', 'C_3'], 'CW': ['CW', 'CX'], 'H': ['H', 'H3'],
- 'CC': ['CX', 'CW', 'CV'], 'CT': ['CT', 'CT_2', 'CT_3']}
-
- # draft
- a2oD = {'amber99_2': ['opls_235', 'opls_271'],
- 'amber99_3': ['opls_302', 'opls_145'],
- 'amber99_5': ['opls_507', 'opls_508', 'opls_510'],
- 'amber99_11': ['opls_209', 'opls_158', 'opls_283', 'opls_223B', 'opls_293B',
- 'opls_284', 'opls_292B', 'opls_274', 'opls_136', 'opls_135',
- 'opls_292', 'opls_157', 'opls_206', 'opls_137', 'opls_505',
- 'opls_224B', 'opls_307', 'opls_308', 'opls_210', 'opls_149'],
- 'amber99_13': ['opls_514'],
- 'amber99_14': ['opls_500'],
- 'amber99_17': ['opls_504', 'opls_241', 'opls_240', 'opls_290', 'opls_301',
- 'opls_310', 'opls_304', 'opls_513'],
- 'amber99_18': ['opls_140'],
- 'amber99_19': ['opls_140'],
- 'amber99_22': ['opls_146'],
- 'amber99_23': ['opls_146'],
- 'amber99_25': ['opls_155'],
- 'amber99_26': ['opls_204'],
- 'amber99_28': ['opls_140'],
- 'amber99_34': ['opls_238', 'opls_239', 'opls_237'],
- 'amber99_35': ['opls_512', 'opls_503'],
- 'amber99_36': ['opls_511'],
- 'amber99_38': ['opls_300', 'opls_303'],
- 'amber99_39': ['opls_309', 'opls_287'],
- 'amber99_41': ['opls_236'],
- 'amber99_43': ['opls_154'],
- 'amber99_45': ['opls_272'],
- 'amber99_47': ['opls_202'],
- 'amber99_48': ['opls_200'],
- }
-
- global pid
- pid = 0
-
- head = "%s created by acpype (Rev: " + svnRev + ") on %s\n"
-
- date = datetime.now().ctime()
-
- usage = \
- """
- acpype -i _file_ [-c _string_] [-n _int_] [-m _int_] [-a _string_] [-f] etc. or
- acpype -p _prmtop_ -x _inpcrd_ [-d]"""
-
- epilog = \
- """
- output: assuming 'root' is the basename of either the top input file,
- the 3-letter residue name or user defined (-b option)
- root_bcc_gaff.mol2: final mol2 file with 'bcc' charges and 'gaff' atom type
- root_AC.inpcrd : coord file for AMBER
- root_AC.prmtop : topology and parameter file for AMBER
- root_AC.lib : residue library file for AMBER
- root_AC.frcmod : modified force field parameters
- root_GMX.gro : coord file for GROMACS
- root_GMX.top : topology file for GROMACS
- root_GMX.itp : molecule unit topology and parameter file for GROMACS
- root_GMX_OPLS.itp : OPLS/AA mol unit topol & par file for GROMACS (experimental!)
- em.mdp, md.mdp : run parameters file for GROMACS
- root_NEW.pdb : final pdb file generated by ACPYPE
- root_CNS.top : topology file for CNS/XPLOR
- root_CNS.par : parameter file for CNS/XPLOR
- root_CNS.inp : run parameters file for CNS/XPLOR
- root_CHARMM.rtf : topology file for CHARMM
- root_CHARMM.prm : parameter file for CHARMM
- root_CHARMM.inp : run parameters file for CHARMM"""
-
- SLEAP_TEMPLATE = \
- """
- source %(leapAmberFile)s
- source %(leapGaffFile)s
- set default fastbld on
- #set default disulfide auto
- %(res)s = loadpdb %(baseOrg)s.pdb
- #check %(res)s
- saveamberparm %(res)s %(acBase)s.prmtop %(acBase)s.inpcrd
- saveoff %(res)s %(acBase)s.lib
- quit
- """
-
- TLEAP_TEMPLATE = \
- """
- verbosity 1
- source %(leapAmberFile)s
- source %(leapGaffFile)s
- mods = loadamberparams %(acBase)s.frcmod
- %(res)s = loadmol2 %(acMol2FileName)s
- check %(res)s
- saveamberparm %(res)s %(acBase)s.prmtop %(acBase)s.inpcrd
- saveoff %(res)s %(acBase)s.lib
- quit
- """
-
-
- def dotproduct(aa, bb):
- return sum((a * b) for a, b in zip(aa, bb))
-
-
- def crosproduct(a, b):
- c = [a[1] * b[2] - a[2] * b[1],
- a[2] * b[0] - a[0] * b[2],
- a[0] * b[1] - a[1] * b[0]]
- return c
-
-
- def length(v):
- return math.sqrt(dotproduct(v, v))
-
-
- def vec_sub(aa, bb):
- return [a - b for a, b in zip(aa, bb)]
-
-
- def imprDihAngle(a, b, c, d):
- ba = vec_sub(a, b)
- bc = vec_sub(c, b)
- cb = vec_sub(b, c)
- cd = vec_sub(d, c)
- n1 = crosproduct(ba, bc)
- n2 = crosproduct(cb, cd)
- angle = math.acos(dotproduct(n1, n2) / (length(n1) * length(n2))) * 180 / Pi
- cp = crosproduct(n1, n2)
- if (dotproduct(cp, bc) < 0):
- angle = -1 * angle
- return angle
-
-
- def invalidArgs(text=None):
- if text:
- print('ERROR: ' + text)
- sys.exit(1)
-
- # verNum = string.split(sys.version)[0]
- verNum = re.sub('[^0-9\.]', '', sys.version.split()[0])
- version = verNum.split('.') # string.split(verNum, ".")
- verList = list(map(int, version))
- if verList < [2, 6, 0]:
- invalidArgs(text="Python version %s\n Sorry, you need python 2.6 or higher" % verNum)
-
- try:
- set()
- except NameError:
- from sets import Set as set # @UnresolvedImport
-
-
- def elapsedTime(seconds, suffixes=['y', 'w', 'd', 'h', 'm', 's'], add_s=False, separator=' '):
- """
- Takes an amount of seconds and turns it into a human-readable amount of time.
- """
- # the formatted time string to be returned
- time = []
-
- # the pieces of time to iterate over (days, hours, minutes, etc)
- # - the first piece in each tuple is the suffix (d, h, w)
- # - the second piece is the length in seconds (a day is 60s * 60m * 24h)
- parts = [(suffixes[0], 60 * 60 * 24 * 7 * 52),
- (suffixes[1], 60 * 60 * 24 * 7),
- (suffixes[2], 60 * 60 * 24),
- (suffixes[3], 60 * 60),
- (suffixes[4], 60),
- (suffixes[5], 1)]
-
- # for each time piece, grab the value and remaining seconds, and add it to
- # the time string
- for suffix, length in parts:
- value = seconds // length
- if value > 0:
- seconds = seconds % length
- time.append('%s%s' % (str(value),
- (suffix, (suffix, suffix + 's')[value > 1])[add_s]))
- if seconds < 1:
- break
-
- return separator.join(time)
-
-
- def splitBlock(dat):
- '''split a amber parm dat file in blocks
- 0 = mass, 1 = extra + bond, 2 = angle, 3 = dihedral, 4 = improp, 5 = hbond
- 6 = equiv nbon, 7 = nbon, 8 = END, 9 = etc.
- '''
- dict_ = {}
- count = 0
- for line in dat:
- line = line.rstrip()
- if count in dict_:
- dict_[count].append(line)
- else:
- dict_[count] = [line]
- if not line:
- count += 1
- return dict_
-
-
- def getParCode(line):
- key = line.replace(' -', '-').replace('- ', '-').split()[0]
- return key
-
-
- def parseFrcmod(lista):
- heads = ['MASS', 'BOND', 'ANGL', 'DIHE', 'IMPR', 'HBON', 'NONB']
- dict_ = {}
- for line in lista[1:]:
- line = line.strip()
- if line[:4] in heads:
- head = line[:4]
- dict_[head] = []
- dd = {}
- continue
- elif line:
- key = line.replace(' -', '-').replace('- ', '-').split()[0]
- if key in dd:
- if not dd[key].count(line):
- dd[key].append(line)
- else:
- dd[key] = [line]
- dict_[head] = dd
- for k in dict_.keys():
- if not dict_[k]:
- dict_.pop(k)
- return dict_
-
-
- def parmMerge(fdat1, fdat2, frcmod=False):
- '''merge two amber parm dat/frcmod files and save in /tmp'''
- name1 = os.path.basename(fdat1).split('.dat')[0]
- if frcmod:
- name2 = os.path.basename(fdat2).split('.')[1]
- else:
- name2 = os.path.basename(fdat2).split('.dat')[0]
- mname = '/tmp/' + name1 + name2 + '.dat'
- mdatFile = open(mname, 'w')
- mdat = ['merged %s %s' % (name1, name2)]
-
- # if os.path.exists(mname): return mname
- dat1 = splitBlock(open(fdat1).readlines())
-
- if frcmod:
- dHeads = {'MASS': 0, 'BOND': 1, 'ANGL': 2, 'DIHE': 3, 'IMPR': 4, 'HBON': 5, 'NONB': 7}
- dat2 = parseFrcmod(open(fdat2).readlines()) # dict
- for k in dat2:
- for parEntry in dat2[k]:
- idFirst = None
- for line in dat1[dHeads[k]][:]:
- if line:
- key = line.replace(' -', '-').replace('- ', '-').split()[0]
- if key == parEntry:
- if not idFirst:
- idFirst = dat1[dHeads[k]].index(line)
- dat1[dHeads[k]].remove(line)
- rev = dat2[k][parEntry][:]
- rev.reverse()
- if idFirst is None:
- idFirst = 0
- for ll in rev:
- if dHeads[k] in [0, 1, 7]: # MASS has title in index 0 and so BOND, NONB
- dat1[dHeads[k]].insert(idFirst + 1, ll)
- else:
- dat1[dHeads[k]].insert(idFirst, ll)
- dat1[0][0] = mdat[0]
- for k in dat1:
- for line in dat1[k]:
- mdatFile.write(line + '\n')
- return mname
-
- dat2 = splitBlock(open(fdat2).readlines())
- for k in dat1.keys()[:8]:
- if k == 0:
- lines = dat1[k][1:-1] + dat2[k][1:-1] + ['']
- for line in lines:
- mdat.append(line)
- if k == 1:
- for i in dat1[k]:
- if '-' in i:
- id1 = dat1[k].index(i)
- break
- for j in dat2[k]:
- if '-' in j:
- id2 = dat2[k].index(j)
- break
- l1 = dat1[k][:id1]
- l2 = dat2[k][:id2]
- line = ''
- for item in l1 + l2:
- line += item.strip() + ' '
- mdat.append(line)
- lines = dat1[k][id1:-1] + dat2[k][id2:-1] + ['']
- for line in lines:
- mdat.append(line)
- if k in [2, 3, 4, 5, 6]: # angles, p dih, imp dih
- lines = dat1[k][:-1] + dat2[k][:-1] + ['']
- for line in lines:
- mdat.append(line)
- if k == 7:
- lines = dat1[k][:-1] + dat2[k][1:-1] + ['']
- for line in lines:
- mdat.append(line)
- for k in dat1.keys()[8:]:
- for line in dat1[k]:
- mdat.append(line)
- for k in dat2.keys()[9:]:
- for line in dat2[k]:
- mdat.append(line)
- for line in mdat:
- mdatFile.write(line + '\n')
- mdatFile.close()
-
- return mname
-
-
- def _getoutput(cmd):
- '''to simulate commands.getoutput in order to work with python 2.6 up to 3.x'''
- out = sub.Popen(cmd, shell=True, stderr=sub.STDOUT, stdout=sub.PIPE).communicate()[0][:-1]
- try:
- o = str(out.decode())
- except:
- o = str(out)
- return o
-
-
- class AbstractTopol(object):
-
- """
- Super class to build topologies
- """
-
- def __init__(self):
- if self.__class__ is AbstractTopol:
- raise TypeError("Attempt to create istance of abstract class AbstractTopol")
-
- def printDebug(self, text=''):
- if self.debug:
- print('DEBUG: %s' % text)
-
- def printWarn(self, text=''):
- if self.verbose:
- print('WARNING: %s' % text)
-
- def printError(self, text=''):
- if self.verbose:
- print('ERROR: %s' % text)
-
- def printMess(self, text=''):
- if self.verbose:
- print('==> %s' % text)
-
- def printQuoted(self, text=''):
- if self.verbose:
- print(10 * '+' + 'start_quote' + 59 * '+')
- print(text)
- print(10 * '+' + 'end_quote' + 61 * '+')
-
- def guessCharge(self):
- """
- Guess the charge of a system based on antechamber
- Returns None in case of error
- """
- done = False
- error = False
- charge = self.chargeVal
- localDir = os.path.abspath('.')
- if not os.path.exists(self.tmpDir):
- os.mkdir(self.tmpDir)
- if not os.path.exists(os.path.join(self.tmpDir, self.inputFile)):
- copy2(self.absInputFile, self.tmpDir)
- os.chdir(self.tmpDir)
-
- if self.chargeType == 'user':
- if self.ext == '.mol2':
- self.printMess("Reading user's charges from mol2 file...")
- charge = self.readMol2TotalCharge(self.inputFile)
- done = True
- else:
- self.printWarn("cannot read charges from a PDB file")
- self.printWarn("using now 'bcc' method for charge")
-
- if self.chargeVal is None and not done:
- self.printWarn("no charge value given, trying to guess one...")
- mol2FileForGuessCharge = self.inputFile
- if self.ext == ".pdb":
- cmd = '%s -ipdb %s -omol2 %s.mol2' % (self.babelExe, self.inputFile,
- self.baseName)
- self.printDebug("guessCharge: " + cmd)
- out = _getoutput(cmd)
- self.printDebug(out)
- mol2FileForGuessCharge = os.path.abspath(self.baseName + ".mol2")
- in_mol = 'mol2'
- else:
- in_mol = self.ext[1:]
- if in_mol == 'mol':
- in_mol = 'mdl'
-
- cmd = '%s -i %s -fi %s -o tmp -fo mol2 -c gas -pf y' % \
- (self.acExe, mol2FileForGuessCharge, in_mol)
-
- if self.debug:
- self.printMess("Debugging...")
- cmd = cmd.replace('-pf y', '-pf n')
- print(cmd)
-
- log = _getoutput(cmd).strip()
-
- if os.path.exists('tmp'):
- charge = self.readMol2TotalCharge('tmp')
- else:
- try:
- charge = float(log.strip().split('equal to the total charge (')[-1].split(') based on Gasteiger atom type, exit')[0])
- except:
- error = True
-
- if error:
- self.printError("guessCharge failed")
- os.chdir(localDir)
- self.printQuoted(log)
- self.printMess("Trying with net charge = 0 ...")
- # self.chargeVal = 0
- return None
- charge = float(charge)
- charge2 = int(round(charge))
- drift = abs(charge2 - charge)
- self.printDebug("Net charge drift '%3.6f'" % drift)
- if drift > diffTol:
- self.printError("Net charge drift '%3.5f' bigger than tolerance '%3.5f'" % (drift, diffTol))
- if not self.force:
- sys.exit(1)
- self.chargeVal = str(charge2)
- self.printMess("... charge set to %i" % charge2)
- os.chdir(localDir)
-
- def setResNameCheckCoords(self):
- """Set a 3 letter residue name
- and check coords duplication
- """
- exit_ = False
- localDir = os.path.abspath('.')
- if not os.path.exists(self.tmpDir):
- os.mkdir(self.tmpDir)
- # if not os.path.exists(os.path.join(tmpDir, self.inputFile)):
- copy2(self.absInputFile, self.tmpDir)
- os.chdir(self.tmpDir)
-
- exten = self.ext[1:]
- if self.ext == '.pdb':
- tmpFile = open(self.inputFile, 'r')
- else:
- if exten == 'mol':
- exten = 'mdl'
- cmd = '%s -i %s -fi %s -o tmp -fo ac -pf y' % \
- (self.acExe, self.inputFile, exten)
- self.printDebug(cmd)
- out = _getoutput(cmd)
- if not out.isspace():
- self.printDebug(out)
- try:
- tmpFile = open('tmp', 'r')
- except:
- rmtree(self.tmpDir)
- raise
-
- tmpData = tmpFile.readlines()
- residues = set()
- coords = {}
- for line in tmpData:
- if 'ATOM ' in line or 'HETATM' in line:
- residues.add(line[17:20])
- at = line[0:17]
- cs = line[30:54]
- if cs in coords:
- coords[cs].append(at)
- else:
- coords[cs] = [at]
- # self.printDebug(coords)
-
- if len(residues) > 1:
- self.printError("more than one residue detected '%s'" % str(residues))
- self.printError("verify your input file '%s'. Aborting ..." % self.inputFile)
- sys.exit(1)
-
- dups = ""
- shortd = ""
- longd = ""
- longSet = set()
- id_ = 0
- items = list(coords.items())
- l = len(items)
- for item in items:
- id_ += 1
- if len(item[1]) > 1: # if True means atoms with same coordinates
- for i in item[1]:
- dups += "%s %s\n" % (i, item[0])
-
- # for i in xrange(0,len(data),f):
- # fdata += (data[i:i+f])+' '
-
- for id2 in range(id_, l):
- item2 = items[id2]
- c1 = list(map(float, [item[0][i:i + 8] for i in range(0, 24, 8)]))
- c2 = list(map(float, [item2[0][i:i + 8] for i in range(0, 24, 8)]))
- dist2 = self.distance(c1, c2)
- if dist2 < minDist2:
- dist = math.sqrt(dist2)
- shortd += "%8.5f %s %s\n" % (dist, item[1], item2[1])
- if dist2 < maxDist2: # and not longOK:
- longSet.add(str(item[1]))
- longSet.add(str(item2[1]))
- if str(item[1]) not in longSet and l > 1:
- longd += "%s\n" % item[1]
-
- if dups:
- self.printError("Atoms with same coordinates in '%s'!" % self.inputFile)
- self.printQuoted(dups[:-1])
- exit_ = True
-
- if shortd:
- self.printError("Atoms TOO close (< %s Ang.)" % minDist)
- self.printQuoted("Dist (Ang.) Atoms\n" + shortd[:-1])
- exit_ = True
-
- if longd:
- self.printError("Atoms TOO alone (> %s Ang.)" % maxDist)
- self.printQuoted(longd[:-1])
- exit_ = True
-
- if exit_:
- if self.force:
- self.printWarn("You chose to proceed anyway with '-f' option. GOOD LUCK!")
- else:
- self.printError("Use '-f' option if you want to proceed anyway. Aborting ...")
- rmtree(self.tmpDir)
- sys.exit(1)
-
- resname = list(residues)[0].strip()
- newresname = resname
-
- # To avoid resname likes: 001 (all numbers), 1e2 (sci number), ADD : reserved terms for leap
- leapWords = ['_cmd_options_', '_types_', 'add', 'addAtomTypes', 'addIons',
- 'addIons2', 'addPath', 'addPdbAtomMap', 'addPdbResMap', 'alias',
- 'alignAxes', 'bond', 'bondByDistance', 'center', 'charge',
- 'check', 'clearPdbAtomMap', 'clearPdbResMap', 'clearVariables',
- 'combine', 'copy', 'createAtom', 'createParmset', 'createResidue',
- 'createUnit', 'crossLink', 'debugOff', 'debugOn', 'debugStatus',
- 'deleteBond', 'deleteOffLibEntry', 'deleteRestraint', 'desc',
- 'deSelect', 'displayPdbAtomMap', 'displayPdbResMap', 'edit',
- 'flip', 'groupSelectedAtoms', 'help', 'impose', 'list', 'listOff',
- 'loadAmberParams', 'loadAmberPrep', 'loadMol2', 'loadOff',
- 'loadPdb', 'loadPdbUsingSeq', 'logFile', 'matchVariables',
- 'measureGeom', 'quit', 'relax', 'remove', 'restrainAngle',
- 'restrainBond', 'restrainTorsion', 'saveAmberParm',
- 'saveAmberParmPert', 'saveAmberParmPol', 'saveAmberParmPolPert',
- 'saveAmberPrep', 'saveMol2', 'saveOff', 'saveOffParm', 'savePdb',
- 'scaleCharges', 'select', 'sequence', 'set', 'setBox', 'solvateBox',
- 'solvateCap', 'solvateDontClip', 'solvateOct', 'solvateShell',
- 'source', 'transform', 'translate', 'verbosity', 'zMatrix']
- isLeapWord = False
- for word in leapWords:
- if resname.upper().startswith(word.upper()):
- self.printDebug("Residue name is a reserved word: '%s'" % word.upper())
- isLeapWord = True
- try:
- float(resname)
- self.printDebug("Residue name is a 'number': '%s'" % resname)
- isNumber = True
- except ValueError:
- isNumber = False
-
- if resname[0].isdigit() or isNumber or isLeapWord:
- newresname = 'R' + resname
- if not resname.isalnum():
- newresname = 'MOL'
- if newresname != resname:
- self.printWarn("In %s.lib, residue name will be '%s' instead of '%s' elsewhere"
- % (self.acBaseName, newresname, resname))
-
- self.resName = newresname
-
- os.chdir(localDir)
- self.printDebug("setResNameCheckCoords done")
-
- def distance(self, c1, c2):
- # print c1, c2
- dist2 = (c1[0] - c2[0]) ** 2 + (c1[1] - c2[1]) ** 2 + (c1[0] - c2[0]) ** 2 + \
- (c1[2] - c2[2]) ** 2
- # dist2 = math.sqrt(dist2)
- return dist2
-
- def readMol2TotalCharge(self, mol2File):
- """Reads the charges in given mol2 file and returns the total
- """
- charge = 0.0
- ll = []
- cmd = '%s -i %s -fi mol2 -o tmp -fo mol2 -c wc -cf tmp.crg -pf y' % \
- (self.acExe, mol2File)
- if self.debug:
- self.printMess("Debugging...")
- cmd = cmd.replace('-pf y', '-pf n')
-
- self.printDebug(cmd)
-
- log = _getoutput(cmd)
-
- if os.path.exists('tmp.crg'):
- tmpFile = open('tmp.crg', 'r')
- tmpData = tmpFile.readlines()
- for line in tmpData:
- ll += line.split()
- charge = sum(map(float, ll))
- if not log.isspace() and self.debug:
- self.printQuoted(log)
-
- self.printDebug("readMol2TotalCharge: " + str(charge))
-
- return charge
-
- def execAntechamber(self, chargeType=None, atomType=None):
- """ AmaberTools 1.3
- To call Antechamber and execute it
- Usage: antechamber -i input file name
- -fi input file format
- -o output file name
- -fo output file format
- -c charge method
- -cf charge file name
- -nc net molecular charge (int)
- -a additional file name
- -fa additional file format
- -ao additional file operation
- crd only read in coordinate
- crg only read in charge
- name only read in atom name
- type only read in atom type
- bond only read in bond type
- -m multiplicity (2S+1), default is 1
- -rn residue name, overrides input file, default is MOL
- -rf residue toplogy file name in prep input file,
- default is molecule.res
- -ch check file name for gaussian, default is molecule
- -ek mopac or sqm keyword, inside quotes
- -gk gaussian keyword, inside quotes
- -df am1-bcc flag, 2 - use sqm(default); 0 - use mopac
- -at atom type, can be gaff (default), amber, bcc and sybyl
- -du fix duplicate atom names: yes(y)[default] or no(n)
- -j atom type and bond type prediction index, default is 4
- 0 no assignment
- 1 atom type
- 2 full bond types
- 3 part bond types
- 4 atom and full bond type
- 5 atom and part bond type
- -s status information: 0(brief), 1(default) or 2(verbose)
- -pf remove intermediate files: yes(y) or no(n)[default]
- -i -o -fi and -fo must appear; others are optional
- List of the File Formats
- file format type abbre. index | file format type abbre. index
- ---------------------------------------------------------------
- Antechamber ac 1 | Sybyl Mol2 mol2 2
- PDB pdb 3 | Modified PDB mpdb 4
- AMBER PREP (int) prepi 5 | AMBER PREP (car) prepc 6
- Gaussian Z-Matrix gzmat 7 | Gaussian Cartesian gcrt 8
- Mopac Internal mopint 9 | Mopac Cartesian mopcrt 10
- Gaussian Output gout 11 | Mopac Output mopout 12
- Alchemy alc 13 | CSD csd 14
- MDL mdl 15 | Hyper hin 16
- AMBER Restart rst 17 | Jaguar Cartesian jcrt 18
- Jaguar Z-Matrix jzmat 19 | Jaguar Output jout 20
- Divcon Input divcrt 21 | Divcon Output divout 22
- Charmm charmm 23 | SQM Output sqmout 24
- --------------------------------------------------------------
- AMBER restart file can only be read in as additional file.
- List of the Charge Methods
- charge method abbre. index | charge method abbre. index
- ----------------------------------------------------------------
- RESP resp 1 | AM1-BCC bcc 2
- CM1 cm1 3 | CM2 cm2 4
- ESP (Kollman) esp 5 | Mulliken mul 6
- Gasteiger gas 7 | Read in charge rc 8
- Write out charge wc 9 | Delete Charge dc 10
- ----------------------------------------------------------------
- a """
- global pid
-
- self.printMess("Executing Antechamber...")
-
- self.makeDir()
-
- ct = chargeType or self.chargeType
- at = atomType or self.atomType
- if 'amber2' in at:
- at = 'amber'
-
- if ct == 'user':
- ct = ''
- else:
- ct = '-c %s' % ct
-
- exten = self.ext[1:]
- if exten == 'mol':
- exten = 'mdl'
-
- cmd = '%s -i %s -fi %s -o %s -fo mol2 %s -nc %s -m %s -s 2 -df %i -at\
- %s -pf y %s' % (self.acExe, self.inputFile, exten, self.acMol2FileName,
- ct, self.chargeVal, self.multiplicity, self.qFlag, at,
- self.ekFlag)
-
- if self.debug:
- self.printMess("Debugging...")
- cmd = cmd.replace('-pf y', '-pf n')
-
- self.printDebug(cmd)
-
- if os.path.exists(self.acMol2FileName) and not self.force:
- self.printMess("AC output file present... doing nothing")
- else:
- try:
- os.remove(self.acMol2FileName)
- except:
- pass
- signal.signal(signal.SIGALRM, self.signal_handler)
- signal.alarm(self.timeTol)
- p = sub.Popen(cmd, shell=True, stderr=sub.STDOUT, stdout=sub.PIPE)
- pid = p.pid
-
- out = str(p.communicate()[0].decode()) # p.stdout.read()
- self.acLog = out
-
- if os.path.exists(self.acMol2FileName):
- self.printMess("* Antechamber OK *")
- else:
- self.printQuoted(self.acLog)
- return True
-
- def signal_handler(self, _signum, _frame): # , pid = 0):
- global pid
- pids = self.job_pids_family(pid)
- self.printDebug("PID: %s, PIDS: %s" % (pid, pids))
- self.printMess("Timed out! Process %s killed, max exec time (%ss) exceeded"
- % (pids, self.timeTol))
- # os.system('kill -15 %s' % pids)
- for i in pids.split():
- os.kill(int(i), 15)
- raise Exception("Semi-QM taking too long to finish... aborting!")
-
- def job_pids_family(self, jpid):
- '''INTERNAL: Return all job processes (PIDs)'''
- pid = repr(jpid)
- dict_pids = {}
- pids = [pid]
- cmd = "ps -A -o uid,pid,ppid|grep %i" % os.getuid()
- out = _getoutput(cmd).split('\n') # getoutput("ps -A -o uid,pid,ppid|grep %i" % os.getuid()).split('\n')
- for item in out:
- vec = item.split()
- dict_pids[vec[2]] = vec[1]
- while 1:
- try:
- pid = dict_pids[pid]
- pids.append(pid)
- except KeyError:
- break
- return ' '.join(pids)
-
- def delOutputFiles(self):
- delFiles = ['mopac.in', 'tleap.in', 'sleap.in', 'fixbo.log',
- 'addhs.log', 'ac_tmp_ot.mol2', 'frcmod.ac_tmp', 'fragment.mol2',
- self.tmpDir] # , 'divcon.pdb', 'mopac.pdb', 'mopac.out'] #'leap.log'
- self.printMess("Removing temporary files...")
- for file_ in delFiles:
- file_ = os.path.join(self.absHomeDir, file_)
- if os.path.exists(file_):
- if os.path.isdir(file_):
- rmtree(file_)
- else:
- os.remove(file_)
-
- def checkXyzAndTopFiles(self):
- fileXyz = self.acXyzFileName
- fileTop = self.acTopFileName
- if os.path.exists(fileXyz) and os.path.exists(fileTop):
- # self.acXyz = fileXyz
- # self.acTop = fileTop
- return True
- return False
-
- def execSleap(self):
- global pid
- self.makeDir()
-
- if self.ext == '.mol2':
- self.printWarn("Sleap doesn't work with mol2 files yet...")
- return True
-
- if self.chargeType != 'bcc':
- self.printWarn("Sleap works only with bcc charge method")
- return True
-
- if self.atomType != 'gaff':
- self.printWarn("Sleap works only with gaff atom type")
- return True
-
- sleapScpt = SLEAP_TEMPLATE % self.acParDict
-
- fp = open('sleap.in', 'w')
- fp.write(sleapScpt)
- fp.close()
-
- cmd = '%s -f sleap.in' % self.sleapExe
-
- if self.checkXyzAndTopFiles() and not self.force:
- self.printMess("Topologies files already present... doing nothing")
- else:
- try:
- os.remove(self.acTopFileName)
- os.remove(self.acXyzFileName)
- except:
- pass
- self.printMess("Executing Sleap...")
- self.printDebug(cmd)
-
- p = sub.Popen(cmd, shell=True, stderr=sub.STDOUT, stdout=sub.PIPE)
- pid = p.pid
- signal.signal(signal.SIGALRM, self.signal_handler)
- signal.alarm(self.timeTol)
-
- out = str(p.communicate()[0].decode()) # p.stdout.read()
-
- self.sleapLog = out
- self.checkLeapLog(self.sleapLog)
-
- if self.checkXyzAndTopFiles():
- self.printMess(" * Sleap OK *")
- else:
- self.printQuoted(self.sleapLog)
- return True
-
- def execTleap(self):
-
- fail = False
-
- self.makeDir()
-
- if self.ext == ".pdb":
- self.printMess('... converting pdb input file to mol2 input file')
- if self.convertPdbToMol2():
- self.printError("convertPdbToMol2 failed")
-
- # print self.chargeVal
-
- if self.execAntechamber():
- self.printError("Antechamber failed")
- fail = True
- # sys.exit(1)
-
- if self.execParmchk():
- self.printError("Parmchk failed")
- fail = True
- # sys.exit(1)
-
- if fail:
- return True
-
- tleapScpt = TLEAP_TEMPLATE % self.acParDict
-
- fp = open('tleap.in', 'w')
- fp.write(tleapScpt)
- fp.close()
-
- cmd = '%s -f tleap.in' % self.tleapExe
-
- if self.checkXyzAndTopFiles() and not self.force:
- self.printMess("Topologies files already present... doing nothing")
- else:
- try:
- os.remove(self.acTopFileName)
- os.remove(self.acXyzFileName)
- except:
- pass
- self.printMess("Executing Tleap...")
- self.printDebug(cmd)
- self.tleapLog = _getoutput(cmd)
- self.checkLeapLog(self.tleapLog)
-
- if self.checkXyzAndTopFiles():
- self.printMess("* Tleap OK *")
- else:
- self.printQuoted(self.tleapLog)
- return True
-
- def checkLeapLog(self, log):
- log = log.splitlines(True)
- check = ''
- block = False
- for line in log:
- # print "*"+line+"*"
- if "Checking '" in line:
- # check += line
- block = True
- if "Checking Unit." in line:
- block = False
- if block:
- check += line
- self.printQuoted(check[:-1])
-
- def locateDat(self, aFile):
- '''locate a file pertinent to $AMBERHOME/dat/leap/parm/'''
- amberhome = os.environ.get('AMBERHOME')
- if amberhome:
- aFileF = os.path.join(amberhome, 'dat/leap/parm', aFile)
- if os.path.exists(aFileF):
- return aFileF
- aFileF = os.path.join(os.path.dirname(self.acExe), '../dat/leap/parm', aFile)
- if os.path.exists(aFileF):
- return aFileF
- return None
-
- def execParmchk(self):
-
- self.makeDir()
- cmd = '%s -i %s -f mol2 -o %s' % (self.parmchkExe, self.acMol2FileName,
- self.acFrcmodFileName)
-
- if 'amber' in self.atomType:
- gaffFile = self.locateDat(self.gaffDatfile)
- parmfile = self.locateDat('parm10.dat')
- frcmodffxxSB = self.locateDat('frcmod.ff14SB')
- # frcmodparmbsc0 = self.locateDat('frcmod.parmbsc0')
- parmGaffFile = parmMerge(parmfile, gaffFile)
- parmGaffffxxSBFile = parmMerge(parmGaffFile, frcmodffxxSB, frcmod=True)
- # parm99gaffff99SBparmbsc0File = parmMerge(parm99gaffff99SBFile, frcmodparmbsc0, frcmod = True)
- # parm10file = self.locateDat('parm10.dat') # PARM99 + frcmod.ff99SB + frcmod.parmbsc0 in AmberTools 1.4
-
- cmd += ' -p %s' % parmGaffffxxSBFile # Ignoring BSC0
- elif 'gaff2' in self.atomType:
- cmd += ' -s 2'
-
- self.parmchkLog = _getoutput(cmd)
-
- self.printDebug(cmd)
-
- if os.path.exists(self.acFrcmodFileName):
- check = self.checkFrcmod()
- if check:
- self.printWarn("Couldn't determine all parameters:")
- self.printMess("From file '%s'\n" % self.acFrcmodFileName + check)
- else:
- self.printMess("* Parmchk OK *")
- else:
- self.printQuoted(self.parmchkLog)
- return True
-
- def checkFrcmod(self):
- check = ""
- frcmodContent = open(self.acFrcmodFileName, 'r').readlines()
- for line in frcmodContent:
- if "ATTN, need revision" in line:
- check += line
- return check
-
- def convertPdbToMol2(self):
- if self.ext == '.pdb':
- if self.execBabel():
- self.printError("convert pdb to mol2 via babel failed")
- return True
-
- def execBabel(self):
-
- self.makeDir()
-
- cmd = '%s -ipdb %s -omol2 %s.mol2' % (self.babelExe, self.inputFile,
- self.baseName)
- self.printDebug(cmd)
- self.babelLog = _getoutput(cmd)
- self.ext = '.mol2'
- self.inputFile = self.baseName + self.ext
- self.acParDict['ext'] = 'mol2'
- if os.path.exists(self.inputFile):
- self.printMess("* Babel OK *")
- else:
- self.printQuoted(self.babelLog)
- return True
-
- def makeDir(self):
-
- os.chdir(self.rootDir)
- self.absHomeDir = os.path.abspath(self.homeDir)
- if not os.path.exists(self.homeDir):
- os.mkdir(self.homeDir)
- os.chdir(self.homeDir)
- copy2(self.absInputFile, '.')
-
- return True
-
- def createACTopol(self):
- """
- If successful, Amber Top and Xyz files will be generated
- """
- # sleap = False
- if self.engine == 'sleap':
- if self.execSleap():
- self.printError("Sleap failed")
- self.printMess("... trying Tleap")
- if self.execTleap():
- self.printError("Tleap failed")
- if self.engine == 'tleap':
- if self.execTleap():
- self.printError("Tleap failed")
- if self.extOld == '.pdb':
- self.printMess("... trying Sleap")
- self.ext = self.extOld
- self.inputFile = self.baseName + self.ext
- if self.execSleap():
- self.printError("Sleap failed")
- if not self.debug:
- self.delOutputFiles()
-
- def createMolTopol(self):
- """
- Create molTop obj
- """
- self.topFileData = open(self.acTopFileName, 'r').readlines()
- self.molTopol = MolTopol(self, verbose=self.verbose, debug=self.debug,
- gmx4=self.gmx4, disam=self.disam, direct=self.direct,
- is_sorted=self.sorted, chiral=self.chiral)
- if self.outTopols:
- if 'cns' in self.outTopols:
- self.molTopol.writeCnsTopolFiles()
- if 'gmx' in self.outTopols:
- self.molTopol.writeGromacsTopolFiles()
- if 'charmm' in self.outTopols:
- self.writeCharmmTopolFiles()
- self.pickleSave()
-
- def pickleSave(self):
- """
- To restore:
- from acpype import *
- #import cPickle as pickle
- import pickle
- o = pickle.load(open('DDD.pkl','rb'))
- NB: It fails to restore with ipython in Mac (Linux OK)
- """
- pklFile = self.baseName + ".pkl"
- dumpFlag = False
- if not os.path.exists(pklFile):
- mess = "Writing pickle file %s" % pklFile
- dumpFlag = True
- elif self.force:
- mess = "Overwriting pickle file %s" % pklFile
- dumpFlag = True
- else:
- mess = "Pickle file %s already present... doing nothing" % pklFile
- self.printMess(mess)
- if dumpFlag:
- with open(pklFile, "wb") as f: # for python 2.6 or higher
- # f = open(pklFile, "wb")
- if verList[0] == 3:
- pickle.dump(self, f, protocol=2, fix_imports=True)
- else:
- pickle.dump(self, f, protocol=2)
-
- def getFlagData(self, flag):
- """
- For a given acFileTop flag, return a list of the data related
- """
- block = False
- tFlag = '%FLAG ' + flag
- data = ''
-
- if len(self.topFileData) == 0:
- raise Exception("PRMTOP file empty?")
-
- for rawLine in self.topFileData:
- if '%COMMENT' in rawLine:
- continue
- line = rawLine.replace('\r', '').replace('\n', '')
- if tFlag in line:
- block = True
- continue
- if block and '%FLAG ' in line:
- break
- if block:
- if '%FORMAT' in line:
- line = line.strip().strip('%FORMAT()').split('.')[0]
- for c in line:
- if c.isalpha():
- f = int(line.split(c)[1])
- break
- continue
- data += line
- # data need format
- sdata = [data[i:i + f].strip() for i in range(0, len(data), f)]
- if '+' and '.' in data and flag != 'RESIDUE_LABEL': # it's a float
- ndata = list(map(float, sdata))
- elif flag != 'RESIDUE_LABEL':
- try: # try if it's integer
- ndata = list(map(int, sdata))
- except: # it's string
- ndata = sdata
- else:
- ndata = sdata
- if flag == 'AMBER_ATOM_TYPE':
- nn = []
- ll = set()
- prefixed = False
- for ii in ndata:
- prefixed = True
- if ii[0].isdigit():
- ll.add(ii)
- ii = 'A' + ii
- nn.append(ii)
- if prefixed and ll:
- self.printDebug("GMX does not like atomtype starting with Digit")
- self.printDebug("prefixing AtomType %s with 'A'." % list(ll))
- ndata = nn
- return ndata # a list
-
- def getResidueLabel(self):
- """
- Get a 3 capital letters code from acFileTop
- Returns a list.
- """
- residueLabel = self.getFlagData('RESIDUE_LABEL')
- residueLabel = list(map(str, residueLabel))
- if residueLabel[0] != residueLabel[0].upper():
- self.printWarn("residue label '%s' in '%s' is not all UPPERCASE" %
- (residueLabel[0], self.inputFile))
- self.printWarn("this may raise problem with some applications like CNS")
- self.residueLabel = residueLabel
-
- def getCoords(self):
- """
- For a given acFileXyz file, return a list of coords as:
- [[x1,y1,z1],[x2,y2,z2], etc.]
- """
- if len(self.xyzFileData) == 0:
- raise Exception("INPCRD file empty?")
- data = ''
- for rawLine in self.xyzFileData[2:]:
- line = rawLine.replace('\r', '').replace('\n', '')
- data += line
- l = len(data)
- ndata = list(map(float, [data[i:i + 12] for i in range(0, l, 12)]))
-
- gdata = []
- for i in range(0, len(ndata), 3):
- gdata.append([ndata[i], ndata[i + 1], ndata[i + 2]])
-
- self.printDebug("getCoords done")
-
- return gdata
-
- def getAtoms(self):
- """
- Set a list with all atoms objects build from dat in acFileTop
- Set also if molTopol atom type system is gaff or amber
- Set also list atomTypes
- Set also resid
- Set also molTopol total charge
- """
- atomNameList = self.getFlagData('ATOM_NAME')
- atomTypeNameList = self.getFlagData('AMBER_ATOM_TYPE')
- self._atomTypeNameList = atomTypeNameList
- massList = self.getFlagData('MASS')
- chargeList = self.getFlagData('CHARGE')
- # totalCharge = sum(chargeList)
- # self.printDebug('charge to be balanced: total %13.10f' % (totalCharge/qConv))
-
- resIds = self.getFlagData('RESIDUE_POINTER') + [0]
- # to guess the resId of the last residue before ion or water
- # for resTemp in self.residueLabel:
- # if resTemp in ionOrWaterResNameList:
- # lastSoluteResId = self.residueLabel.index(resTemp) - 1
- # break
- # print lastSoluteResId, self.residueLabel[lastSoluteResId]
- # uniqAtomTypeId = self.getFlagData('ATOM_TYPE_INDEX') # for LJ
- # balanceChargeList = self.balanceCharges(chargeList)
- coords = self.getCoords()
- ACOEFs, BCOEFs = self.getABCOEFs()
-
- atoms = []
- atomTypes = []
- tmpList = [] # a list with unique atom types
- totalCharge = 0.0
- countRes = 0
- id_ = 0
- FirstNonSoluteId = None
- for atomName in atomNameList:
- if atomName != atomName.upper():
- self.printDebug("atom name '%s' HAS to be all UPPERCASE... Applying this here." %
- atomName)
- atomName = atomName.upper()
- atomTypeName = atomTypeNameList[id_]
- if id_ + 1 == resIds[countRes]:
- resid = countRes # self.residueLabel[countRes]
- countRes += 1
- resName = self.residueLabel[resid]
- if resName in ionOrSolResNameList and not FirstNonSoluteId:
- FirstNonSoluteId = id_
- # print id_, resid, resName
- mass = massList[id_]
- # charge = balanceChargeList[id_]
- charge = chargeList[id_]
- chargeConverted = charge / qConv
- totalCharge += charge
- coord = coords[id_]
- ACOEF = ACOEFs[id_]
- BCOEF = BCOEFs[id_]
- atomType = AtomType(atomTypeName, mass, ACOEF, BCOEF)
- if atomTypeName not in tmpList:
- tmpList.append(atomTypeName)
- atomTypes.append(atomType)
- atom = Atom(atomName, atomType, id_ + 1, resid, mass, chargeConverted, coord)
- atoms.append(atom)
- id_ += 1
-
- balanceChargeList, balanceValue, balanceIds = self.balanceCharges(chargeList, FirstNonSoluteId)
-
- for id_ in balanceIds:
- atoms[id_].charge = balanceValue / qConv
- # self.printDebug("atom ids and balanced charges: %s, %3f10" % (balanceIds, balanceValue/qConv))
-
- if atomTypeName[0].islower():
- self.atomTypeSystem = 'gaff'
- else:
- self.atomTypeSystem = 'amber'
-
- self.printDebug('Balanced TotalCharge %13.10f' % float(sum(balanceChargeList) / qConv))
- self.totalCharge = int(totalCharge)
-
- self.atoms = atoms
- self.atomTypes = atomTypes
-
- self.pbc = None
- if len(coords) == len(atoms) + 2 or len(coords) == len(atoms) * 2 + 2:
- self.pbc = [coords[-2], coords[-1]]
- self.printDebug("PBC = %s" % self.pbc)
- self.printDebug("getAtoms done")
-
- def getBonds(self):
- uniqKbList = self.getFlagData('BOND_FORCE_CONSTANT')
- uniqReqList = self.getFlagData('BOND_EQUIL_VALUE')
- bondCodeHList = self.getFlagData('BONDS_INC_HYDROGEN')
- bondCodeNonHList = self.getFlagData('BONDS_WITHOUT_HYDROGEN')
- bondCodeList = bondCodeHList + bondCodeNonHList
- bonds = []
- for i in range(0, len(bondCodeList), 3):
- idAtom1 = bondCodeList[i] // 3 # remember python starts with id 0
- idAtom2 = bondCodeList[i + 1] // 3
- bondTypeId = bondCodeList[i + 2] - 1
- atom1 = self.atoms[idAtom1]
- atom2 = self.atoms[idAtom2]
- kb = uniqKbList[bondTypeId]
- req = uniqReqList[bondTypeId]
- atoms = [atom1, atom2]
- bond = Bond(atoms, kb, req)
- bonds.append(bond)
- self.bonds = bonds
- self.printDebug("getBonds done")
-
- def getAngles(self):
- uniqKtList = self.getFlagData('ANGLE_FORCE_CONSTANT')
- uniqTeqList = self.getFlagData('ANGLE_EQUIL_VALUE')
- # for list below, true atom number = index/3 + 1
- angleCodeHList = self.getFlagData('ANGLES_INC_HYDROGEN')
- angleCodeNonHList = self.getFlagData('ANGLES_WITHOUT_HYDROGEN')
- angleCodeList = angleCodeHList + angleCodeNonHList
- angles = []
- for i in range(0, len(angleCodeList), 4):
- idAtom1 = angleCodeList[i] // 3 # remember python starts with id 0
- idAtom2 = angleCodeList[i + 1] // 3
- idAtom3 = angleCodeList[i + 2] // 3
- angleTypeId = angleCodeList[i + 3] - 1
- atom1 = self.atoms[idAtom1]
- atom2 = self.atoms[idAtom2]
- atom3 = self.atoms[idAtom3]
- kt = uniqKtList[angleTypeId]
- teq = uniqTeqList[angleTypeId] # angle given in rad in prmtop
- atoms = [atom1, atom2, atom3]
- angle = Angle(atoms, kt, teq)
- angles.append(angle)
- self.angles = angles
- self.printDebug("getAngles done")
-
- def getDihedrals(self):
- """
- Get dihedrals (proper and imp), condensed list of prop dih and
- atomPairs
- """
- uniqKpList = self.getFlagData('DIHEDRAL_FORCE_CONSTANT')
- uniqPeriodList = self.getFlagData('DIHEDRAL_PERIODICITY')
- uniqPhaseList = self.getFlagData('DIHEDRAL_PHASE')
- # for list below, true atom number = abs(index)/3 + 1
- dihCodeHList = self.getFlagData('DIHEDRALS_INC_HYDROGEN')
- dihCodeNonHList = self.getFlagData('DIHEDRALS_WITHOUT_HYDROGEN')
- dihCodeList = dihCodeHList + dihCodeNonHList
- properDih = []
- improperDih = []
- condProperDih = [] # list of dihedrals condensed by the same quartet
- # atomPairs = []
- atomPairs = set()
- for i in range(0, len(dihCodeList), 5):
- idAtom1 = dihCodeList[i] // 3 # remember python starts with id 0
- idAtom2 = dihCodeList[i + 1] // 3
- # 3 and 4 indexes can be negative: if id3 < 0, end group interations
- # in amber are to be ignored; if id4 < 0, dihedral is improper
- idAtom3raw = dihCodeList[i + 2] // 3 # can be negative -> exclude from 1-4vdw
- idAtom4raw = dihCodeList[i + 3] // 3 # can be negative -> Improper
- idAtom3 = abs(idAtom3raw)
- idAtom4 = abs(idAtom4raw)
- dihTypeId = dihCodeList[i + 4] - 1
- atom1 = self.atoms[idAtom1]
- atom2 = self.atoms[idAtom2]
- atom3 = self.atoms[idAtom3]
- atom4 = self.atoms[idAtom4]
- kPhi = uniqKpList[dihTypeId] # already divided by IDIVF
- period = int(uniqPeriodList[dihTypeId]) # integer
- phase = uniqPhaseList[dihTypeId] # angle given in rad in prmtop
- if phase == kPhi == 0:
- period = 0 # period is set to 0
- atoms = [atom1, atom2, atom3, atom4]
- dihedral = Dihedral(atoms, kPhi, period, phase)
- if idAtom4raw > 0:
- try:
- atomsPrev = properDih[-1].atoms
- except:
- atomsPrev = []
- properDih.append(dihedral)
- if idAtom3raw < 0 and atomsPrev == atoms:
- condProperDih[-1].append(dihedral)
- else:
- condProperDih.append([dihedral])
- pair = (atom1, atom4)
- # if atomPairs.count(pair) == 0 and idAtom3raw > 0:
- if idAtom3raw > 0:
- atomPairs.add(pair)
- else:
- improperDih.append(dihedral)
- try:
- atomPairs = sorted(atomPairs)
- except:
- pass
- self.properDihedrals = properDih
- self.improperDihedrals = improperDih
- self.condensedProperDihedrals = condProperDih # [[],[],...]
- self.atomPairs = atomPairs # set((atom1, atom2), ...)
- self.printDebug("getDihedrals done")
-
- def getChirals(self):
- """
- Get chiral atoms, its 4 neighbours and improper dihedral angle
- """
- self.chiralGroups = []
- if self.obchiralExe:
- # print (self.obchiralExe, os.getcwd())
- cmd = '%s %s' % (self.obchiralExe, self.inputFile)
- # print(cmd)
- out = map(int, re.findall('Atom (\d+) Is', _getoutput(cmd)))
- # print("*%s*" % out)
- chiralGroups = []
- for id_ in out:
- atChi = self.atoms[id_ - 1]
- quad = []
- for bb in self.bonds:
- bAts = bb.atoms[:]
- if atChi in bAts:
- bAts.remove(atChi)
- quad.append(bAts[0])
- if len(quad) != 4:
- if self.chiral:
- self.printWarn("Atom %s has less than 4 connections to 4 different atoms. It's NOT Chiral!" % atChi)
- continue
- v1, v2, v3, v4 = [x.coords for x in quad]
- chiralGroups.append((atChi, quad, imprDihAngle(v1, v2, v3, v4)))
- self.chiralGroups = chiralGroups
-
- def sortAtomsForGromacs(self):
- """
- Re-sort atoms for gromacs, which expects all hydrogens to immediately
- follow the heavy atom they are bonded to and belong to the same charge
- group.
- Currently, atom mass < 1.2 is taken to denote a proton. This behavior
- may be changed by modifying the 'is_hydrogen' function within.
- JDC 2011-02-03
- """
-
- # Build dictionary of bonded atoms.
- bonded_atoms = dict()
- for atom in self.atoms:
- bonded_atoms[atom] = list()
- for bond in self.bonds:
- [atom1, atom2] = bond.atoms
- bonded_atoms[atom1].append(atom2)
- bonded_atoms[atom2].append(atom1)
-
- # Define hydrogen and heavy atom classes.
- def is_hydrogen(atom):
- return (atom.mass < 1.2)
-
- def is_heavy(atom):
- return not is_hydrogen(atom)
-
- # Build list of sorted atoms, assigning charge groups by heavy atom.
- sorted_atoms = list()
- cgnr = 1 # charge group number: each heavy atoms is assigned its own charge group
- # First pass: add heavy atoms, followed by the hydrogens bonded to them.
- for atom in self.atoms:
- if is_heavy(atom):
- # Append heavy atom.
- atom.cgnr = cgnr
- sorted_atoms.append(atom)
- # Append all hydrogens.
- for bonded_atom in bonded_atoms[atom]:
- if is_hydrogen(bonded_atom) and not (bonded_atom in sorted_atoms):
- # Append bonded hydrogen.
- bonded_atom.cgnr = cgnr
- sorted_atoms.append(bonded_atom)
- cgnr += 1
-
- # Second pass: Add any remaining atoms.
- if len(sorted_atoms) < len(self.atoms):
- for atom in self.atoms:
- if not (atom in sorted_atoms):
- atom.cgnr = cgnr
- sorted_atoms.append(atom)
- cgnr += 1
-
- # Replace current list of atoms with sorted list.
- self.atoms = sorted_atoms
-
- # Renumber atoms in sorted list, starting from 1.
- for (index, atom) in enumerate(self.atoms):
- atom.id = index + 1
-
- return
-
- def setAtomPairs(self):
- """
- Set a list of pair of atoms pertinent to interaction 1-4 for vdw.
- WRONG: Deprecated
- """
- atomPairs = []
- for item in self.condensedProperDihedrals:
- dih = item[0]
- atom1 = dih.atoms[0]
- atom2 = dih.atoms[3]
- pair = [atom1, atom2]
- if atomPairs.count(pair) == 0:
- atomPairs.append(pair)
- self.atomPairs = atomPairs # [[atom1, atom2], ...]
- self.printDebug("atomPairs done")
-
- def getExcludedAtoms(self):
- """
- Returns a list of atoms with a list of its excluded atoms up to 3rd
- neighbour.
- It's implicitly indexed, i.e., a sequence of atoms in position n in
- the excludedAtomsList corresponds to atom n (self.atoms) and so on.
- NOT USED
- """
- excludedAtomsIdList = self.getFlagData('EXCLUDED_ATOMS_LIST')
- numberExcludedAtoms = self.getFlagData('NUMBER_EXCLUDED_ATOMS')
- atoms = self.atoms
- interval = 0
- excludedAtomsList = []
- for number in numberExcludedAtoms:
- temp = excludedAtomsIdList[interval:interval + number]
- if temp == [0]:
- excludedAtomsList.append([])
- else:
- excludedAtomsList.append([atoms[a - 1] for a in temp])
- interval += number
- self.excludedAtoms = excludedAtomsList
- self.printDebug("getExcludedAtoms")
-
- def balanceCharges(self, chargeList, FirstNonSoluteId=None):
- """
- Note that python is very annoying about floating points.
- Even after balance, there will always be some residue of order e-12
- to e-16, which is believed to vanished once one writes a topology
- file, say, for CNS or GMX, where floats are represented with 4 or 5
- maximum decimals.
- """
- limIds = []
- # self.printDebug(chargeList)
- total = sum(chargeList)
- totalConverted = total / qConv
- self.printDebug('charge to be balanced: total %13.10f' % (totalConverted))
- maxVal = max(chargeList[:FirstNonSoluteId])
- minVal = min(chargeList[:FirstNonSoluteId])
- if abs(maxVal) >= abs(minVal):
- lim = maxVal
- else:
- lim = minVal
- nLims = chargeList.count(lim)
- # limId = chargeList.index(lim)
- diff = totalConverted - round(totalConverted)
- fix = lim - diff * qConv / nLims
- id_ = 0
- for c in chargeList:
- if c == lim:
- limIds.append(id_)
- chargeList[id_] = fix
- id_ += 1
- # self.printDebug(chargeList)
- self.printDebug("balanceCharges done")
- return chargeList, fix, limIds
-
- def getABCOEFs(self):
- uniqAtomTypeIdList = self.getFlagData('ATOM_TYPE_INDEX')
- nonBonIdList = self.getFlagData('NONBONDED_PARM_INDEX')
- rawACOEFs = self.getFlagData('LENNARD_JONES_ACOEF')
- rawBCOEFs = self.getFlagData('LENNARD_JONES_BCOEF')
- # print nonBonIdList, len(nonBonIdList), rawACOEFs, len(rawACOEFs)
- ACOEFs = []
- BCOEFs = []
- ntypes = max(uniqAtomTypeIdList)
- # id_ = 0
- # for atName in self._atomTypeNameList:
- for id_ in range(len(self._atomTypeNameList)):
- # id_ = self._atomTypeNameList.index(atName)
- atomTypeId = uniqAtomTypeIdList[id_]
- index = ntypes * (atomTypeId - 1) + atomTypeId
- nonBondId = nonBonIdList[index - 1]
- # print "*****", index, ntypes, atName, id_, atomTypeId, nonBondId
- ACOEFs.append(rawACOEFs[nonBondId - 1])
- BCOEFs.append(rawBCOEFs[nonBondId - 1])
- # id_ += 1
- # print ACOEFs
- self.printDebug("getABCOEFs done")
- return ACOEFs, BCOEFs
-
- def setProperDihedralsCoef(self):
- """
- It takes self.condensedProperDihedrals and returns
- self.properDihedralsCoefRB, a reduced list of quartet atoms + RB.
- Coeficients ready for GMX (multiplied by 4.184)
- self.properDihedralsCoefRB = [ [atom1,..., atom4], C[0:5] ]
- For proper dihedrals: a quartet of atoms may appear with more than
- one set of parameters and to convert to GMX they are treated as RBs.
- The resulting coefs calculated here may look slighted different from
- the ones calculated by amb2gmx.pl because python is taken full float
- number from prmtop and not rounded numbers from rdparm.out as
- amb2gmx.pl does.
- """
- properDihedralsCoefRB = []
- properDihedralsAlphaGamma = []
- properDihedralsGmx45 = []
- for item in self.condensedProperDihedrals:
- V = 6 * [0.0]
- C = 6 * [0.0]
- for dih in item:
- period = dih.period # Pn
- kPhi = dih.kPhi # in rad
- phaseRaw = dih.phase * radPi # in degree
- phase = int(phaseRaw) # in degree
- if period > 4 and self.gmx4:
- self.printError("Likely trying to convert ILDN to RB, DO NOT use option '-z'")
- sys.exit(1)
- if phase in [0, 180]:
- properDihedralsGmx45.append([item[0].atoms, phaseRaw, kPhi, period])
- if self.gmx4:
- if kPhi > 0:
- V[period] = 2 * kPhi * cal
- if period == 1:
- C[0] += 0.5 * V[period]
- if phase == 0:
- C[1] -= 0.5 * V[period]
- else:
- C[1] += 0.5 * V[period]
- elif period == 2:
- if phase == 180:
- C[0] += V[period]
- C[2] -= V[period]
- else:
- C[2] += V[period]
- elif period == 3:
- C[0] += 0.5 * V[period]
- if phase == 0:
- C[1] += 1.5 * V[period]
- C[3] -= 2 * V[period]
- else:
- C[1] -= 1.5 * V[period]
- C[3] += 2 * V[period]
- elif period == 4:
- if phase == 180:
- C[2] += 4 * V[period]
- C[4] -= 4 * V[period]
- else:
- C[0] += V[period]
- C[2] -= 4 * V[period]
- C[4] += 4 * V[period]
- else:
- properDihedralsAlphaGamma.append([item[0].atoms, phaseRaw, kPhi, period])
- # print phaseRaw, kPhi, period
- if phase in [0, 180]:
- properDihedralsCoefRB.append([item[0].atoms, C])
-
- # print properDihedralsCoefRB
- # print properDihedralsAlphaGamma
-
- self.printDebug("setProperDihedralsCoef done")
-
- self.properDihedralsCoefRB = properDihedralsCoefRB
- self.properDihedralsAlphaGamma = properDihedralsAlphaGamma
- self.properDihedralsGmx45 = properDihedralsGmx45
-
- def writeCharmmTopolFiles(self):
-
- self.printMess("Writing CHARMM files\n")
-
- # self.makeDir()
-
- at = self.atomType
- self.getResidueLabel()
- res = self.resName # self.residueLabel[0]
- # print res, self.residueLabel, type(self.residueLabel)
-
- cmd = '%s -i %s -fi mol2 -o %s -fo charmm -s 2 -at %s \
- -pf y -rn %s' % (self.acExe, self.acMol2FileName, self.charmmBase,
- at, res)
-
- if self.debug:
- cmd = cmd.replace('-pf y', '-pf n')
- self.printDebug(cmd)
- _log = _getoutput(cmd)
-
- def writePdb(self, file_):
- """
- Write a new PDB file_ with the atom names defined by Antechamber
- Input: file_ path string
- The format generated here use is slightly different from
- http://www.wwpdb.org/documentation/format23/sect9.html respected to
- atom name
- """
- # TODO: assuming only one residue ('1')
- pdbFile = open(file_, 'w')
- fbase = os.path.basename(file_)
- pdbFile.write("REMARK " + head % (fbase, date))
- id_ = 1
- for atom in self.atoms:
- # id_ = self.atoms.index(atom) + 1
- aName = atom.atomName
- if len(aName) == 2:
- aName = ' %s ' % aName
- elif len(aName) == 1:
- aName = ' %s ' % aName
- for l in aName:
- if l.isalpha():
- s = l
- break
- rName = self.residueLabel[0]
- x = atom.coords[0]
- y = atom.coords[1]
- z = atom.coords[2]
- line = "%-6s%5d %4s %3s Z%4d%s%8.3f%8.3f%8.3f%6.2f%6.2f%s%2s\n" % \
- ('ATOM', id_, aName, rName, 1, 4 * ' ', x, y, z, 1.0, 0.0, 10 * ' ', s)
- pdbFile.write(line)
- id_ += 1
- pdbFile.write('END\n')
-
- def writeGromacsTopolFiles(self, amb2gmx=False):
- """
- # from ~/Programmes/amber10/dat/leap/parm/gaff.dat
- #atom type atomic mass atomic polarizability comments
- ca 12.01 0.360 Sp2 C in pure aromatic systems
- ha 1.008 0.135 H bonded to aromatic carbon
- #bonded atoms harmonic force kcal/mol/A^2 eq. dist. Ang. comments
- ca-ha 344.3* 1.087** SOURCE3 1496 0.0024 0.0045
- * for gmx: 344.3 * 4.184 * 100 * 2 = 288110 kJ/mol/nm^2 (why factor 2?)
- ** convert Ang to nm ( div by 10) for gmx: 1.087 A = 0.1087 nm
- # CA HA 1 0.10800 307105.6 ; ged from 340. bsd on C6H6 nmodes; PHE,TRP,TYR (from ffamber99bon.itp)
- # CA-HA 367.0 1.080 changed from 340. bsd on C6H6 nmodes; PHE,TRP,TYR (from parm99.dat)
- # angle HF kcal/mol/rad^2 eq angle degrees comments
- ca-ca-ha 48.5* 120.01 SOURCE3 2980 0.1509 0.2511
- * to convert to gmx: 48.5 * 4.184 * 2 = 405.848 kJ/mol/rad^2 (why factor 2?)
- # CA CA HA 1 120.000 418.400 ; new99 (from ffamber99bon.itp)
- # CA-CA-HA 50.0 120.00 (from parm99.dat)
- # dihedral idivf barrier hight/2 kcal/mol phase degrees periodicity comments
- X -ca-ca-X 4 14.500* 180.000 2.000 intrpol.bsd.on C6H6
- * to convert to gmx: 14.5/4 * 4.184 * 2 (?) (yes in amb2gmx, not in topolbuild, why?) = 30.334 or 15.167 kJ/mol
- # X -CA-CA-X 4 14.50 180.0 2. intrpol.bsd.on C6H6 (from parm99.dat)
- # X CA CA X 3 30.33400 0.00000 -30.33400 0.00000 0.00000 0.00000 ; intrpol.bsd.on C6H6
- ;propers treated as RBs in GROMACS to use combine multiple AMBER torsions per quartet (from ffamber99bon.itp)
- # impr. dihedral barrier hight/2 phase degrees periodicity comments
- X -X -ca-ha 1.1* 180. 2. bsd.on C6H6 nmodes
- * to convert to gmx: 1.1 * 4.184 = 4.6024 kJ/mol/rad^2
- # X -X -CA-HA 1.1 180. 2. bsd.on C6H6 nmodes (from parm99.dat)
- # X X CA HA 1 180.00 4.60240 2 ; bsd.on C6H6 nmodes
- ;impropers treated as propers in GROMACS to use correct AMBER analytical function (from ffamber99bon.itp)
- # 6-12 parms sigma = 2 * r * 2^(-1/6) epsilon
- # atomtype radius Ang. pot. well depth kcal/mol comments
- ha 1.4590* 0.0150** Spellmeyer
- ca 1.9080 0.0860 OPLS
- * to convert to gmx:
- sigma = 1.4590 * 2^(-1/6) * 2 = 2 * 1.29982 Ang. = 2 * 0.129982 nm = 1.4590 * 2^(5/6)/10 = 0.259964 nm
- ** to convert to gmx: 0.0150 * 4.184 = 0.06276 kJ/mol
- # amber99_3 CA 0.0000 0.0000 A 3.39967e-01 3.59824e-01 (from ffamber99nb.itp)
- # amber99_22 HA 0.0000 0.0000 A 2.59964e-01 6.27600e-02 (from ffamber99nb.itp)
- # C* 1.9080 0.0860 Spellmeyer
- # HA 1.4590 0.0150 Spellmeyer (from parm99.dat)
- # to convert r and epsilon to ACOEF and BCOEF
- # ACOEF = sqrt(e1*e2) * (r1 + r2)^12 ; BCOEF = 2 * sqrt(e1*e2) * (r1 + r2)^6 = 2 * ACOEF/(r1+r2)^6
- # to convert ACOEF and BCOEF to r and epsilon
- # r = 0.5 * (2*ACOEF/BCOEF)^(1/6); ep = BCOEF^2/(4*ACOEF)
- # to convert ACOEF and BCOEF to sigma and epsilon (GMX)
- # sigma = (ACOEF/BCOEF)^(1/6) * 0.1 ; epsilon = 4.184 * BCOEF^2/(4*ACOEF)
- # ca ca 819971.66 531.10
- # ca ha 76245.15 104.66
- # ha ha 5716.30 18.52
- For proper dihedrals: a quartet of atoms may appear with more than
- one set of parameters and to convert to GMX they are treated as RBs;
- use the algorithm:
- for(my $j=$i;$j<=$lines;$j++){
- my $period = $pn{$j};
- if($pk{$j}>0) {
- $V[$period] = 2*$pk{$j}*$cal;
- }
- # assign V values to C values as predefined #
- if($period==1){
- $C[0]+=0.5*$V[$period];
- if($phase{$j}==0){
- $C[1]-=0.5*$V[$period];
- }else{
- $C[1]+=0.5*$V[$period];
- }
- }elsif($period==2){
- if(($phase{$j}==180)||($phase{$j}==3.14)){
- $C[0]+=$V[$period];
- $C[2]-=$V[$period];
- }else{
- $C[2]+=$V[$period];
- }
- }elsif($period==3){
- $C[0]+=0.5*$V[$period];
- if($phase{$j}==0){
- $C[1]+=1.5*$V[$period];
- $C[3]-=2*$V[$period];
- }else{
- $C[1]-=1.5*$V[$period];
- $C[3]+=2*$V[$period];
- }
- }elsif($period==4){
- if(($phase{$j}==180)||($phase{$j}==3.14)){
- $C[2]+=4*$V[$period];
- $C[4]-=4*$V[$period];
- }else{
- $C[0]+=$V[$period];
- $C[2]-=4*$V[$period];
- $C[4]+=4*$V[$period];
- }
- }
- }
- """
-
- self.printMess("Writing GROMACS files\n")
-
- self.setAtomType4Gromacs()
-
- self.writeGroFile()
-
- self.writeGromacsTop(amb2gmx=amb2gmx)
-
- self.writeMdpFiles()
-
- def setAtomType4Gromacs(self):
- """Atom types names in Gromacs TOP file are not case sensitive;
- this routine will append a '_' to lower case atom type.
- E.g.: CA and ca -> CA and ca_
- """
- if self.disam:
- self.printMess("Disambiguating lower and uppercase atomtypes in GMX top file.\n")
- self.atomTypesGromacs = self.atomTypes
- self.atomsGromacs = self.atoms
- return
-
- atNames = [at.atomTypeName for at in self.atomTypes]
- # print atNames
- delAtomTypes = []
- modAtomTypes = []
- atomTypesGromacs = []
- dictAtomTypes = {}
- for at in self.atomTypes:
- atName = at.atomTypeName
- dictAtomTypes[atName] = at
- if atName.islower() and atName.upper() in atNames:
- # print atName, atName.upper()
- atUpper = self.atomTypes[atNames.index(atName.upper())]
- # print at.atomTypeName,at.mass, at.ACOEF, at.BCOEF
- # print atUpper.atomTypeName, atUpper.mass, atUpper.ACOEF, atUpper.BCOEF
- if at.ACOEF is atUpper.ACOEF and at.BCOEF is at.BCOEF:
- delAtomTypes.append(atName)
- else:
- newAtName = atName + '_'
- modAtomTypes.append(atName)
- atomType = AtomType(newAtName, at.mass, at.ACOEF, at.BCOEF)
- atomTypesGromacs.append(atomType)
- dictAtomTypes[newAtName] = atomType
- else:
- atomTypesGromacs.append(at)
-
- atomsGromacs = []
- for a in self.atoms:
- atName = a.atomType.atomTypeName
- if atName in delAtomTypes:
- atom = Atom(a.atomName, dictAtomTypes[atName.upper()], a.id,
- a.resid, a.mass, a.charge, a.coords)
- atom.cgnr = a.cgnr
- atomsGromacs.append(atom)
- elif atName in modAtomTypes:
- atom = Atom(a.atomName, dictAtomTypes[atName + '_'], a.id,
- a.resid, a.mass, a.charge, a.coords)
- atom.cgnr = a.cgnr
- atomsGromacs.append(atom)
- else:
- atomsGromacs.append(a)
-
- self.atomTypesGromacs = atomTypesGromacs
- self.atomsGromacs = atomsGromacs
- # print [i.atomTypeName for i in atomTypesGromacs]
- # print modAtomTypes
- # print delAtomTypes
-
- def writeGromacsTop(self, amb2gmx=False):
- if self.atomTypeSystem == 'amber':
- d2opls = dictAtomTypeAmb2OplsGmxCode
- else:
- d2opls = dictAtomTypeGaff2OplsGmxCode
-
- topText = []
- itpText = []
- oitpText = []
- otopText = []
- top = self.baseName + '_GMX.top'
- itp = self.baseName + '_GMX.itp'
- otop = self.baseName + '_GMX_OPLS.top'
- oitp = self.baseName + '_GMX_OPLS.itp'
-
- headDefault = \
- """
- [ defaults ]
- ; nbfunc comb-rule gen-pairs fudgeLJ fudgeQQ
- 1 2 yes 0.5 0.8333
- """
- headItp = \
- """
- ; Include %s topology
- #include "%s"
- """
- headOpls = \
- """
- ; Include forcefield parameters
- #include "ffoplsaa.itp"
- """
- headSystem = \
- """
- [ system ]
- %s
- """
- headMols = \
- """
- [ molecules ]
- ; Compound nmols
- """
- headAtomtypes = \
- """
- [ atomtypes ]
- ;name bond_type mass charge ptype sigma epsilon Amb
- """
- headAtomtypesOpls = \
- """
- ; For OPLS atomtypes manual fine tuning
- ; AC_at:OPLS_at:OPLScode: Possible_Aternatives (see ffoplsaa.atp and ffoplsaanb.itp)
- """
- headMoleculetype = \
- """
- [ moleculetype ]
- ;name nrexcl
- %-16s 3
- """
- headAtoms = \
- """
- [ atoms ]
- ; nr type resi res atom cgnr charge mass ; qtot bond_type
- """
- headBonds = \
- """
- [ bonds ]
- ; ai aj funct r k
- """
- headPairs = \
- """
- [ pairs ]
- ; ai aj funct
- """
- headAngles = \
- """
- [ angles ]
- ; ai aj ak funct theta cth
- """
- headProDih = \
- """
- [ dihedrals ] ; propers
- ; treated as RBs in GROMACS to use combine multiple AMBER torsions per quartet
- ; i j k l func C0 C1 C2 C3 C4 C5
- """
-
- headProDihAlphaGamma = """; treated as usual propers in GROMACS since Phase angle diff from 0 or 180 degrees
- ; i j k l func phase kd pn
- """
-
- headProDihGmx45 = \
- """
- [ dihedrals ] ; propers
- ; for gromacs 4.5 or higher, using funct 9
- ; i j k l func phase kd pn
- """
-
- headImpDih = \
- """
- [ dihedrals ] ; impropers
- ; treated as propers in GROMACS to use correct AMBER analytical function
- ; i j k l func phase kd pn
- """
- _headTopWaterTip3p = \
- """
- [ bondtypes ]
- ; i j func b0 kb
- OW HW 1 0.09572 462750.4 ; TIP3P water
- HW HW 1 0.15139 462750.4 ; TIP3P water
- [ angletypes ]
- ; i j k func th0 cth
- HW OW HW 1 104.520 836.800 ; TIP3P water
- HW HW OW 1 127.740 0.000 ; (found in crystallographic water with 3 bonds)
- """
-
- _headTopWaterSpce = \
- """
- [ bondtypes ]
- ; i j func b0 kb
- OW HW 1 0.1 462750.4 ; SPCE water
- HW HW 1 0.1633 462750.4 ; SPCE water
- [ angletypes ]
- ; i j k func th0 cth
- HW OW HW 1 109.47 836.800 ; SPCE water
- HW HW OW 1 125.265 0.000 ; SPCE water
- """
- # NOTE: headTopWaterTip3p and headTopWaterSpce actually do NOTHING
- headNa = \
- """
- [ moleculetype ]
- ; molname nrexcl
- NA+ 1
- [ atoms ]
- ; id_ at type res nr residu name at name cg nr charge mass
- 1 IP 1 NA+ NA+ 1 1 22.9898
- """
- headCl = \
- """
- [ moleculetype ]
- ; molname nrexcl
- CL- 1
- [ atoms ]
- ; id_ at type res nr residu name at name cg nr charge mass
- 1 IM 1 CL- CL- 1 -1 35.45300
- """
- headK = \
- """
- [ moleculetype ]
- ; molname nrexcl
- K+ 1
- [ atoms ]
- ; id_ at type res nr residu name at name cg nr charge mass
- 1 K 1 K+ K+ 1 1 39.100
- """
- headWaterTip3p = \
- """
- [ moleculetype ]
- ; molname nrexcl ; TIP3P model
- WAT 2
- [ atoms ]
- ; nr type resnr residue atom cgnr charge mass
- 1 OW 1 WAT O 1 -0.834 16.00000
- 2 HW 1 WAT H1 1 0.417 1.00800
- 3 HW 1 WAT H2 1 0.417 1.00800
- #ifdef FLEXIBLE
- [ bonds ]
- ; i j funct length force.c.
- 1 2 1 0.09572 462750.4 0.09572 462750.4
- 1 3 1 0.09572 462750.4 0.09572 462750.4
- [ angles ]
- ; i j k funct angle force.c.
- 2 1 3 1 104.520 836.800 104.520 836.800
- #else
- [ settles ]
- ; i j funct length
- 1 1 0.09572 0.15139
- [ exclusions ]
- 1 2 3
- 2 1 3
- 3 1 2
- #endif
- """
-
- headWaterSpce = \
- """
- [ moleculetype ]
- ; molname nrexcl ; SPCE model
- WAT 2
- [ atoms ]
- ; nr type resnr residue atom cgnr charge mass
- 1 OW 1 WAT O 1 -0.8476 15.99940
- 2 HW 1 WAT H1 1 0.4238 1.00800
- 3 HW 1 WAT H2 1 0.4238 1.00800
- #ifdef FLEXIBLE
- [ bonds ]
- ; i j funct length force.c.
- 1 2 1 0.1 462750.4 0.1 462750.4
- 1 3 1 0.1 462750.4 0.1 462750.4
- [ angles ]
- ; i j k funct angle force.c.
- 2 1 3 1 109.47 836.800 109.47 836.800
- #else
- [ settles ]
- ; OW funct doh dhh
- 1 1 0.1 0.16330
- [ exclusions ]
- 1 2 3
- 2 1 3
- 3 1 2
- #endif
- """
- if self.direct and amb2gmx:
- self.printMess("Converting directly from AMBER to GROMACS.\n")
-
- # Dict of ions dealt by acpype emulating amb2gmx
- ionsDict = {'Na+': headNa, 'Cl-': headCl, 'K+': headK}
- ionsSorted = []
- # NOTE: headWaterTip3p and headWaterSpce actually do the real thing
- # so, skipping headTopWaterTip3p and headWaterTip3p
- # headTopWater = headTopWaterTip3p
- headWater = headWaterTip3p
-
- nWat = 0
- # topFile.write("; " + head % (top, date))
- topText.append("; " + head % (top, date))
- otopText.append("; " + head % (otop, date))
- # topFile.write(headDefault)
- topText.append(headDefault)
-
- nSolute = 0
- if not amb2gmx:
- topText.append(headItp % (itp, itp))
- otopText.append(headOpls)
- otopText.append(headItp % (itp, itp))
- itpText.append("; " + head % (itp, date))
- oitpText.append("; " + head % (oitp, date))
-
- self.printDebug("atomTypes %i" % len(self.atomTypesGromacs))
- temp = []
- otemp = []
- for aType in self.atomTypesGromacs:
- aTypeName = aType.atomTypeName
- oaCode = d2opls.get(aTypeName, ['x', '0'])[:-1]
- aTypeNameOpls = oplsCode2AtomTypeDict.get(oaCode[0], 'x')
- A = aType.ACOEF
- B = aType.BCOEF
- # one cannot infer sigma or epsilon for B = 0, assuming 0 for them
- if B == 0.0:
- sigma, epsilon, r0, epAmber = 0, 0, 0, 0
- else:
- r0 = 0.5 * math.pow((2 * A / B), (1.0 / 6))
- epAmber = 0.25 * B * B / A
- sigma = 0.1 * math.pow((A / B), (1.0 / 6))
- epsilon = cal * epAmber
- if aTypeName == 'OW':
- if A == 629362.166 and B == 625.267765:
- # headTopWater = headTopWaterSpce
- headWater = headWaterSpce
- # OW 629362.166 625.267765 spce
- # OW 581935.564 594.825035 tip3p
- # print aTypeName, A, B
- line = " %-8s %-11s %3.5f %3.5f A %13.5e %13.5e" % \
- (aTypeName, aTypeName, 0.0, 0.0, sigma, epsilon) + \
- " ; %4.2f %1.4f\n" % (r0, epAmber)
- oline = "; %s:%s:opls_%s: %s\n" % (aTypeName, aTypeNameOpls, oaCode[0], repr(oaCode[1:]))
- # tmpFile.write(line)
- temp.append(line)
- otemp.append(oline)
- if amb2gmx:
- topText.append(headAtomtypes)
- topText += temp
- nWat = self.residueLabel.count('WAT')
- for ion in ionsDict:
- nIon = self.residueLabel.count(ion)
- if nIon > 0:
- idIon = self.residueLabel.index(ion)
- ionsSorted.append((idIon, nIon, ion))
- ionsSorted.sort()
- else:
- itpText.append(headAtomtypes)
- itpText += temp
- oitpText.append(headAtomtypesOpls)
- oitpText += otemp
- self.printDebug("GMX atomtypes done")
-
- if len(self.atoms) > 3 * nWat + sum([x[1] for x in ionsSorted]):
- nSolute = 1
-
- if nWat:
- # topText.append(headTopWater)
- self.printDebug("type of water '%s'" % headWater[43:48].strip())
-
- if nSolute:
- if amb2gmx:
- topText.append(headMoleculetype % self.baseName)
- else:
- itpText.append(headMoleculetype % self.baseName)
- oitpText.append(headMoleculetype % self.baseName)
-
- self.printDebug("atoms %i" % len(self.atoms))
- qtot = 0.0
- count = 1
- temp = []
- otemp = []
- id2oplsATDict = {}
- for atom in self.atomsGromacs:
- resid = atom.resid
- resname = self.residueLabel[resid]
- if not self.direct:
- if resname in list(ionsDict.keys()) + ['WAT']:
- break
- aName = atom.atomName
- aType = atom.atomType.atomTypeName
- oItem = d2opls.get(aType, ['x', 0])
- oplsAtName = oplsCode2AtomTypeDict.get(oItem[0], 'x')
- id_ = atom.id
- id2oplsATDict[id_] = oplsAtName
- oaCode = 'opls_' + oItem[0]
- cgnr = id_
- if self.sorted:
- cgnr = atom.cgnr # JDC
- charge = atom.charge
- mass = atom.mass
- omass = float(oItem[-1])
- qtot += charge
- resnr = resid + 1
- line = "%6d %4s %5d %5s %5s %4d %12.6f %12.5f ; qtot %1.3f\n" % \
- (id_, aType, resnr, resname, aName, cgnr, charge, mass, qtot) # JDC
- oline = "%6d %4s %5d %5s %5s %4d %12.6f %12.5f ; qtot % 3.3f %-4s\n" % \
- (id_, oaCode, resnr, resname, aName, cgnr, charge, omass, qtot, oplsAtName) # JDC
- count += 1
- temp.append(line)
- otemp.append(oline)
- if temp:
- if amb2gmx:
- topText.append(headAtoms)
- topText += temp
- else:
- itpText.append(headAtoms)
- itpText += temp
- oitpText.append(headAtoms)
- oitpText += otemp
- self.printDebug("GMX atoms done")
-
- # remove bond of water
- self.printDebug("bonds %i" % len(self.bonds))
- temp = []
- otemp = []
- for bond in self.bonds:
- res1 = self.residueLabel[bond.atoms[0].resid]
- res2 = self.residueLabel[bond.atoms[0].resid]
- if 'WAT' in [res1, res2]:
- continue
- a1Name = bond.atoms[0].atomName
- a2Name = bond.atoms[1].atomName
- id1 = bond.atoms[0].id
- id2 = bond.atoms[1].id
- oat1 = id2oplsATDict.get(id1)
- oat2 = id2oplsATDict.get(id2)
- line = "%6i %6i %3i %13.4e %13.4e ; %6s - %-6s\n" % (id1, id2, 1,
- bond.rEq * 0.1, bond.kBond * 200 * cal, a1Name, a2Name)
- oline = "%6i %6i %3i ; %13.4e %13.4e ; %6s - %-6s %6s - %-6s\n" % \
- (id1, id2, 1, bond.rEq * 0.1, bond.kBond * 200 * cal, a1Name,
- a2Name, oat1, oat2)
- temp.append(line)
- otemp.append(oline)
- temp.sort()
- otemp.sort()
- if temp:
- if amb2gmx:
- topText.append(headBonds)
- topText += temp
- else:
- itpText.append(headBonds)
- itpText += temp
- oitpText.append(headBonds)
- oitpText += otemp
- self.printDebug("GMX bonds done")
-
- self.printDebug("atomPairs %i" % len(self.atomPairs))
- temp = []
- for pair in self.atomPairs:
- # if not printed:
- # tmpFile.write(headPairs)
- # printed = True
- a1Name = pair[0].atomName
- a2Name = pair[1].atomName
- id1 = pair[0].id
- id2 = pair[1].id
- # id1 = self.atoms.index(pair[0]) + 1
- # id2 = self.atoms.index(pair[1]) + 1
- line = "%6i %6i %6i ; %6s - %-6s\n" % (id1, id2, 1, a1Name,
- a2Name)
- temp.append(line)
- temp.sort()
- if temp:
- if amb2gmx:
- topText.append(headPairs)
- topText += temp
- else:
- itpText.append(headPairs)
- itpText += temp
- oitpText.append(headPairs)
- oitpText += temp
- self.printDebug("GMX pairs done")
-
- self.printDebug("angles %i" % len(self.angles))
- temp = []
- otemp = []
- for angle in self.angles:
- a1 = angle.atoms[0].atomName
- a2 = angle.atoms[1].atomName
- a3 = angle.atoms[2].atomName
- id1 = angle.atoms[0].id
- id2 = angle.atoms[1].id
- id3 = angle.atoms[2].id
- oat1 = id2oplsATDict.get(id1)
- oat2 = id2oplsATDict.get(id2)
- oat3 = id2oplsATDict.get(id3)
- line = "%6i %6i %6i %6i %13.4e %13.4e ; %6s - %-6s - %-6s\n" % (id1, id2,
- id3, 1, angle.thetaEq * radPi, 2 * cal * angle.kTheta, a1, a2, a3)
- oline = "%6i %6i %6i %6i ; %13.4e %13.4e ; %6s - %-4s - %-6s %4s - %+4s - %-4s\n" % \
- (id1, id2, id3, 1, angle.thetaEq * radPi, 2 * cal * angle.kTheta,
- a1, a2, a3, oat1, oat2, oat3)
- temp.append(line)
- otemp.append(oline)
- temp.sort()
- otemp.sort()
- if temp:
- if amb2gmx:
- topText.append(headAngles)
- topText += temp
- else:
- itpText.append(headAngles)
- itpText += temp
- oitpText.append(headAngles)
- oitpText += otemp
- self.printDebug("GMX angles done")
-
- self.setProperDihedralsCoef()
- self.printDebug("properDihedralsCoefRB %i" % len(self.properDihedralsCoefRB))
- self.printDebug("properDihedralsAlphaGamma %i" % len(self.properDihedralsAlphaGamma))
- self.printDebug("properDihedralsGmx45 %i" % len(self.properDihedralsGmx45))
- temp = []
- otemp = []
- if self.gmx4:
- self.printMess("Writing RB dihedrals for old GMX 4.\n")
- for dih in self.properDihedralsCoefRB:
- a1 = dih[0][0].atomName
- a2 = dih[0][1].atomName
- a3 = dih[0][2].atomName
- a4 = dih[0][3].atomName
- id1 = dih[0][0].id
- id2 = dih[0][1].id
- id3 = dih[0][2].id
- id4 = dih[0][3].id
- oat1 = id2oplsATDict.get(id1)
- oat2 = id2oplsATDict.get(id2)
- oat3 = id2oplsATDict.get(id3)
- oat4 = id2oplsATDict.get(id4)
- c0, c1, c2, c3, c4, c5 = dih[1]
- line = \
- "%6i %6i %6i %6i %6i %10.5f %10.5f %10.5f %10.5f %10.5f %10.5f" % \
- (id1, id2, id3, id4, 3, c0, c1, c2, c3, c4, c5) \
- + " ; %6s-%6s-%6s-%6s\n" % (a1, a2, a3, a4)
- oline = \
- "%6i %6i %6i %6i %6i ; %10.5f %10.5f %10.5f %10.5f %10.5f %10.5f" % \
- (id1, id2, id3, id4, 3, c0, c1, c2, c3, c4, c5) \
- + " ; %6s-%6s-%6s-%6s %4s-%4s-%4s-%4s\n" % (a1, a2, a3, a4, oat1, oat2, oat3, oat4)
- temp.append(line)
- otemp.append(oline)
- temp.sort()
- otemp.sort()
- if temp:
- if amb2gmx:
- topText.append(headProDih)
- topText += temp
- else:
- itpText.append(headProDih)
- itpText += temp
- oitpText.append(headProDih)
- oitpText += otemp
- self.printDebug("GMX proper dihedrals done")
- else:
- self.printMess("Writing GMX dihedrals for GMX 4.5 and higher.\n")
- funct = 9 # 9
- for dih in self.properDihedralsGmx45:
- a1 = dih[0][0].atomName
- a2 = dih[0][1].atomName
- a3 = dih[0][2].atomName
- a4 = dih[0][3].atomName
- id1 = dih[0][0].id
- id2 = dih[0][1].id
- id3 = dih[0][2].id
- id4 = dih[0][3].id
- ph = dih[1] # phase already in degree
- kd = dih[2] * cal # kPhi PK
- pn = dih[3] # .period
- line = "%6i %6i %6i %6i %6i %8.2f %9.5f %3i ; %6s-%6s-%6s-%6s\n" % \
- (id1, id2, id3, id4, funct, ph, kd, pn, a1, a2, a3, a4)
- oline = "%6i %6i %6i %6i %6i ; %8.2f %9.5f %3i ; %6s-%6s-%6s-%6s\n" % \
- (id1, id2, id3, id4, funct, ph, kd, pn, a1, a2, a3, a4)
- temp.append(line)
- otemp.append(oline)
- temp.sort()
- otemp.sort()
- if temp:
- if amb2gmx:
- topText.append(headProDihGmx45)
- topText += temp
- else:
- itpText.append(headProDihGmx45)
- itpText += temp
- oitpText.append(headProDihGmx45)
- oitpText += otemp
-
- # for properDihedralsAlphaGamma
- if not self.gmx4:
- funct = 4 # 4
- else:
- funct = 1
- temp = []
- otemp = []
- for dih in self.properDihedralsAlphaGamma:
- a1 = dih[0][0].atomName
- a2 = dih[0][1].atomName
- a3 = dih[0][2].atomName
- a4 = dih[0][3].atomName
- id1 = dih[0][0].id
- id2 = dih[0][1].id
- id3 = dih[0][2].id
- id4 = dih[0][3].id
- ph = dih[1] # phase already in degree
- kd = dih[2] * cal # kPhi PK
- pn = dih[3] # .period
- line = "%6i %6i %6i %6i %6i %8.2f %9.5f %3i ; %6s-%6s-%6s-%6s\n" % \
- (id1, id2, id3, id4, funct, ph, kd, pn, a1, a2, a3, a4)
- oline = "%6i %6i %6i %6i %6i ; %8.2f %9.5f %3i ; %6s-%6s-%6s-%6s\n" % \
- (id1, id2, id3, id4, funct, ph, kd, pn, a1, a2, a3, a4)
- temp.append(line)
- otemp.append(oline)
- temp.sort()
- otemp.sort()
- if temp:
- if amb2gmx:
- topText.append(headProDihAlphaGamma)
- topText += temp
- else:
- itpText.append(headProDihAlphaGamma)
- itpText += temp
- oitpText.append(headProDihAlphaGamma)
- oitpText += otemp
- self.printDebug("GMX special proper dihedrals done")
-
- self.printDebug("improperDihedrals %i" % len(self.improperDihedrals))
- temp = []
- otemp = []
- for dih in self.improperDihedrals:
- a1 = dih.atoms[0].atomName
- a2 = dih.atoms[1].atomName
- a3 = dih.atoms[2].atomName
- a4 = dih.atoms[3].atomName
- id1 = dih.atoms[0].id
- id2 = dih.atoms[1].id
- id3 = dih.atoms[2].id
- id4 = dih.atoms[3].id
- kd = dih.kPhi * cal
- pn = dih.period
- ph = dih.phase * radPi
- line = "%6i %6i %6i %6i %6i %8.2f %9.5f %3i ; %6s-%6s-%6s-%6s\n" % \
- (id1, id2, id3, id4, funct, ph, kd, pn, a1, a2, a3, a4)
- oline = "%6i %6i %6i %6i %6i ; %8.2f %9.5f %3i ; %6s-%6s-%6s-%6s\n" % \
- (id1, id2, id3, id4, funct, ph, kd, pn, a1, a2, a3, a4)
- temp.append(line)
- otemp.append(oline)
- temp.sort()
- otemp.sort()
- if temp:
- if amb2gmx:
- topText.append(headImpDih)
- topText += temp
- else:
- itpText.append(headImpDih)
- itpText += temp
- oitpText.append(headImpDih)
- oitpText += otemp
- self.printDebug("GMX improper dihedrals done")
-
- if not self.direct:
- for ion in ionsSorted:
- topText.append(ionsDict[ion[2]])
-
- if nWat:
- topText.append(headWater)
-
- topText.append(headSystem % (self.baseName))
- topText.append(headMols)
- otopText.append(headSystem % (self.baseName))
- otopText.append(headMols)
-
- if nSolute > 0:
- topText.append(" %-16s %-6i\n" % (self.baseName, nSolute))
- otopText.append(" %-16s %-6i\n" % (self.baseName, nSolute))
-
- if not self.direct:
- for ion in ionsSorted:
- topText.append(" %-16s %-6i\n" % (ion[2].upper(), ion[1]))
-
- if nWat:
- topText.append(" %-16s %-6i\n" % ('WAT', nWat))
-
- gmxDir = os.path.abspath('.')
- topFileName = os.path.join(gmxDir, top)
- topFile = open(topFileName, 'w')
- topFile.writelines(topText)
-
- if not amb2gmx:
- itpFileName = os.path.join(gmxDir, itp)
- itpFile = open(itpFileName, 'w')
- itpFile.writelines(itpText)
- oitpFileName = os.path.join(gmxDir, oitp)
- oitpFile = open(oitpFileName, 'w')
- oitpFile.writelines(oitpText)
- otopFileName = os.path.join(gmxDir, otop)
- otopFile = open(otopFileName, 'w')
- otopFile.writelines(otopText)
-
- def writeGroFile(self):
- # print "Writing GROMACS GRO file\n"
- self.printDebug("writing GRO file")
- gro = self.baseName + '_GMX.gro'
- gmxDir = os.path.abspath('.')
- groFileName = os.path.join(gmxDir, gro)
- groFile = open(groFileName, 'w')
- groFile.write(head % (gro, date))
- groFile.write(" %i\n" % len(self.atoms))
- count = 1
- for atom in self.atoms:
- coords = [c * 0.1 for c in atom.coords]
- resid = atom.resid
- line = "%5d%5s%5s%5d%8.3f%8.3f%8.3f\n" % \
- (resid + 1, self.residueLabel[resid], atom.atomName,
- count, coords[0], coords[1], coords[2])
- count += 1
- if count == 100000:
- count = 0
- groFile.write(line)
- if self.pbc:
- boxX = self.pbc[0][0] * 0.1
- boxY = self.pbc[0][1] * 0.1
- boxZ = self.pbc[0][2] * 0.1
- vX = self.pbc[1][0]
- # vY = self.pbc[1][1]
- # vZ = self.pbc[1][2]
- if vX == 90.0:
- self.printDebug("PBC triclinic")
- text = "%11.5f %11.5f %11.5f\n" % (boxX, boxY, boxZ)
- elif round(vX, 2) == 109.47:
- self.printDebug("PBC octahedron")
- f1 = 0.471405 # 1/3 * sqrt(2)
- f2 = 0.333333 * boxX
- v22 = boxY * 2 * f1
- v33 = boxZ * f1 * 1.73205 # f1 * sqrt(3)
- v21 = v31 = v32 = 0.0
- v12 = f2
- v13 = -f2
- v23 = f1 * boxX
- text = "%11.5f %11.5f %11.5f %11.5f %11.5f %11.5f %11.5f %11.5f %11.5f\n" % \
- (boxX, v22, v33, v21, v31, v12, v32, v13, v23)
- else:
- self.printDebug("Box size estimated")
- X = [a.coords[0] * 0.1 for a in self.atoms]
- Y = [a.coords[1] * 0.1 for a in self.atoms]
- Z = [a.coords[2] * 0.1 for a in self.atoms]
- boxX = max(X) - min(X) # + 2.0 # 2.0 is double of rlist
- boxY = max(Y) - min(Y) # + 2.0
- boxZ = max(Z) - min(Z) # + 2.0
- text = "%11.5f %11.5f %11.5f\n" % (boxX * 20.0, boxY * 20.0, boxZ * 20.0)
- groFile.write(text)
-
- def writeMdpFiles(self):
- emMdp = """; to test
- ; gmx grompp -f em.mdp -c {base}_GMX.gro -p {base}_GMX.top -o em.tpr -v
- ; gmx mdrun -ntmpi 1 -v -deffnm em
- integrator = steep
- nsteps = 500
- """.format(base=self.baseName)
- mdMdp = """; to test
- ; gmx grompp -f md.mdp -c em.gro -p {base}_GMX.top -o md.tpr
- ; gmx mdrun -ntmpi 1 -v -deffnm md
- integrator = md
- nsteps = 10000
- """.format(base=self.baseName)
- emMdpFile = open('em.mdp', 'w')
- mdMdpFile = open('md.mdp', 'w')
- emMdpFile.write(emMdp)
- mdMdpFile.write(mdMdp)
-
- def writeCnsTopolFiles(self):
- autoAngleFlag = True
- autoDihFlag = True
- cnsDir = os.path.abspath('.')
-
- pdb = self.baseName + '_NEW.pdb'
- par = self.baseName + '_CNS.par'
- top = self.baseName + '_CNS.top'
- inp = self.baseName + '_CNS.inp'
-
- pdbFileName = os.path.join(cnsDir, pdb)
- parFileName = os.path.join(cnsDir, par)
- topFileName = os.path.join(cnsDir, top)
- inpFileName = os.path.join(cnsDir, inp)
-
- self.CnsTopFileName = topFileName
- self.CnsInpFileName = inpFileName
- self.CnsParFileName = parFileName
- self.CnsPdbFileName = pdbFileName
-
- parFile = open(parFileName, 'w')
- topFile = open(topFileName, 'w')
- inpFile = open(inpFileName, 'w')
-
- self.printMess("Writing NEW PDB file\n")
- self.writePdb(pdbFileName)
-
- self.printMess("Writing CNS/XPLOR files\n")
-
- # print "Writing CNS PAR file\n"
- parFile.write("Remarks " + head % (par, date))
- parFile.write("\nset echo=false end\n")
-
- parFile.write("\n{ Bonds: atomType1 atomType2 kb r0 }\n")
- lineSet = []
- for bond in self.bonds:
- a1Type = bond.atoms[0].atomType.atomTypeName + '_'
- a2Type = bond.atoms[1].atomType.atomTypeName + '_'
- kb = 1000.0
- if not self.allhdg:
- kb = bond.kBond
- r0 = bond.rEq
- line = "BOND %5s %5s %8.1f %8.4f\n" % (a1Type, a2Type, kb, r0)
- lineRev = "BOND %5s %5s %8.1f %8.4f\n" % (a2Type, a1Type, kb, r0)
- if line not in lineSet:
- if lineRev not in lineSet:
- lineSet.append(line)
- for item in lineSet:
- parFile.write(item)
-
- parFile.write("\n{ Angles: aType1 aType2 aType3 kt t0 }\n")
- lineSet = []
- for angle in self.angles:
- a1 = angle.atoms[0].atomType.atomTypeName + '_'
- a2 = angle.atoms[1].atomType.atomTypeName + '_'
- a3 = angle.atoms[2].atomType.atomTypeName + '_'
- kt = 500.0
- if not self.allhdg:
- kt = angle.kTheta
- t0 = angle.thetaEq * radPi
- line = "ANGLe %5s %5s %5s %8.1f %8.2f\n" % (a1, a2, a3, kt, t0)
- lineRev = "ANGLe %5s %5s %5s %8.1f %8.2f\n" % (a3, a2, a1, kt, t0)
- if line not in lineSet:
- if lineRev not in lineSet:
- lineSet.append(line)
- for item in lineSet:
- parFile.write(item)
-
- parFile.write("\n{ Proper Dihedrals: aType1 aType2 aType3 aType4 kt per\
- iod phase }\n")
- lineSet = set()
- for item in self.condensedProperDihedrals:
- seq = ''
- id_ = 0
- for dih in item:
- # id_ = item.index(dih)
- l = len(item)
- a1 = dih.atoms[0].atomType.atomTypeName + '_'
- a2 = dih.atoms[1].atomType.atomTypeName + '_'
- a3 = dih.atoms[2].atomType.atomTypeName + '_'
- a4 = dih.atoms[3].atomType.atomTypeName + '_'
- kp = 750.0
- if not self.allhdg:
- kp = dih.kPhi
- p = dih.period
- ph = dih.phase * radPi
- if l > 1:
- if id_ == 0:
- line = "DIHEdral %5s %5s %5s %5s MULT %1i %7.3f %4i %8\
- .2f\n" % (a1, a2, a3, a4, l, kp, p, ph)
- else:
- line = "%s %7.3f %4i %8.2f\n" % (40 * " ", kp, p, ph)
- else:
- line = "DIHEdral %5s %5s %5s %5s %15.3f %4i %8.2f\n" % (a1,
- a2, a3, a4, kp, p, ph)
- seq += line
- id_ += 1
- lineSet.add(seq)
- for item in lineSet:
- parFile.write(item)
-
- parFile.write("\n{ Improper Dihedrals: aType1 aType2 aType3 aType4 kt p\
- eriod phase }\n")
- lineSet = set()
- for idh in self.improperDihedrals:
- a1 = idh.atoms[0].atomType.atomTypeName + '_'
- a2 = idh.atoms[1].atomType.atomTypeName + '_'
- a3 = idh.atoms[2].atomType.atomTypeName + '_'
- a4 = idh.atoms[3].atomType.atomTypeName + '_'
- kp = 750.0
- if not self.allhdg:
- kp = idh.kPhi
- p = idh.period
- ph = idh.phase * radPi
- line = "IMPRoper %5s %5s %5s %5s %13.1f %4i %8.2f\n" % (a1, a2, a3,
- a4, kp, p, ph)
- lineSet.add(line)
-
- if self.chiral:
- for idhc in self.chiralGroups:
- _atc, neig, angle = idhc
- a1 = neig[0].atomType.atomTypeName + '_'
- a2 = neig[1].atomType.atomTypeName + '_'
- a3 = neig[2].atomType.atomTypeName + '_'
- a4 = neig[3].atomType.atomTypeName + '_'
- kp = 11000.0
- p = 0
- ph = angle
- line = "IMPRoper %5s %5s %5s %5s %13.1f %4i %8.2f\n" % (a1, a2, a3,
- a4, kp, p, ph)
- lineSet.add(line)
-
- for item in lineSet:
- parFile.write(item)
-
- parFile.write("\n{ Nonbonded: Type Emin sigma; (1-4): Emin/2 sigma }\n")
- for at in self.atomTypes:
- A = at.ACOEF
- B = at.BCOEF
- atName = at.atomTypeName + '_'
- if B == 0.0:
- sigma = epAmber = ep2 = sig2 = 0.0
- else:
- epAmber = 0.25 * B * B / A
- ep2 = epAmber / 2.0
- sigma = math.pow((A / B), (1.0 / 6))
- sig2 = sigma
- line = "NONBonded %5s %11.6f %11.6f %11.6f %11.6f\n" % (atName,
- epAmber, sigma, ep2, sig2)
- parFile.write(line)
- parFile.write("\nset echo=true end\n")
-
- # print "Writing CNS TOP file\n"
- topFile.write("Remarks " + head % (top, date))
- topFile.write("\nset echo=false end\n")
- topFile.write("\nautogenerate angles=%s dihedrals=%s end\n" %
- (autoAngleFlag, autoDihFlag))
-
- topFile.write("\n{ atomType mass }\n")
- for at in self.atomTypes:
- atType = at.atomTypeName + '_'
- mass = at.mass
- line = "MASS %-5s %8.3f\n" % (atType, mass)
- topFile.write(line)
-
- topFile.write("\nRESIdue %s\n" % self.residueLabel[0])
- topFile.write("\nGROUP\n")
-
- topFile.write("\n{ atomName atomType Charge }\n")
- for at in self.atoms:
- atName = at.atomName
- atType = at.atomType.atomTypeName + '_'
- charge = at.charge
- line = "ATOM %-5s TYPE= %-5s CHARGE= %8.4f END\n" % (atName, atType,
- charge)
- topFile.write(line)
-
- topFile.write("\n{ Bonds: atomName1 atomName2 }\n")
- for bond in self.bonds:
- a1Name = bond.atoms[0].atomName
- a2Name = bond.atoms[1].atomName
- line = "BOND %-5s %-5s\n" % (a1Name, a2Name)
- topFile.write(line)
-
- if not autoAngleFlag or 1: # generating angles anyway
- topFile.write("\n{ Angles: atomName1 atomName2 atomName3}\n")
- for angle in self.angles:
- a1Name = angle.atoms[0].atomName
- a2Name = angle.atoms[1].atomName
- a3Name = angle.atoms[2].atomName
- line = "ANGLe %-5s %-5s %-5s\n" % (a1Name, a2Name, a3Name)
- topFile.write(line)
-
- if not autoDihFlag or 1: # generating angles anyway
- topFile.write("\n{ Proper Dihedrals: name1 name2 name3 name4 }\n")
- for item in self.condensedProperDihedrals:
- for dih in item:
- l = len(item)
- a1Name = dih.atoms[0].atomName
- a2Name = dih.atoms[1].atomName
- a3Name = dih.atoms[2].atomName
- a4Name = dih.atoms[3].atomName
- line = "DIHEdral %-5s %-5s %-5s %-5s\n" % (a1Name, a2Name,
- a3Name, a4Name)
- break
- topFile.write(line)
-
- topFile.write("\n{ Improper Dihedrals: aName1 aName2 aName3 aName4 }\n")
- for dih in self.improperDihedrals:
- a1Name = dih.atoms[0].atomName
- a2Name = dih.atoms[1].atomName
- a3Name = dih.atoms[2].atomName
- a4Name = dih.atoms[3].atomName
- line = "IMPRoper %-5s %-5s %-5s %-5s\n" % (a1Name, a2Name, a3Name,
- a4Name)
- topFile.write(line)
-
- if self.chiral:
- for idhc in self.chiralGroups:
- _atc, neig, angle = idhc
- a1Name = neig[0].atomName
- a2Name = neig[1].atomName
- a3Name = neig[2].atomName
- a4Name = neig[3].atomName
- line = "IMPRoper %-5s %-5s %-5s %-5s\n" % (a1Name, a2Name, a3Name,
- a4Name)
- topFile.write(line)
-
- topFile.write("\nEND {RESIdue %s}\n" % self.residueLabel[0])
-
- topFile.write("\nset echo=true end\n")
-
- # print "Writing CNS INP file\n"
- inpFile.write("Remarks " + head % (inp, date))
- inpData = \
- """
- topology
- @%(CNS_top)s
- end
- parameters
- @%(CNS_par)s
- nbonds
- atom cdie shift eps=1.0 e14fac=0.4 tolerance=0.5
- cutnb=9.0 ctonnb=7.5 ctofnb=8.0
- nbxmod=5 vswitch wmin 1.0
- end
- remark dielectric constant eps set to 1.0
- end
- flags exclude elec ? end
- segment name=" "
- chain
- coordinates @%(NEW_pdb)s
- end
- end
- coordinates @%(NEW_pdb)s
- coord copy end
- ! Remarks If you want to shake up the coordinates a bit ...
- vector do (x=x+6*(rand()-0.5)) (all)
- vector do (y=y+6*(rand()-0.5)) (all)
- vector do (z=z+6*(rand()-0.5)) (all)
- write coordinates output=%(CNS_ran)s end
- ! Remarks RMS diff after randomisation and before minimisation
- coord rms sele=(known and not hydrogen) end
- print threshold=0.02 bonds
- print threshold=3.0 angles
- print threshold=3.0 dihedrals
- print threshold=3.0 impropers
- ! Remarks Do Powell energy minimisation
- minimise powell
- nstep=250 drop=40.0
- end
- write coordinates output=%(CNS_min)s end
- write structure output=%(CNS_psf)s end
- ! constraints interaction (not hydro) (not hydro) end
- print threshold=0.02 bonds
- print threshold=3.0 angles
- print threshold=3.0 dihedrals
- print threshold=3.0 impropers
- flags exclude * include vdw end energy end
- distance from=(not hydro) to=(not hydro) cutoff=2.6 end
- ! Remarks RMS fit after minimisation
- coord fit sele=(known and not hydrogen) end
- stop
- """
- dictInp = {}
- dictInp['CNS_top'] = top
- dictInp['CNS_par'] = par
- dictInp['NEW_pdb'] = pdb
- dictInp['CNS_min'] = self.baseName + '_NEW_min.pdb'
- dictInp['CNS_psf'] = self.baseName + '_CNS.psf'
- dictInp['CNS_ran'] = self.baseName + '_rand.pdb'
- line = inpData % dictInp
- inpFile.write(line)
- if os.path.exists(self.obchiralExe):
- self.printDebug("chiralGroups %i" % len(self.chiralGroups))
- else:
- self.printDebug("No 'obchiral' to process chiral atoms. Consider installing http://openbabel.org")
-
-
- class ACTopol(AbstractTopol):
-
- """
- Class to build the AC topologies (Antechamber AmberTools)
- """
-
- def __init__(self, inputFile, chargeType='bcc', chargeVal=None,
- multiplicity='1', atomType='gaff', force=False, basename=None,
- debug=False, outTopol='all', engine='tleap', allhdg=False,
- timeTol=36000, qprog='sqm', ekFlag=None, verbose=True,
- gmx4=False, disam=False, direct=False, is_sorted=False, chiral=False):
-
- self.debug = debug
- self.verbose = verbose
- self.gmx4 = gmx4
- self.disam = disam
- self.direct = direct
- self.sorted = is_sorted
- self.chiral = chiral
- self.inputFile = os.path.basename(inputFile)
- self.rootDir = os.path.abspath('.')
- self.absInputFile = os.path.abspath(inputFile)
- if not os.path.exists(self.absInputFile):
- self.printWarn("input file doesn't exist")
- baseOriginal, ext = os.path.splitext(self.inputFile)
- base = basename or baseOriginal
- self.baseOriginal = baseOriginal
- self.baseName = base # name of the input file without ext.
- self.timeTol = timeTol
- self.printDebug("Max execution time tolerance is %s" % elapsedTime(self.timeTol))
- self.ext = ext
- if ekFlag == '"None"' or ekFlag is None:
- self.ekFlag = ''
- else:
- self.ekFlag = '-ek %s' % ekFlag
- self.extOld = ext
- self.homeDir = self.baseName + '.acpype'
- self.chargeType = chargeType
- self.chargeVal = chargeVal
- self.multiplicity = multiplicity
- self.atomType = atomType
- self.gaffDatfile = 'gaff.dat'
- leapGaffFile = 'leaprc.gaff'
- if '2' in self.atomType:
- leapGaffFile = 'leaprc.gaff2'
- self.gaffDatfile = 'gaff2.dat'
- self.force = force
- self.engine = engine
- self.allhdg = allhdg
- self.acExe = ''
- dirAmber = os.getenv('AMBERHOME', os.getenv('ACHOME'))
- if dirAmber:
- for ac_bin in ['bin', 'exe']:
- ac_path = os.path.join(dirAmber, ac_bin, 'antechamber')
- if os.path.exists(ac_path):
- self.acExe = ac_path
- break
- if not self.acExe:
- self.acExe = _getoutput('which antechamber') or '' # '/Users/alan/Programmes/antechamber-1.27/exe/antechamber'
- if not os.path.exists(self.acExe):
- self.printError("no 'antechamber' executable!")
- return None
- self.tleapExe = _getoutput('which tleap') or ''
- self.sleapExe = _getoutput('which sleap') or ''
- self.parmchkExe = _getoutput('which parmchk2') or ''
- self.babelExe = _getoutput('which babel') or ''
- if not os.path.exists(self.babelExe):
- if self.ext != '.mol2' and self.ext != '.mdl': # and self.ext != '.mol':
- self.printError("no 'babel' executable; you need it if input is PDB")
- self.printError("otherwise use only MOL2 or MDL file as input ... aborting!")
- sys.exit(1)
- else:
- self.printWarn("no 'babel' executable, no PDB file as input can be used!")
- acBase = base + '_AC'
- self.acBaseName = acBase
- self.acXyzFileName = acBase + '.inpcrd'
- self.acTopFileName = acBase + '.prmtop'
- self.acFrcmodFileName = acBase + '.frcmod'
- self.tmpDir = os.path.join(self.rootDir, '.acpype_tmp_%s' % os.path.basename(base))
- self.setResNameCheckCoords()
- self.guessCharge()
- acMol2FileName = '%s_%s_%s.mol2' % (base, chargeType, atomType)
- self.acMol2FileName = acMol2FileName
- self.charmmBase = '%s_CHARMM' % base
- # check for which version of antechamber
- if 'amber10' in self.acExe:
- if qprog == 'sqm':
- self.printWarn("SQM is not implemented in AmberTools 1.2")
- self.printWarn("Setting mopac for antechamber")
- qprog = 'mopac'
- elif qprog == 'divcon':
- if not os.path.exists(os.path.join(os.path.dirname(self.acExe), qprog)):
- self.printWarn("DIVCON is not installed")
- self.printWarn("Setting mopac for antechamber")
- qprog = 'mopac'
- elif 'amber1' in self.acExe:
- if qprog == 'divcon':
- self.printWarn("DIVCON is not implemented in AmberTools > 1.3 anymore")
- self.printWarn("Setting sqm for antechamber")
- qprog = 'sqm'
- elif qprog == 'mopac':
- if not os.path.exists(os.path.join(os.path.dirname(self.acExe), qprog)):
- self.printWarn("MOPAC is not installed")
- self.printWarn("Setting sqm for antechamber")
- return None
- qprog = 'sqm'
- else:
- self.printWarn("Old version of antechamber. Strongly consider upgrading to AmberTools")
- self.printWarn("Setting mopac for antechamber")
- qprog = 'mopac'
- self.qFlag = qDict[qprog]
- self.outTopols = [outTopol]
- if outTopol == 'all':
- self.outTopols = outTopols
- self.acParDict = {'base': base, 'ext': ext[1:], 'acBase': acBase,
- 'acMol2FileName': acMol2FileName, 'res': self.resName,
- 'leapAmberFile': leapAmberFile, 'baseOrg': self.baseOriginal,
- 'leapGaffFile': leapGaffFile}
-
-
- class MolTopol(ACTopol):
-
- """"
- Class to write topologies and parameters files for several applications
- http://amber.scripps.edu/formats.html (not updated to amber 10 yet)
- Parser, take information in AC xyz and top files and convert to objects
- INPUTS: acFileXyz and acFileTop
- RETURN: molTopol obj or None
- """
-
- def __init__(self, acTopolObj=None, acFileXyz=None, acFileTop=None,
- debug=False, basename=None, verbose=True, gmx4=False,
- disam=False, direct=False, is_sorted=False, chiral=False):
-
- self.chiral = chiral
- self.obchiralExe = _getoutput('which obchiral') or ''
- self.allhdg = False
- self.debug = debug
- self.gmx4 = gmx4
- self.disam = disam
- self.direct = direct
- self.sorted = is_sorted
- self.verbose = verbose
- self.inputFile = acFileTop
- if acTopolObj:
- if not acFileXyz:
- acFileXyz = acTopolObj.acXyzFileName
- if not acFileTop:
- acFileTop = acTopolObj.acTopFileName
- self._parent = acTopolObj
- self.allhdg = self._parent.allhdg
- self.debug = self._parent.debug
- self.inputFile = self._parent.inputFile
- if not os.path.exists(acFileXyz) and not os.path.exists(acFileTop):
- self.printError("Files '%s' and '%s' don't exist")
- self.printError("molTopol object won't be created")
- return None
-
- # if not os.path.exists(self.obchiralExe) and self.chiral:
- # self.printError("no 'obchiral' executable, it won't work to store non-planar improper dihedrals!")
- # self.printWarn("Consider installing http://openbabel.org")
-
- self.xyzFileData = open(acFileXyz, 'r').readlines()
- self.topFileData = open(acFileTop, 'r').readlines()
- self.printDebug("prmtop and inpcrd files loaded")
-
- # self.pointers = self.getFlagData('POINTERS')
-
- self.getResidueLabel()
- if len(self.residueLabel) > 1:
- self.baseName = basename or os.path.splitext(os.path.basename(acFileTop))[0] # 'solute'
- else:
- self.baseName = basename or self.residueLabel[0] # 3 caps letters
- if acTopolObj:
- self.baseName = basename or acTopolObj.baseName
- self.printDebug("basename defined = '%s'" % self.baseName)
-
- self.getAtoms()
-
- self.getBonds()
-
- self.getAngles()
-
- self.getDihedrals()
-
- self.getChirals()
- if not os.path.exists(self.obchiralExe) and self.chiral:
- self.printError("no 'obchiral' executable, it won't work to store non-planar improper dihedrals!")
- self.printWarn("Consider installing http://openbabel.org")
- elif self.chiral and not self.chiralGroups:
- self.printWarn("No chiral atoms found")
-
- # self.setAtomPairs()
-
- # self.getExcludedAtoms()
-
- # a list of FLAGS from acTopFile that matter
- # self.flags = ( 'POINTERS', 'ATOM_NAME', 'CHARGE', 'MASS', 'ATOM_TYPE_INDEX',
- # 'NUMBER_EXCLUDED_ATOMS', 'NONBONDED_PARM_INDEX',
- # 'RESIDUE_LABEL', 'BOND_FORCE_CONSTANT', 'BOND_EQUIL_VALUE',
- # 'ANGLE_FORCE_CONSTANT', 'ANGLE_EQUIL_VALUE',
- # 'DIHEDRAL_FORCE_CONSTANT', 'DIHEDRAL_PERIODICITY',
- # 'DIHEDRAL_PHASE', 'AMBER_ATOM_TYPE' )
-
- # Sort atoms for gromacs output. # JDC
- if self.sorted:
- self.printMess("Sorting atoms for gromacs ordering.\n")
- self.sortAtomsForGromacs()
-
-
- class Atom(object):
-
- """
- Charges in prmtop file has to be divide by 18.2223 to convert to charge
- in units of the electron charge.
- To convert ACOEF and BCOEF to r0 (Ang.) and epsilon (kcal/mol), as seen
- in gaff.dat for example; same atom type (i = j):
- r0 = 1/2 * (2 * ACOEF/BCOEF)^(1/6)
- epsilon = 1/(4 * A) * BCOEF^2
- To convert r0 and epsilon to ACOEF and BCOEF
- ACOEF = sqrt(ep_i * ep_j) * (r0_i + r0_j)^12
- BCOEF = 2 * sqrt(ep_i * ep_j) * (r0_i + r0_j)^6
- = 2 * ACOEF/(r0_i + r0_j)^6
- where index i and j for atom types.
- Coord is given in Ang. and mass in Atomic Mass Unit.
- """
-
- def __init__(self, atomName, atomType, id_, resid, mass, charge, coord):
- self.atomName = atomName
- self.atomType = atomType
- self.id = id_
- self.cgnr = id_
- self.resid = resid
- self.mass = mass
- self.charge = charge # / qConv
- self.coords = coord
-
- def __str__(self):
- return '<Atom id=%s, name=%s, %s>' % (self.id, self.atomName, self.atomType)
-
- def __repr__(self):
- return '<Atom id=%s, name=%s, %s>' % (self.id, self.atomName, self.atomType)
-
-
- class AtomType(object):
-
- """
- AtomType per atom in gaff or amber.
- """
-
- def __init__(self, atomTypeName, mass, ACOEF, BCOEF):
- self.atomTypeName = atomTypeName
- self.mass = mass
- self.ACOEF = ACOEF
- self.BCOEF = BCOEF
-
- def __str__(self):
- return '<AtomType=%s>' % self.atomTypeName
-
- def __repr__(self):
- return '<AtomType=%s>' % self.atomTypeName
-
-
- class Bond(object):
-
- """
- attributes: pair of Atoms, spring constant (kcal/mol), dist. eq. (Ang)
- """
-
- def __init__(self, atoms, kBond, rEq):
- self.atoms = atoms
- self.kBond = kBond
- self.rEq = rEq
-
- def __str__(self):
- return '<%s, r=%s>' % (self.atoms, self.rEq)
-
- def __repr__(self):
- return '<%s, r=%s>' % (self.atoms, self.rEq)
-
-
- class Angle(object):
-
- """
- attributes: 3 Atoms, spring constant (kcal/mol/rad^2), angle eq. (rad)
- """
-
- def __init__(self, atoms, kTheta, thetaEq):
- self.atoms = atoms
- self.kTheta = kTheta
- self.thetaEq = thetaEq # rad, to convert to degree: thetaEq * 180/Pi
-
- def __str__(self):
- return '<%s, ang=%.2f>' % (self.atoms, self.thetaEq * 180 / Pi)
-
- def __repr__(self):
- return '<%s, ang=%.2f>' % (self.atoms, self.thetaEq * 180 / Pi)
-
-
- class Dihedral(object):
-
- """
- attributes: 4 Atoms, spring constant (kcal/mol), periodicity,
- phase (rad)
- """
-
- def __init__(self, atoms, kPhi, period, phase):
- self.atoms = atoms
- self.kPhi = kPhi
- self.period = period
- self.phase = phase # rad, to convert to degree: kPhi * 180/Pi
-
- def __str__(self):
- return '<%s, ang=%.2f>' % (self.atoms, self.phase * 180 / Pi)
-
- def __repr__(self):
- return '<%s, ang=%.2f>' % (self.atoms, self.phase * 180 / Pi)
-
- if __name__ == '__main__':
- t0 = time.time()
- print(header)
-
- parser = optparse.OptionParser(usage=usage + epilog)
- parser.add_option('-i', '--input',
- action="store",
- dest='input',
- help="input file name with either extension '.pdb', '.mdl' or '.mol2' (mandatory if -p and -x not set)",)
- parser.add_option('-b', '--basename',
- action="store",
- dest='basename',
- help='a basename for the project (folder and output files)',)
- parser.add_option('-x', '--inpcrd',
- action="store",
- dest='inpcrd',
- help="amber inpcrd file name (always used with -p)",)
- parser.add_option('-p', '--prmtop',
- action="store",
- dest='prmtop',
- help="amber prmtop file name (always used with -x)",)
- parser.add_option('-c', '--charge_method',
- type='choice',
- choices=['gas', 'bcc', 'user'],
- action="store",
- default='bcc',
- dest='charge_method',
- help="charge method: gas, bcc (default), user (user's charges in mol2 file)",)
- parser.add_option('-n', '--net_charge',
- action="store",
- type='int',
- default=0,
- dest='net_charge',
- help="net molecular charge (int), for gas default is 0",)
- parser.add_option('-m', '--multiplicity',
- action="store",
- type='int',
- default=1,
- dest='multiplicity',
- help="multiplicity (2S+1), default is 1",)
- parser.add_option('-a', '--atom_type',
- type='choice',
- choices=['gaff', 'amber', 'gaff2', 'amber2'], # , 'bcc', 'sybyl']
- action="store",
- default='gaff',
- dest='atom_type',
- help="atom type, can be gaff, gaff2, amber (AMBER14SB) or amber2 (AMBER14SB + GAFF2), default is gaff",)
- parser.add_option('-q', '--qprog',
- type='choice',
- choices=['mopac', 'sqm', 'divcon'],
- action="store",
- default='sqm',
- dest='qprog',
- help="am1-bcc flag, sqm (default), divcon, mopac",)
- parser.add_option('-k', '--keyword',
- action="store",
- dest='keyword',
- help="mopac or sqm keyword, inside quotes",)
- parser.add_option('-f', '--force',
- action="store_true",
- dest='force',
- help='force topologies recalculation anew',)
- parser.add_option('-d', '--debug',
- action="store_true",
- dest='debug',
- help='for debugging purposes, keep any temporary file created',)
- parser.add_option('-o', '--outtop',
- type='choice',
- choices=['all'] + outTopols,
- action="store",
- default='all',
- dest='outtop',
- help="output topologies: all (default), gmx, cns or charmm",)
- parser.add_option('-z', '--gmx4',
- action="store_true",
- dest='gmx4',
- help='write RB dihedrals old GMX 4.0',)
- parser.add_option('-t', '--cnstop',
- action="store_true",
- dest='cnstop',
- help='write CNS topology with allhdg-like parameters (experimental)',)
- parser.add_option('-e', '--engine',
- type='choice',
- choices=['tleap', 'sleap'],
- action="store",
- default='tleap',
- dest='engine',
- help="engine: tleap (default) or sleap (not fully matured)",)
- parser.add_option('-s', '--max_time',
- action="store",
- type='int',
- default=36000,
- dest='max_time',
- help="max time (in sec) tolerance for sqm/mopac, default is 10 hours",)
- parser.add_option('-y', '--ipython',
- action="store_true",
- dest='ipython',
- help='start iPython interpreter',)
- parser.add_option('-w', '--verboseless',
- action="store_false",
- default=True,
- dest='verboseless',
- help='print nothing',)
- parser.add_option('-g', '--disambiguate',
- action="store_true",
- dest='disambiguate',
- help='disambiguate lower and uppercase atomtypes in GMX top file',)
- parser.add_option('-u', '--direct',
- action="store_true",
- dest='direct',
- help="for 'amb2gmx' mode, does a direct conversion, for any solvent",)
- parser.add_option('-l', '--sorted',
- action="store_true",
- dest='sorted',
- help="sort atoms for GMX ordering",)
- parser.add_option('-j', '--chiral',
- action="store_true",
- dest='chiral',
- help="create improper dihedral parameters for chiral atoms in CNS",)
-
- options, remainder = parser.parse_args()
-
- amb2gmx = False
-
- # if options.chiral:
- # options.cnstop = True
-
- if not options.input:
- amb2gmx = True
- if not options.inpcrd or not options.prmtop:
- parser.error("missing input files")
- elif options.inpcrd or options.prmtop:
- parser.error("either '-i' or ('-p', '-x'), but not both")
-
- if options.debug:
- text = "Python Version %s" % verNum
- print('DEBUG: %s' % text)
-
- if options.direct and not amb2gmx:
- parser.error("option -u is only meaningful in 'amb2gmx' mode")
-
- try:
- if amb2gmx:
- print("Converting Amber input files to Gromacs ...")
- system = MolTopol(acFileXyz=options.inpcrd, acFileTop=options.prmtop,
- debug=options.debug, basename=options.basename,
- verbose=options.verboseless, gmx4=options.gmx4,
- disam=options.disambiguate, direct=options.direct,
- is_sorted=options.sorted, chiral=options.chiral)
- system.printDebug("prmtop and inpcrd files parsed")
- system.writeGromacsTopolFiles(amb2gmx=True)
- else:
- molecule = ACTopol(options.input, chargeType=options.charge_method,
- chargeVal=options.net_charge, debug=options.debug,
- multiplicity=options.multiplicity, atomType=options.atom_type,
- force=options.force, outTopol=options.outtop,
- engine=options.engine, allhdg=options.cnstop,
- basename=options.basename, timeTol=options.max_time,
- qprog=options.qprog, ekFlag='''"%s"''' % options.keyword,
- verbose=options.verboseless, gmx4=options.gmx4,
- disam=options.disambiguate, direct=options.direct,
- is_sorted=options.sorted, chiral=options.chiral)
-
- if not molecule.acExe:
- molecule.printError("no 'antechamber' executable... aborting ! ")
- hint1 = "HINT1: is 'AMBERHOME' or 'ACHOME' environment variable set?"
- hint2 = "HINT2: is 'antechamber' in your $PATH?\n What 'which antechamber' in your terminal says?\n 'alias' doesn't work for ACPYPE."
- molecule.printMess(hint1)
- molecule.printMess(hint2)
- sys.exit(1)
-
- molecule.createACTopol()
- molecule.createMolTopol()
- acpypeFailed = False
- except:
- exceptionType, exceptionValue, exceptionTraceback = sys.exc_info()
- print("ACPYPE FAILED: %s" % exceptionValue)
- if options.debug:
- traceback.print_tb(exceptionTraceback, file=sys.stdout)
- acpypeFailed = True
-
- execTime = int(round(time.time() - t0))
- if execTime == 0:
- msg = "less than a second"
- else:
- msg = elapsedTime(execTime)
- print("Total time of execution: %s" % msg)
-
- if options.ipython:
- try:
- from IPython.Shell import IPShellEmbed # @UnresolvedImport @UnusedImport
- except:
- from IPython.frontend.terminal.embed import InteractiveShellEmbed as IPShellEmbed # @UnresolvedImport @Reimport
- ipshell = IPShellEmbed()
- ipshell()
-
- try:
- rmtree(molecule.tmpDir)
- except:
- pass
- if acpypeFailed:
- sys.exit(1)
- try:
- os.chdir(molecule.rootDir)
- except:
- pass
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。