def is_item(item, check=True): from molsysmt.basic import get_form try: form = get_form(item) output = True except: output = False return output
def is_string(item, check=True): from molsysmt.basic import get_form from molsysmt.tools.form import is_string as form_is_string if check: from molsysmt.tools.item import is_item if not is_item(item): raise WrongItemError() form = get_form(item, check=False) return form_is_string(form)
def add_missing_heavy_atoms(molecular_system, selection='all', missing_heavy_atoms=None, engine='PDBFixer', syntaxis='MolSysMT'): engine = digest_engine(engine) output = None if engine == "PDBFixer": from molsysmt.basic import convert, get_form, select output_form = get_form(molecular_system) if missing_heavy_atoms is None: from molsysmt.build import get_missing_heavy_atoms missing_heavy_atoms = get_missing_heavy_atoms(molecular_system, selection=selection, syntaxis=syntaxis) tmp_molecular_system = convert(molecular_system, to_form="pdbfixer.PDBFixer") tmp_molecular_system.missingResidues = {} tmp_molecular_system.findMissingAtoms() tmp_molecular_system.missingTerminals = {} aux_dict = {} for group, atoms in tmp_molecular_system.missingAtoms.items(): if group.index in missing_heavy_atoms: aux_dict[group] = [] for atom in atoms: if atom.name in missing_heavy_atoms[group.index]: aux_dict[group].append(atom) tmp_molecular_system.missingAtoms = aux_dict tmp_molecular_system.addMissingAtoms() output = convert(tmp_molecular_system, to_form=output_form) else: raise NotImplementedError return output
def mutate(molecular_system, residue_indices=None, to_residue_names=None, engine='PDBFixer', verbose=False): if engine == "PDBFixer": from molsysmt.basic import get, convert, get_form if not hasattr(residue_indices, '__iter__'): residue_indices = [residue_indices] if not hasattr(to_residue_names, '__iter__'): to_residue_names = [to_residue_names] to_residue_names = [name.upper() for name in to_residue_names] form_in = get_form(molecular_system) tmp_molecular_system = convert(molecular_system, to_form="pdbfixer.PDBFixer") from_residue_names, residue_ids, in_chain_ids = get( tmp_molecular_system, target='group', indices=residue_indices, group_name=True, group_id=True, chain_id=True) for residue_id, from_residue_name, to_residue_name, in_chain_id in zip( residue_ids, from_residue_names, to_residue_names, in_chain_ids): mutation_string = "-".join( [from_residue_name, str(residue_id), to_residue_name]) if verbose: print(mutation_string) tmp_molecular_system.applyMutations([mutation_string], in_chain_id) tmp_molecular_system = convert(tmp_molecular_system, to_form=form_in) return tmp_molecular_system else: raise NotImplementedError
def add_terminal_cappings(molecular_system, N_terminal=None, C_terminal=None, selection='all', syntaxis='MolSysMT', engine='PDBFixer'): from molsysmt.basic import get_form, convert, get, select form_in = get_form(molecular_system) if engine is 'PDBFixer': from pdbfixer.pdbfixer import Sequence tmp_molecular_system = convert(molecular_system, to_form='pdbfixer.PDBFixer') atom_indices_in_selection = select(tmp_molecular_system, selection=selection, syntaxis=syntaxis) atom_indices_in_components = get( tmp_molecular_system, target='component', selection='component_type in ["peptide", "protein"] \ and atom_index in @atom_indices_in_selection', atom_index=True) for atom_indices_in_component in atom_indices_in_components: chain_id = get( tmp_molecular_system, target='chain', selection='atom_index in @atom_indices_in_component', chain_id=True) groups_sequence = get( tmp_molecular_system, target='group', selection='atom_index in @atom_indices_in_component', group_name=True) groups_sequence = list(groups_sequence) if N_terminal is not None: groups_sequence = [N_terminal] + groups_sequence if C_terminal is not None: groups_sequence = groups_sequence + [C_terminal] tmp_molecular_system.sequences.append( Sequence(chain_id, groups_sequence)) tmp_molecular_system.findMissingResidues() tmp_molecular_system.findMissingAtoms() tmp_molecular_system.addMissingAtoms() n_hs = get(tmp_molecular_system, target='atom', selection='atom_type=="H"', n_atoms=True) if n_hs > 0: tmp_molecular_system.addMissingHydrogens(pH=7.4) tmp_molecular_system = convert(tmp_molecular_system, to_form=form_in) else: raise NotImplementedError return tmp_molecular_system
def equilibration_NPT(item, temperature=300 * _unit.kelvin, pressure=1.0 * _unit.atmosphere, time=1.0 * _unit.nanosecond, protocol=0, forcefield=['AMBER99SB-ILDN', 'TIP3P'], engine='OpenMM', verbose=True, form_out=None, *kwargs): """equilibration_NPT (item, protocol, forcefield, constraint_HBonds, engine, verbose) Description Parameters ---------- item : molecular model Molecular model in any form to be operated by the method. protocol : int (default 0) description. forcefield : list or str (default ["AMBER99SB-ILDN", "TIP3P"]) Forcefield to model the inter-atomic interactions. engine : str (default "OpenMM") Returns ------- item : molecular model The result is a new molecular model with coordinates or positions relaxed to the nearest local minimum of the potential energy. Examples -------- Remove chains 0 and 1 from the pdb: 1B3T. >>> import molsysmt as m3t >>> system = m3t.load('pdb:1B3T') >>> minimized_system = m3t.minimze(system) >>> minimized_equilibrated = m3t.equilibration_NPT(system) """ from molsysmt.basic import get_form, get, convert, reformat engine = _digest_engines(engine) if engine == 'OpenMM': in_form = get_form(item) forcefield = _digest_forcefields(forcefield, engine) in_form = get_form(item) topology = _convert(item, 'openmm.Topology') positions = get(item, coordinates=True) positions = reformat(attribute='coordinates', value=positions, is_format=in_form, to_format='openmm') if protocol == 0: new_positions, new_velocities, equil_data = _equil_NPT_OpenMM_protocol_0( topology, positions, temperature=temperature, pressure=pressure, time=time, forcefield=forcefield, verbose=verbose, progress_bar=progress_bar) else: raise NotImplementedError
def solvate(molecular_system, box_geometry="truncated octahedral", clearance='14.0 angstroms', anion='Cl-', num_anions="neutralize", cation='Na+', num_cations="neutralize", ionic_strength='0.0 molar', engine="LEaP", to_form=None, logfile=False, verbose=False): """solvate(item, geometry=None, water=None, engine=None) Methods and wrappers to create and solvate boxes Parameters ---------- anion: 'Cl-', 'Br-', 'F-', and 'I-' num_anions: number of cations to add. integer or "neutralize" cation: "NA" 'Cs+', 'K+', 'Li+', 'Na+', and 'Rb+' num_cations: number of cations to add. integer or "neutralize" box_geometry: "cubic", "truncated_octahedral" or "rhombic_dodecahedron" (Default: "truncated_octahedral") Returns ------- item : bla bla bla bla Examples -------- See Also -------- Notes ----- """ from molsysmt.basic import get_form, convert engine = digest_engine(engine) to_form = digest_to_form(to_form) if to_form is None: to_form = get_form(molecular_system) if engine == "OpenMM": from openmm import Vec3 clearance = puw.convert(clearance, to_form='openmm.unit') ionic_strength = puw.convert(ionic_strength, to_form='openmm.unit') modeller = convert(molecular_system, to_form='openmm.Modeller') molecular_mechanics = convert(molecular_system, to_form='molsysmt.MolecularMechanics') parameters = molecular_mechanics.get_openmm_System_parameters() forcefield = molecular_mechanics.to_openmm_ForceField() solvent_model = None if molecular_mechanics.water_model == 'SPC': solvent_model = 'tip3p' elif molecular_mechanics.water_model in [ 'TIP3P', 'TIP3PFB', 'SPCE', 'TIP4PEW', 'TIP4PFB', 'TIP5P' ]: solvent_model = molecular_mechanics.water_model.lower() else: raise NotImplementedError() if box_geometry == "truncated octahedral": max_size = max( max((pos[i] for pos in modeller.positions)) - min((pos[i] for pos in modeller.positions)) for i in range(3)) vectors = Vec3(1.0, 0, 0), Vec3(1.0 / 3.0, 2.0 * np.sqrt(2.0) / 3.0, 0.0), Vec3(-1.0 / 3.0, np.sqrt(2.0) / 3.0, np.sqrt(6.0) / 3.0) box_vectors = [(max_size + clearance) * v for v in vectors] modeller.addSolvent(forcefield, model=solvent_model, boxVectors=box_vectors, ionicStrength=ionic_strength, positiveIon=cation, negativeIon=anion) elif box_geometry == "rhombic dodecahedral": max_size = max( max((pos[i] for pos in modeller.positions)) - min((pos[i] for pos in modeller.positions)) for i in range(3)) vectors = Vec3(1.0, 0.0, 0.0), Vec3(0.0, 1.0, 0.0), Vec3(0.5, 0.5, np.sqrt(2) / 2) box_vectors = [(max_size + clearance) * v for v in vectors] modeller.addSolvent(forcefield, model=solvent_model, boxVectors=box_vectors, ionicStrength=ionic_strength, positiveIon=cation, negativeIon=anion) else: modeller.addSolvent(forcefield, model=solvent_model, padding=clearance, ionicStrength=ionic_strength, positiveIon=cation, negativeIon=anion) tmp_item = convert(modeller, to_form=to_form) del (modeller) return tmp_item elif engine == "PDBFixer": from openmm import Vec3 clearance = puw.convert(clearance, to_form='openmm.unit') ionic_strength = puw.convert(ionic_strength, to_form='openmm.unit') pdbfixer = convert(molecular_system, to_form='pdbfixer.PDBFixer') max_size = max( max((pos[i] for pos in pdbfixer.positions)) - min((pos[i] for pos in pdbfixer.positions)) for i in range(3)) box_size = None box_vectors = None if box_geometry == "truncated octahedral": vectors = Vec3(1.0, 0, 0), Vec3(1.0 / 3.0, 2.0 * np.sqrt(2.0) / 3.0, 0.0), Vec3(-1.0 / 3.0, np.sqrt(2.0) / 3.0, np.sqrt(6.0) / 3.0) elif box_geometry == "rhombic dodecahedral": vectors = Vec3(1.0, 0.0, 0.0), Vec3(0.0, 1.0, 0.0), Vec3(0.5, 0.5, np.sqrt(2) / 2) elif box_geometry == "cubic": vectors = Vec3(1.0, 0.0, 0.0), Vec3(0.0, 1.0, 0.0), Vec3(0.0, 0.0, 1.0) box_vectors = [(max_size + clearance) * v for v in vectors] pdbfixer.addSolvent(boxVectors=box_vectors, ionicStrength=ionic_strength, positiveIon=cation, negativeIon=anion) tmp_item = convert(pdbfixer, to_form=to_form) del (pdbfixer) return tmp_item elif engine == "LEaP": from molsysmt.thirds.tleap import TLeap from molsysmt._private.files_and_directories import temp_directory, temp_filename from molsysmt.tools.file_pdb import replace_HETATM_by_ATOM_in_terminal_cappings from shutil import rmtree, copyfile from os import getcwd, chdir from molsysmt.basic import set as _set, select from molsysmt.build import has_hydrogens, remove_hydrogens if has_hydrogens(molecular_system): raise ValueError( "A molecular system without hydrogen atoms is needed.") #molecular_system = remove_hydrogens(molecular_system) #if verbose: # print("All Hydrogen atoms were removed to be added by LEaP\n\n") indices_NME_C = select( molecular_system, target='atom', selection='group_name=="NME" and atom_name=="C"') with_NME_C = (len(indices_NME_C) > 0) if with_NME_C: _set(molecular_system, target='atom', selection='group_name=="NME" and atom_name=="C"', atom_name='CH3') current_directory = getcwd() working_directory = temp_directory() pdbfile_in = temp_filename(dir=working_directory, extension='pdb') _ = convert(molecular_system, to_form=pdbfile_in) #replace_HETATM_from_capping_atoms(pdbfile_in) tmp_prmtop = temp_filename(dir=working_directory, extension='prmtop') tmp_inpcrd = tmp_prmtop.replace('prmtop', 'inpcrd') tmp_logfile = tmp_prmtop.replace('prmtop', 'leap.log') molecular_mechanics = convert(molecular_system, to_form='molsysmt.MolecularMechanics') parameters = molecular_mechanics.get_leap_parameters() forcefield = parameters['forcefield'] water = parameters['water_model'] solvent_model = None if water == 'SPC': solvent_model = 'SPCBOX' elif water == 'TIP3P': solvent_model = 'TIP3PBOX' elif water == 'TIP4P': solvent_model = 'TIP4PBOX' if verbose: print('Working directory:', working_directory) tleap = TLeap() tleap.load_parameters(*forcefield) tleap.load_unit('MolecularSystem', pdbfile_in) tleap.check_unit('MolecularSystem') tleap.get_total_charge('MolecularSystem') tleap.solvate('MolecularSystem', solvent_model, clearance, box_geometry=box_geometry) if num_anions != 0: if num_anions == 'neutralize': num_anions = 0 tleap.add_ions('MolecularSystem', anion, num_ions=num_anions, replace_solvent=True) if num_cations != 0: if num_cations == 'neutralize': num_cations = 0 tleap.add_ions('MolecularSystem', cation, num_ions=num_cations, replace_solvent=True) tleap.save_unit('MolecularSystem', tmp_prmtop) errors = tleap.run(working_directory=working_directory, verbose=verbose) del (tleap) if logfile: copyfile(tmp_logfile, current_directory + '/build_peptide.log') tmp_item = convert([tmp_prmtop, tmp_inpcrd], to_form=to_form) if with_NME_C: _set(tmp_item, target='atom', selection='group_name=="NME" and atom_name=="CH3"', atom_name='C') rmtree(working_directory) return tmp_item else: raise NotImplementedError
def add_hydrogens(molecular_system, pH=7.4, forcefield='AMBER99SB-ILDN', engine='OpenMM', verbose=False): """add_missing_hydrogens(item, pH=7.4, forcefield='AMBER99SB-ILDN', engine='OpenMM', verbose=False) The missing hydrogens of a molecular model are added. This method does not remove any hydrogen already present. Regarding the protonation states of the aminoacids the documentation corresponding to the chosen engine should be checked for further details. - OpenMM: The protonation state is determined according the frequency of the variant at the specified pH, and the participation of Cysteines in disulfide bonds or Histidines in hydrogen bonds. This engine needs the specification of a forcefield. See the `OpenMM User Manual <http://docs.openmm.org/7.0.0/userguide/application.html#adding-hydrogens>`_ or the `OpenMM Api Guide <http://docs.openmm.org/development/api-python/generated/simtk.openmm.app.modeller.Modeller.html#simtk.openmm.app.modeller.Modeller.addHydrogens>`_. - PDBFixer: The protonation state is determined according to the frequency of the variant at the specified pH. See the `PDBFixer Manual <http://htmlpreview.github.io/?https://raw.github.com/pandegroup/pdbfixer/master/Manual.html>`_. Parameters ---------- item: Molecular model in accepted form. Molecular model in any of the accepted forms by MolSysMT. pH: float, default: 7.4 The pH based on which to determine the aminoacids protonation states. forcefield: str, default: 'AMBER99SB-ILDN' Name of the forcefield to be used by OpenMM ([check the list of names accepted here]()) engine: str ('OpenMM' or 'PDBFixer'), default: 'OpenMM' Name of the engine used to add the missing hydrogens. The following options are available: - 'OpenMM': The method openmm.app.modeller.Modeller.addHydrogens is included in the workflow. See the `OpenMM User Manual <http://docs.openmm.org/7.0.0/userguide/application.html#adding-hydrogens>`_ or the `OpenMM Api Guide <http://docs.openmm.org/development/api-python/generated/simtk.openmm.app.modeller.Modeller.html#simtk.openmm.app.modeller.Modeller.addHydrogens>`_. - 'PDBFixer': The method pdbfixer.PDBFixer.addMissingHydrogens() is included in the workflow. See the `PDBFixer Manual <http://htmlpreview.github.io/?https://raw.github.com/pandegroup/pdbfixer/master/Manual.html>`_. verbose: bool, default: False The method prints out useful information if verbose=`True`. Returns ------- item : Molecular model in the same form as input `item`. A new molecular model with the missing hydrogens added is returned. The form will be the same as the input model. Examples -------- See Also -------- Notes ----- """ from molsysmt.basic import convert, get_form form = get_form(molecular_system) engine = digest_engine(engine) if engine == "OpenMM": tmp_item = convert(molecular_system, to_form="openmm.Modeller") log_residues_changed = tmp_item.addHydrogens(pH=pH) if verbose: print('Missing hydrogens added.') ii = 0 for residue in item.topology.residues(): if log_residues_changed[ii] is not None: print('{}-{} to {}-{}'.format(residue.name, residue.index, log_residues_changed[ii], residue.index)) ii += 1 elif engine == 'PDBFixer': tmp_item = convert(molecular_system, to_form="pdbfixer.PDBFixer") tmp_item.addMissingHydrogens(pH=pH) if verbose: print('Missing hydrogens added (PDBFixer gives no details).') else: raise NotImplementedError tmp_item = convert(tmp_item, to_form=form) return tmp_item
def energy_minimization (molecular_system, method='L-BFGS', selection='all', syntaxis='MolSysMT', engine='OpenMM', to_form=None, verbose=True): """remove(item, selection=None, syntaxis='mdtraj') A new structure is returned with the molecular model relaxed to the nearest potential energy local minimum. Parameters ---------- item : molecular model Molecular model in any form to be operated by the method. method : str (default "L-BFGS") Energy minimization method. method : str (default "AMBER99SB-ILDN") Forcefield to model the inter-atomic interactions. selection : str, int, list, tuple or numpy array (default None) Region to be minimized defined as a selection sentence or atoms indices list. By default None means all atoms and there by the whole molecular model is minized. syntaxis : str (default "mdtraj") Name of the selection syntaxis used: "mdtraj" or "amber". engine : str (default "openmm") Returns ------- item : molecular model The result is a new molecular model with coordinates or positions relaxed to the nearest local minimum of the potential energy. Examples -------- Remove chains 0 and 1 from the pdb: 1B3T. >>> import molsysmt as m3t >>> system = m3t.load('pdb:1B3T') Check the number of chains >>> minimized_system = m3t.minimze(system) """ from molsysmt._private.engines import digest_engine from molsysmt._private._digestion import digest_molecular_system from molsysmt.basic import convert, get_form engine=digest_engine(engine) in_form = get_form(molecular_system) if to_form is None: to_form = in_form if engine=='OpenMM': molecular_system = digest_molecular_system(molecular_system) if molecular_system.simulation_item is None: from molsysmt.native.simulation import simulation_to_potential_energy_minimization molecular_system = molecular_system.combine_with_items(simulation_to_potential_energy_minimization) simulation = convert(molecular_system, selection=selection, syntaxis=syntaxis, to_form='openmm.Simulation') if verbose: state_pre_min = simulation.context.getState(getEnergy=True) energy_pre_min = state_pre_min.getPotentialEnergy() energy_pre_min = puw.standardize(energy_pre_min) print("Potential Energy before minimization: {}".format(energy_pre_min)) if method=='L-BFGS': simulation.minimizeEnergy() if verbose: state_post_min = simulation.context.getState(getEnergy=True) energy_post_min = state_post_min.getPotentialEnergy() energy_post_min = puw.standardize(energy_post_min) print("Potential Energy after minimization: {}".format(energy_post_min)) tmp_item = convert(simulation, to_form=to_form) return tmp_item else: raise NotImplementedError
def model_loop (item, target_sequence=None, finesse=0, engine='modeller', verbose=False): if engine=='modeller': from molsysmt.topology import get_sequence_alignment as get_sequence_alignment import tempfile as _tempfile from os import remove from os import curdir from os import listdir from glob import glob import modeller as modeller import modeller.automodel as automodel from molsysmt.basic import get_form, get, set form_in = get_form(item) tmp_box = get(item, box=True) seq_original = convert(item, to_form='string:aminoacids1') seq_aligned, _, _, _, _ = get_sequence_alignment('aminoacids1:'+seq_original, 'aminoacids1:'+target_sequence)[0] tmp_pdbfilename = tempfile.NamedTemporaryFile(suffix=".pdb").name tmp_name = tmp_pdbfilename.split('/')[-1].split('.')[0] tmp_seqfilename = '/tmp/'+tmp_name+'.seq' tmp_alifilename = '/tmp/'+tmp_name+'.ali' _ = convert(item, to_form=tmp_pdbfilename) if verbose: modeller.log.verbose() else: modeller.log.none() e = modeller.environ() e.io.atom_files_directory = ['.', '/tmp'] m = modeller.model(e, file=tmp_pdbfilename) aln = modeller.alignment(e) aln.append_model(m, align_codes=tmp_name) aln.write(file=tmp_seqfilename) alifile = open(tmp_alifilename,'w') seqfile = open(tmp_seqfilename,'r') lines_seqfile = seqfile.readlines() alifile.write(lines_seqfile[1]) alifile.write(lines_seqfile[2]) alifile.write(seq_aligned+'*\n') alifile.write('>P1;'+tmp_name+'_fill\n') alifile.write('sequence:::::::::\n') alifile.write(target_sequence+'*\n') alifile.close() seqfile.close() del(lines_seqfile) a = automodel.loopmodel(e, alnfile = tmp_alifilename, knowns = tmp_name, sequence = tmp_name+'_fill') a.write_intermediates = False a.starting_model = 1 a.ending_model = 1 a.loop.starting_model = 1 a.loop.ending_model = 12 if finesse==0: a.loop.md_level = automodel.refine.very_fast elif finesse==1: a.loop.md_level = automodel.refine.fast elif finesse==2: a.loop.md_level = automodel.refine.slow elif finesse==3: a.loop.md_level = automodel.refine.very_slow elif finesse==4: a.loop.md_level = automodel.refine.slow_large a.make() remove(tmp_pdbfilename) remove(tmp_seqfilename) remove(tmp_alifilename) files_produced = [ ff for ff in _listdir(_curdir) if ff.startswith(tmp_name) ] candidate_value = float("inf") candidate_pdb_file = None for pdb_loopmodel in [ ff for ff in files_produced if ff.startswith(tmp_name+'_fill.BL')]: pdb_file=open(pdb_loopmodel,'r') _ = pdb_file.readline() objective_function_value = float(pdb_file.readline().split(' ')[-1]) if objective_function_value < candidate_value: candidate_value = objective_function_value candidate_pdb_file = pdb_loopmodel pdb_file.close() print("Best loop model with modeller's objective function:",candidate_value) tmp_item = convert(candidate_pdb_file, to_form=form_in) for file_produced in files_produced: remove(file_produced) set(tmp_item, box=tmp_box) del(tmp_box) return tmp_item elif engine=='pyrosetta': pass elif engine=='ensembler': pass