def copy_top_and_dependancies(self, dest_file): dest_folder = os_command.get_directory(dest_file) logger.info("Copy topologie file and dependancies") if self.path != os.path.abspath(dest_file): shutil_copy(self.path, os.path.abspath(dest_file)) self.copy_dependancies(dest_folder)
def get_include_file_list(self): file_list = [] for posre in self.posres_file: # print(posre) file_list.append( os.path.abspath( os.path.join(os_command.get_directory(self.path), posre['file']))) return file_list
def add_posre(self, mol_name, posre_name, selec_dict, fc, replace=True): for top_mol in self.top_mol_list: # print(mol_name, top_mol.name) if top_mol.name == mol_name: index_posre = top_mol.get_selection_index( selec_dict=selec_dict) if index_posre: # Create the posre itp file : logger.debug("Posre for : {}".format(top_mol.name)) posre_file_name = os.path.abspath( os.path.join( os_command.get_directory(self.path), self.name + "_posre_" + posre_name + ".itp")) # posre_file_name = self.name+"_posre_"+posre_name+".itp" write_index_posre_file(atom_index_list=index_posre, posre_file=posre_file_name, type_val=1, fc=fc) # Add the posre include in the mol itp file: # Need to solve the problem of #ifdef location with .top # files containing self top if replace: # Remove previous def: new_content = "" with open(self.path) as file: posre_def = None for line in file: # print("Itp line: \"{}\" ".format(line)) # Check posres include: if line[:6] == '#ifdef': line_list = line.split() posre_def = line_list[1] if posre_def != posre_name: new_content += line if line[:6] == '#endif': posre_def = None # Add the new one: new_content += '#ifdef ' + posre_name + '\n' new_content += '#include \"' +\ os.path.basename(posre_file_name) + "\" \n" new_content += '#endif \n\n' # Save the file: file = open(self.path, "w") file.write(new_content) file.close() else: with open(self.path, 'a') as file: file.write('#ifdef ' + posre_name + '\n') # file.write('#include \"'+self.name+"_posre_"+\ # posre_name+".itp\" \n") file.write('#include \"' + os.path.basename(posre_file_name) + "\" \n") file.write('#endif \n\n')
def write_file(self, top_out): filout = open(top_out, 'w') filout.write("; Topologie file created by " + __name__ + "\n") if self.forcefield: filout.write("; Forcefield: \n") filout.write("#include \"" + self.forcefield['fullname'] + "\"\n") # print include files filout.write("\n; Itp to include: \n") for itp in self.itp_list: filout.write("#include \"" + itp.fullname + "\"\n") # Check if the include is in the ff folder: # if self.forcefield['fullname'].split("/")[0] == \ # itp.fullname.split("/")[0]: # filout.write("#include \""+itp.fullname+"\"\n") # else: # filout.write("#include \""+itp.fullname+"\"\n") filout.write("\n[ system ]\n; Name\n") filout.write(self.name + "\n") filout.write("\n[ molecules ]\n; Compound #mols\n") for mol in self.mol_comp: filout.write(mol['name'] + " \t" + mol['num'] + "\n") filout.write("\n") # INTER if self.inter_interact: filout.write("[ intermolecular_interactions ]\n") if self.inter_bond_list: filout.write("\n[ bonds ]\n; ai aj type " " bA kA bB kB\n") for param in self.inter_bond_list: filout.write( "{:>6}{:>6}{:>6}{:>13}{:>13}{:>13}{:>13}\n".format( param['ai'], param['aj'], param['type'], param['rA'], param['kA'], param['rB'], param['kB'])) if self.inter_angl_list: filout.write("\n[ angles ]\n; ai aj ak " " type thA kA thB kB\n") for param in self.inter_angl_list: filout.write("{:>6}{:>6}{:>6}{:>6}{:>13}{:>13}{:>13}" "{:>13}\n".format(param['ai'], param['aj'], param['ak'], param['type'], param['thA'], param['kA'], param['thB'], param['kB'])) if self.inter_dihe_list: filout.write("\n[ dihedrals ]\n; ai aj ak al" " type phiA kA phiB kB\n") for param in self.inter_dihe_list: filout.write("{:>6}{:>6}{:>6}{:>6}{:>6}{:>13}{:>13}" "{:>13}{:>13}\n".format( param['ai'], param['aj'], param['ak'], param['al'], param['type'], param['thA'], param['kA'], param['thB'], param['kB'])) filout.close() self.copy_dependancies(os_command.get_directory(top_out))
def copy_dependancies(self, dest_folder): dest_folder = os.path.abspath(dest_folder) file_to_copy = self.get_include_file_list() # print(file_to_copy) for file in file_to_copy: if os.path.abspath(os_command.get_directory(file)) !=\ os.path.abspath(dest_folder): # print("Copy: "+file+":to: "+dest_folder) shutil_copy(file, dest_folder)
def __init__(self, top_in): self.path = os_command.full_path_and_check(top_in) self.forcefield = None self.itp_list = [] self.mol_comp = [] self.name = "" self.folder = os_command.get_directory(top_in) self.include_itp = False # Intermolecular restraints (only for Free ener): self.inter_interact = False self.inter_bond_list = [] self.inter_angl_list = [] self.inter_dihe_list = [] self.read_file(top_in) if self.include_itp: logger.info("Rewrite topologie: {}".format(top_in)) self.write_file(top_in)
def antechamber(pdb_in, mol2_out, charge_model="bcc", check_file_out=True, **antechamber_options): """Compute a molecule topologie using the ``antechamber`` software: :param pdb_in: pdb input :type pdb_in: str :param mol2_out: pdb output :type mol2_out: str :param charge_model: charge model :type charge_model: str, default="bcc" :param check_file_out: flag to check or not if file has already been created. If the file is present then the command break. :type check_file_out: bool, optional, default=True :param reduce_options: Optional arguments for ``reduce`` Output files: - mol2_out - ANTECHAMBER_AM1BCC_PRE.AC - ANTECHAMBER_BOND_TYPE.AC - ANTECHAMBER_BOND_TYPE.AC0 - ANTECHAMBER_AC.AC - ATOMTYPE.INF - ANTECHAMBER_AC.AC0 - ANTECHAMBER_AM1BCC.AC :Example: >>> pdb_manip.show_log() >>> TEST_OUT = getfixture('tmpdir') >>> add_hydrogen(pdb_in=TEST_PATH+'/phenol.pdb',\ pdb_out=TEST_OUT+'/phenol_h.pdb') #doctest: +ELLIPSIS reduce -build -nuclear .../phenol.pdb >>> phenol_coor = pdb_manip.Coor(TEST_OUT+'/phenol_h.pdb') \ #doctest: +ELLIPSIS Succeed to read file .../phenol_h.pdb , 13 atoms found >>> antechamber(pdb_in=TEST_OUT+'/phenol_h.pdb',\ mol2_out=TEST_OUT+'/phenol_h.mol2') #doctest: +ELLIPSIS antechamber -i phenol_h.pdb -fi pdb -o phenol_h.mol2 -fo \ mol2 -c bcc """ # Check if output files exist: if check_file_out and os.path.isfile(mol2_out): logger.info( "MOL2 files not created, {} already exist".format(mol2_out)) return start_dir = os.path.abspath(".") # Create and go in out_folder: out_folder = os_command.get_directory(mol2_out) os_command.create_and_go_dir(out_folder) # Define reduce command: cmd_antechamber = os_command.Command([ ANTECHAMBER_BIN, "-i", pdb_in, "-fi", str(pdb_in).split('.')[-1], "-o", mol2_out, "-fo", "mol2", "-c", charge_model ], **antechamber_options) cmd_antechamber.display() cmd_antechamber.run(display=False) logger.info("Succeed to save file %s" % os.path.relpath(mol2_out)) # Get absolute path: os.chdir(start_dir) return
def correct_charge_type(self, forcefield, index_list=None): """ Correct the charge and atom type of an itp object, base on a ff `.rtp` file. This is specially usefull, to correct charge of termini resiudes of a cyclicized peptide. if index_list is None, will correct all atom charges, if not, only atoms listed in index_list. """ # First extract charge and type from the ff .rtp file forcefield_path = forcefield['path'] rtp_path = os.path.abspath( os.path.join(os_command.get_directory(forcefield_path), 'aminoacids.rtp')) if not os_command.check_file_exist(rtp_path): rtp_path = os.path.abspath( os.path.join(os_command.get_directory(forcefield_path), 'merged.rtp')) logger.info('Read rtp file : {}'.format(rtp_path)) ff_rtp = Rtp(rtp_path) # Correct charges and type: # for atom_num, atom in self.atom_dict.items(): if index_list is None: index_list = self.atom_dict.keys() for atom_num in index_list: atom = self.atom_dict[atom_num] res_name = atom['res_name'] resid = atom['res_num'] atom_name = atom['atom_name'] # With Amber disulfide cys are called CYX in the rtp and CYS in # the itp. # Don't get sense but need to check the protonation state of cys # By counting atoms # With charmm disuldie cys is CYS2 if res_name == 'CYS': if len( self.get_selection_index(selec_dict={ 'res_num': [resid], 'res_name': ['CYS'] })) == 10: if forcefield['name'].startswith('amber'): res_name = 'CYX' elif forcefield['name'].startswith('charmm'): res_name = 'CYS2' # print(res_name) # With gromacs all histidine are called HIS ! if res_name == 'HIS': if len( self.get_selection_index(selec_dict={ 'res_num': [resid], 'res_name': ['HIS'] })) == 18: if forcefield['name'].startswith('amber'): res_name = 'HIP' elif forcefield['name'].startswith('charmm'): res_name = 'HSP' elif len( self.get_selection_index(selec_dict={ 'res_num': [resid], 'atom_name': ['HE2'] })) == 1: if forcefield['name'].startswith('amber'): res_name = 'HIE' elif forcefield['name'].startswith('charmm'): res_name = 'HSE' else: if forcefield['name'].startswith('amber'): res_name = 'HID' elif forcefield['name'].startswith('charmm'): res_name = 'HSD' # print(atom) # print(ff_rtp.res_dict[res_name]['atom'][atom_name]) if atom_name in ff_rtp.res_dict[res_name]['atom']: atom_type = \ ff_rtp.res_dict[res_name]['atom'][atom_name]['type'] atom_charge = \ ff_rtp.res_dict[res_name]['atom'][atom_name]['charge'] # print('Correct residue {:4} atom {:4} atom type {:4} ' # 'to {:4}'.format(res_name, atom['atom_name'], # atom['atom_type'], atom_type)) # print('Correct charge {:4} ' # 'to {:4}'.format(self.atom_dict[atom_num]['charge'], # atom_charge)) if atom_type != atom['atom_type']: logger.warning('Correct residue {:4} atom {:4} atom ' 'type {:4} to {:4}'.format( res_name, atom['atom_name'], atom['atom_type'], atom_type)) else: logger.warning('Can\'t find residue {:4} atom {:4} atom ' 'type {:4} parameters in forcefield'.format( res_name, atom['atom_name'], atom['atom_type'])) self.atom_dict[atom_num]['atom_type'] = atom_type self.atom_dict[atom_num]['charge'] = atom_charge
def compute_pdb2pqr(pdb_in, pdb_out, ff="CHARMM", method='propka', ph=7.0, check_file_out=True): """ Use pdb2pqr to define protonation state of each residue of a protein. :param pdb_in: path of input pdb file :type pdb_in: str :param pdb_out: path of output pdb file :type pdb_out: str :param ff: forcefield nomenclature for atom names :type ff: str, optional, default="CHARMM" :param method: Method used to calculate ph values (propka or pdb2pka). :type method: str, optional, default="propka" :param ph: pH value to define AA residue :type ph: float, optional, default=7.0 :param check_file_out: flag to check or not if file has already been created. If the file is present then the command break. :type check_file_out: bool, optional, default=True :Example: >>> pdb_manip.show_log() >>> TEST_OUT = str(getfixture('tmpdir')) >>> # Compute protonation with pdb2pqr: >>> compute_pdb2pqr(os.path.join(TEST_PATH,'4n1m.pdb'), ... os.path.join(TEST_OUT, '4n1m.pqr')) #doctest: +ELLIPSIS Succeed to read file ...4n1m.pdb , 2530 atoms found Succeed to save file ...tmp_pdb2pqr.pdb pdb2pqr30... --ff CHARMM --ffout CHARMM --keep-chain \ --titration-state-method=propka --with-ph=7.00 \ ...tmp_pdb2pqr.pdb ...4n1m.pqr 0 >>> prot_coor = pdb_manip.Coor() >>> prot_coor.read_pdb(os.path.join(TEST_OUT, '4n1m.pqr'), \ pqr_format = True) #doctest: +ELLIPSIS Succeed to read file ...4n1m.pqr , 2549 atoms found >>> HSD_index = prot_coor.get_index_selection({'res_name' : ['HSD'], ... 'name':['CA']}) >>> print(len(HSD_index)) 4 >>> HSE_index = prot_coor.get_index_selection({'res_name' : ['HSE'], ... 'name':['CA']}) >>> print(len(HSE_index)) 0 >>> HSP_index = prot_coor.get_index_selection({'res_name' : ['HSP'], ... 'name':['CA']}) >>> print(len(HSP_index)) 1 .. note:: Idealy I would need a pdb file with 3 different histidine protonation. I couldn't find one. """ # print("Compute pdb2pqr on",pdb_in) # Check if output files exist and create directory: if check_file_out and os_command.check_file_and_create_path(pdb_out): logger.info("pdb2pqr not launched %s already exist" % pdb_out) return pdb_out out_folder = os_command.get_directory(pdb_out) # print("out_folder", out_folder) # WARING : # Many bugs are due to the REMARK field in pdb2pqr # The 2 following steps remove the REMARK field of the pdb tmp_coor = pdb_manip.Coor() tmp_coor.read_pdb(pdb_in) # Remove Nucleic acids: # WARNING, that part might be removed, as pdb2pqr could compute # protonation on nucleic acid in a near future na_index = tmp_coor.get_index_selection({'res_name': pdb_manip.NA_DICT}) tmp_coor.del_atom_index(index_list=na_index) # Remove HETATM no_hetatm_pdb = tmp_coor.select_part_dict({'field': 'ATOM'}) if no_hetatm_pdb.num == 0: logger.warning('No amino acids present in pdb file' ', no PD2PQR calculation') tmp_coor = pdb_manip.Coor() tmp_coor.read_pdb(pdb_in) # To be coherent with the pdb2pqr calc., remove HETATOM : no_hetatm_pdb = tmp_coor.select_part_dict({'field': 'ATOM'}) no_hetatm_pdb.write_pqr(pdb_out) return no_hetatm_pdb.write_pdb(os.path.join(out_folder + "/tmp_pdb2pqr.pdb")) cmd_pdb2pqr = os_command.Command([ PDB2PQR_BIN, "--ff", ff, "--ffout", ff, "--keep-chain", "--titration-state-method={}".format(method), "--with-ph={:.2f}".format(ph), os.path.join(out_folder + "/tmp_pdb2pqr.pdb"), pdb_out ]) cmd_pdb2pqr.display() out_data = cmd_pdb2pqr.run() os_command.delete_file(os.path.join(out_folder + "/tmp_pdb2pqr.pdb")) return out_data