"""
Prime homology modeling functions.
Copyright Schrodinger, LLC. All rights reserved.
"""
# Contributors: Piotr Rotkiewicz
import os
import tempfile
from . import constants
from . import dialogs
from . import fileio
from . import jobs
from . import maestro as maestro_helpers
from .align import align
from .prime_gui import getPrimeLigandsForEntryID
try:
from schrodinger.maestro import maestro
except:
maestro = None
try:
from schrodinger.job import jobcontrol
except ImportError:
jobcontrol = None
try:
from schrodinger.infra import mm
except ImportError:
mm = None
try:
import _pymmlibs
except ImportError:
_pymmlibs = None
[docs]def prime_get_default_settings():
"""
Returns a dictionary with default Prime settings.
"""
parameters = {}
parameters["preview_model"] = False
parameters["keep_rotamers"] = True
parameters["optimize_side_chains"] = True
parameters["minimize_residues"] = True
parameters["build_insertions"] = True
parameters["max_insertion_length"] = 20
parameters["build_transitions"] = True
parameters["build_deletions"] = True
parameters["knowledge_based"] = False
parameters["num_output_struct"] = 10
parameters["template_residue_numbers"] = False
return parameters
[docs]def prime_build_consensus_model(sequence_group,
progress_dialog=None,
job_settings="",
viewer=None):
"""
Builds a Prime consensus homology model.
"""
if not sequence_group or not sequence_group.reference:
return False
# Get Schrodinger path.
schrodinger_path = jobs.getSchrodingerPath()
if schrodinger_path is None:
return False
query = sequence_group.reference
template_list = []
for seq in sequence_group.sequences:
if seq.type == constants.SEQ_AMINO_ACIDS:
ssa = None
for child in seq.children:
if child.type == constants.SEQ_SECONDARY:
ssa = child
break
if seq != query and seq.has_structure and seq.selected:
if seq.from_maestro:
# Attempt to extract structural data from a Maestro
# structure.
if not maestro_helpers.maestroExtractStructureData(seq):
continue
template_list.append((seq, ssa))
if len(template_list) < 2:
return False
# Store current directory.
cwd = os.getcwd()
tmpdir = None
if job_settings and job_settings["temporary_dir"]:
# Create a temporary directory where the job will run and change
# current directory to temporary.
try:
tmpdir = tempfile.mkdtemp()
os.chdir(tmpdir)
except:
dialogs.error_dialog(
"Cannot Run Job",
"Cannot create a temporary directory for Prime job.")
return False
# This is a return status.
status = True
input_file_name = "consensus_model.inp"
alignment_file_name = "consensus_model.align"
try:
alignment_file = open(alignment_file_name, "w")
except:
status = False
if status:
try:
name = ">" + \
query.short_name[:4].upper() + "_" + query.chain_id.upper()
alignment_file.write(">" + query.short_name + "\n")
alignment_file.write(
query.text().replace('-', '~').replace('X', '~') + "\n")
for seq, ssa in template_list:
chain_id = seq.chain_id.upper()
if chain_id <= ' ':
chain_id = 'A'
tmpl_name = seq.short_name[:4].upper() + "_" + chain_id
name = ">" + tmpl_name + " "
alignment_file.write(name + "Chain,\n")
alignment_file.write(
seq.text().replace('-', '~').replace('X', '~') + "\n")
alignment_file.write(name + "ssa,\n")
alignment_file.write(ssa.text().replace(' ', '~') + "\n")
structure_file = open(tmpl_name + ".pdb", "w")
for res in seq.residues:
if not res.is_gap:
res_lines = []
# In case chain_id = ' ' replace it with 'A'
for line in res.structure:
if len(line) > 21 and line[21] != chain_id[0]:
new_line = list(line)
new_line[21] = chain_id[0]
line = "".join(new_line)
res_lines.append(line)
structure_file.writelines(res_lines)
structure_file.write("TER\nEND\n")
structure_file.close()
alignment_file.close()
except:
status = False
if status:
try:
input_file = open(input_file_name, "w")
except:
status = False
if status:
try:
input_file.write("ALIGN_FILE consensus_model.align\n")
input_file.close()
except:
status = False
if status:
# Run Prime consensus_homology program.
job_command = schrodinger_path + "consensus_homology"
current_entries = maestro_helpers.maestroGetListOfEntryIDs()
# Launch the job and wait until it incorporates. Pass all input
# file names to Prime as command line parameters.
job_result = jobs.run_job_via_jobcontrol(
[job_command] + ["consensus_model"],
"consensus_model.log",
dialog_title="Building Consensus Homology Model",
progress_dialog=progress_dialog,
settings=job_settings)
# Check the job return status.
if job_result == jobs.JOB_STATUS_MISSING:
# Missing or invalid job control module.
dialogs.error_dialog("Job Failed",
"Could not run homology modeling job.")
status = False
elif job_result == jobs.JOB_STATUS_FAILED:
# Job could not be launched (probably missing backend).
dialogs.error_dialog(
"Job Failed", "Could not build homology model.\n"
"Do you have Prime installed?")
status = False
elif job_result == jobs.JOB_STATUS_KILLED:
# Job was interrupted.
dialogs.error_dialog("Job Interrupted",
"Homology modeling job was interrupted.")
status = False
if status:
if maestro:
# Incorporate the model into Maestro.
model_file_name = "consensus_model-out.maegz"
if os.path.isfile(model_file_name):
try:
# Get Maestro entry of the built model.
entry_id = maestro_helpers.getEntryByJobName(
"consensus_model")
if not entry_id:
# Preserve wsreplace setting.
wsreplace = maestro.get_command_option(
"entryimport", "wsreplace")
# Incorporate model, but leave other structures
# included in workspace.
maestro.command(
"entryimport wsreplace=true format=maestro \"" +
model_file_name + "\"")
# Restore original value for wsreplace.
maestro.command("entryimport" + " wsreplace=" +
wsreplace)
if entry_id:
# Create a model name.
model_name = "Model of " + query.short_name
model_name = model_name.rstrip()
# Rename the entry and set a new title.
maestro.command("entrysetprop "
"property=s_m_title value=\"" +
model_name + "\" entry \"" +
str(entry_id) + "\"")
maestro.command("entrysetprop "
"property=s_m_entry_name value=\"" +
model_name + "\" entry \"" +
str(entry_id) + "\"")
# Propagate current MSV colors to the structure.
for group in [sequence_group]:
group.unmarkTemplateRegions()
reference = group.reference
if not reference:
continue
model_name = "Model of " + reference.short_name
model_name = model_name.rstrip()
# Incorporate the model entry into a current group.
maestro_helpers.maestroIncorporateEntries(
group, what="all", ignore=current_entries)
# Get all sequences associated with this entry.
sequences = group.getMaestroSequencesForEntryId(
entry_id)
for seq in sequences:
seq.name = model_name
seq.short_name = model_name
# Propagate gaps from query sequence to the model
# sequence.
new_residues = reference.propagateGaps(
seq, parent_sequence=seq)
if not new_residues:
seq.visible = False
continue
seq.residues = new_residues
seq.propagateGapsToChildren()
# Align the model sequence with the reference
align(reference, seq)
# Fit to workspace.
maestro.command("fit")
if viewer:
maestro_helpers.synchronizePropertiesWithMaestro(
viewer, colors=True)
viewer.setColorMode(constants.COLOR_MAESTRO)
viewer.contents_changed = True
viewer.updateView()
except:
pass
# Change current directory back to the original directory and remove
# temporary files and directory.
try:
os.chdir(cwd)
if job_settings:
keep_files = job_settings["keep_files"]
else:
keep_files = False
if tmpdir and not keep_files:
jobs.removeTmpJobDir(tmpdir, keep=[model_file_name])
except:
dialogs.error_dialog("Cannot Remove Temporary Files",
"Cannot remove temporary Prime job files."),
status = False
return status
[docs]def prime_run(
settings=None,
mode=constants.PRIME_MODE_SINGLE,
group_list=[], # noqa: M511
valid_template_list=[], # noqa: M511
progress_dialog=None,
viewer=None,
job_settings=""):
"""
This function is used to create homology models. It generates input files
for Prime, runs the Prime job, and incorporates built models into Maestro.
This function is called when the user clicks on "Build Model" button
in Build Homology Model panel.
There are several possible homology modeling scenarios that need to be
handled by this function:
1) modeling using a single query and a single template,
2) modeling using a single query and multiple templates with selected
template regions: all templates are used to build a single composite
model,
3) modeling using a single query and multiple templates in order to build
a homo-multimer: each template is used to create an individual model,
but query sequence is identical for each of the models,
4) modeling using multiple queries and multiple templates: each query /
template pair is treated independently in order to build a hetero-multimer.
In addition, there are possible mixed scenarios, e.g. building
a hetero-multimer consisting of homo-multimers.
:note: We are using "query" and "sequence group" as synonyms. A sequence
group can include a single query sequence and several template sequences.
The "reference" and "query sequence" are also used as synonyms.
:type sequence_group: `SequenceGroup`
:param sequence_group: A default (current) sequence group.
:rtype: boolean
:return: True on successful job completion, False if the job could not
be completed.
"""
# MSV doesn't allow to run two jobs simultaneously. Quit if another
# job is already running.
if jobs.checkJobIsRunning():
return False
# If there are no queries selected in Prime settings panel
# use current sequence group for building the model.
if not group_list:
return False
sequence_group = group_list[0]
# Get Schrodinger path.
schrodinger_path = jobs.getSchrodingerPath()
if schrodinger_path is None:
return False
if mode == constants.PRIME_MODE_CONSENSUS:
return prime_build_consensus_model(group_list[0],
progress_dialog=progress_dialog,
job_settings=job_settings)
# Note: in current implementation a job is run in a temporary directory
# that is removed after the job is completed. This behavior may be changed
# in future versions.
# Store current directory.
cwd = os.getcwd()
tmpdir = None
if job_settings and job_settings["temporary_dir"]:
# Create a temporary directory where the job will run and change
# current directory to temporary.
try:
tmpdir = tempfile.mkdtemp()
os.chdir(tmpdir)
except:
dialogs.error_dialog(
"Cannot Run Job",
"Cannot create a temporary directory for Prime job.")
return False
# This is a return status.
status = True
# Extract Prime parameters from a parameter list (the parameters are
# stored in Prime settings panel).
quick_build_mode = settings["preview_model"]
keep_rotamers = settings["keep_rotamers"]
side_opt = settings["optimize_side_chains"]
minimize = settings["minimize_residues"]
build_insertions = settings["build_insertions"]
max_insertion_size = settings["max_insertion_length"]
build_transitions = settings["build_transitions"]
build_deletions = settings["build_deletions"]
knowledge_based = settings["knowledge_based"]
num_output_struct = settings["num_output_struct"]
template_residue_numbers = settings["template_residue_numbers"]
if quick_build_mode:
side_opt = False
minimize = False
build_insertions = False
build_transitions = False
build_deletions = False
max_insertion_size = 0
if not build_insertions:
max_insertion_size = 0
# List of input file name prefixes.
input_file_list = []
n_templates = len(valid_template_list)
if mode == constants.PRIME_MODE_COMPOSITE and n_templates > 1:
answer = dialogs.question_dialog(
"Structure Alignment",
"Composite/chimera models require that the templates "
"be structurally aligned prior to Model Building.\n\n"
"Do you want to structurally align the templates?")
if answer == "yes":
maestro.command("entrywsexclude all")
maestro.command("showpanel structalign")
for template in valid_template_list:
maestro.command("entrywsinclude entry " +
str(template.maestro_entry_id))
maestro.command("structalignstart all")
maestro.command("hidepanel structalign")
elif answer == "cancel":
return False
all_template_names = ""
global_template_index = 0
# Write input files for each query sequence.
# Iterate over all sequence groups.
for query_index, group in enumerate(group_list):
if not status:
# Break if something went wrong.
break
# Check if the group includes a valid reference (query) sequence.
reference = group.reference
if reference is None:
# No reference, so ignore this group.
continue
# print "DEBUG query", query_index, reference.name
# Make sure all sequences have identical lengths by adding gaps
# to the end of the sequence.
group.removeTerminalGaps()
group.padAlignment()
# Build a list of templates. Valid template sequences need to have
# structural information associated with them, and cannot be
# a query (reference) sequence.
template_list = []
for seq in group.sequences:
if seq.type == constants.SEQ_AMINO_ACIDS:
if seq.isValidTemplate(reference=reference):
if seq.from_maestro:
# Attempt to extract structural data from a Maestro
# structure.
if not maestro_helpers.maestroExtractStructureData(seq):
continue
template_list.append(seq)
# print "DEBUG template", seq.name
if len(template_list) == 0:
# No valid templates, so just ignore this query.
continue
# Make a list of selected sequences.
selected_template_list = [seq for seq in template_list if seq.selected]
# Make a list of templates with marked regions.
marked_template_list = []
if len(selected_template_list) == 0:
# If no sequences are selected we are either building
# a composite model using marked template regions, or just
# a single-template model.
# If residues are marked in a template sequence, append this
# sequence to marked templates list.
for template in template_list:
for res in template.residues:
# Is the residue marked?
if res.model:
marked_template_list.append(template)
break
if len(marked_template_list) > 0:
# We have at least single template with marked regions.
if len(marked_template_list) > 9:
# Prime input format can only support 9 or less templates
# for building the composite model, so we need to trim
# the list of templates if there are too many. This is
# very unlikely to happen.
dialogs.warning_dialog(
"Building Homology Model"
"Only 9 first templates will be used "
"for building the composite model.")
# Trim the marked template list.
marked_template_list = marked_template_list[:9]
# Use the marked template list for modeling.
template_list = marked_template_list
else:
# We don't have any selected sequences nor marked residues.
# Use a first available template for modeling.
template_list = template_list[:1]
else:
# We have selected templates - assume we are going to build
# a homo-multimer (or just a single chain model based on a
# single selected template).
template_list = selected_template_list
# Iterate over the templates.
for template_index, template in enumerate(template_list):
# print "DEBUG using template", template_index, template.name
if template_index == 0 or len(selected_template_list) > 1:
# Initialize Prime input file only if this is first template
# or if we are building a homo-multimer (number of selected
# template sequences > 1).
# Make a list of lines to be written to Prime input file.
input_file_lines = [
"JOB_TYPE MODEL\n", "QUERY_OFFSET 0\n"
]
chain_id = template.chain_id
global_template_index += 1
template_name = "template%d" % (global_template_index)
if chain_id != ' ':
template_name += '_' + chain_id
# Write template info.
input_file_lines.append("TEMPLATE_NAME %s\n" % template_name)
input_file_lines.append("%s_NUMBER %d\n" %
(template_name, template_index + 1))
input_file_lines.append("%s_STRUCT_FILE %s.ent\n" %
(template_name, template_name))
input_file_lines.append("%s_ALIGN_FILE %s.aln\n" %
(template_name, template_name))
# Get list of all ligands associated with the template entry.
# all_ligand_names include the entry ligand names in a
# form of entry_name + ' ' + residue_name + ' ' +
# chain_name + ':' + residue_number
all_ligand_names, all_ligand_entries = maestro_helpers.\
getMaestroLigandList(template_list=[template])
# Write a template PDB file.
structure_file_name = template_name + ".ent"
structure_file = open(structure_file_name, "w")
# The Residue.structure list keeps structure information
# in PDB format, so we just need to write out these lines.
# Also, create template sequence and make sure query
# sequence does match it.
query_seq_txt = ''
original_query_seq_txt = group.reference.text()
template_seq_txt = ''
for index, res in enumerate(template.residues):
test_resname = res.getSignature()
if any(test_resname in name for name in all_ligand_names):
# Skip this alignment column because the template
# residue is a ligand, i.e. test_resname partially
# matches one of items in all_ligand_names.
continue
if res.structure:
structure_file.writelines(res.structure)
template_seq_txt += res.code
else:
# For structureless residues write gap instead
template_seq_txt += '.'
query_seq_txt += original_query_seq_txt[index]
# Create query sequence line. Replace gaps with dots.
query_seq_txt = 'ProbeAA: ' + \
query_seq_txt.replace('~', '.').replace('-', '.') + '\n'
# Create template sequence line. Replace gaps with dots.
template_seq_txt = 'Fold AA: ' + \
template_seq_txt.replace('~', '.').replace('-', '.') + '\n'
structure_file.writelines(["TER\n"])
ligand_crosslinks = ""
lig_index = 0
if hasattr(group, 'ligand_list') and group.ligand_list:
ligands = getPrimeLigandsForEntryID(template.maestro_entry_id)
# group.ligand_list stores the ligands selected in the GUI
# 'ligands' is the full list of ligand ct that belong to
# the current entry
ligand_names, ligand_constraints = list(zip(*group.ligand_list))
for ligand in ligands:
if len(ligand.atom) == 0:
continue
ligname = ligand.atom[1].pdbres[:3] + ' ' + \
ligand.atom[1].chain + ':' + \
str(ligand.atom[1].resnum)
if ligname not in list(ligand_names):
continue
input_file_lines.append(
"%s_HETERO_%d %s %c:%d\n" %
(template_name, lig_index, ligand.atom[1].pdbres[:3],
ligand.atom[1].chain, ligand.atom[1].resnum))
ligand_lines = []
for atom in ligand.atom:
pdbline = "HETATM%5d %-4s %4s%c%4d%c %8.3f%8.3f%8.3f\n" % \
(atom.index, atom.pdbname, atom.pdbres, atom.chain,
atom.resnum, atom.inscode, atom.x, atom.y, atom.z)
ligand_lines.append(pdbline)
ligand_lines.append("TER\n")
structure_file.writelines(ligand_lines)
# Extract the ligand constraints if they are defined
constraint_seq = ligand_constraints[ligand_names.index(
ligname)]
for index, res in enumerate(
constraint_seq.gaplessResidues()):
if hasattr(res, 'query_constraint'):
ligand_crosslinks += " A:" + str(index + 1) + \
" Z:" + str(500 + lig_index)
lig_index += 1
structure_file.writelines(["END\n"])
structure_file.close()
# Write aligment file for this template.
alignment_file_name = template_name + ".aln"
try:
alignment_file = open(alignment_file_name, "w")
alignment_file.writelines(query_seq_txt)
alignment_file.writelines(template_seq_txt)
alignment_file.close()
except IOError:
dialogs.error_dialog("Cannot Build Homology Model",
"Error writing alignment file.")
status = False
break
if template_index == len(template_list) - 1 or \
len(selected_template_list) > 1:
# Write Prime input file only if we iterated over all templates
# or if we are building a homo-multimer (number of selected
# template sequences > 1).
# Write out Prime settings.
if tmpdir:
input_file_lines.append("DIR_NAME %s\n" % tmpdir)
else:
input_file_lines.append("DIR_NAME %s\n" % cwd)
input_file_lines.append("TAILS 0\n")
input_file_lines.append("SIDE_OPT\t" + str(side_opt).lower() +
"\n")
input_file_lines.append("MINIMIZE\t" + str(minimize).lower() +
"\n")
input_file_lines.append("TEMPLATE_RESIDUE_NUMBERS\t" +
str(template_residue_numbers).lower() +
"\n")
input_file_lines.append("BUILD_INSERTIONS\t" +
str(build_insertions).lower() + "\n")
input_file_lines.append("MAX_INSERTION_SIZE\t" +
str(max_insertion_size).lower() + "\n")
input_file_lines.append("BUILD_TRANSITIONS\t" +
str(build_transitions).lower() + "\n")
input_file_lines.append("BUILD_DELETIONS\t" +
str(build_deletions).lower() + "\n")
input_file_lines.append("KEEP_ROTAMERS\t" +
str(keep_rotamers).lower() + "\n")
if knowledge_based:
input_file_lines.append("KNOWLEDGE_BASED\ttrue\n")
input_file_lines.append("NUM_OUTPUT_STRUCT\t" +
str(num_output_struct) + "\n")
# Retrieve crosslink information from the sequence group.
crosslinks = []
for seq in group.sequences:
if seq.type == constants.SEQ_CONSTRAINTS:
for constraint in seq.constraint_list:
start, end, seq, prime = constraint
# Use this constraint only if is defined for Prime
# model building.
if prime and seq == reference:
# Get actual residues.
cstart_res = reference.getResidue(start,
ungapped=True)
cend_res = reference.getResidue(end,
ungapped=True)
# Write residue numbers.
crosslinks.append(
(cstart_res.num, cend_res.num))
# Write a CROSSLINK line if the crosslinks are present
# and the modeling method is Energy-based
if (len(crosslinks) > 0 or ligand_crosslinks) \
and not knowledge_based:
line = "CROSSLINK "
for start, end in crosslinks:
line += " A:" + str(start) + " A:" + str(end)
line += ligand_crosslinks
line += "\n"
input_file_lines.append(line)
# Build a composite string only if there are several templates
# with marked regions.
if len(marked_template_list) > 1:
composite = ""
for index, res in enumerate(group.reference.residues):
if res.is_gap:
# The composite string covers only template
# regions, not gaps.
continue
# We initially put "1" at this position - it is going
# to be ignored if there is no template coverage here.
pos = "1"
for tmp_index, template in enumerate(
marked_template_list):
if index < len(template.residues):
if template.residues[index].model:
pos = str(tmp_index + 1)
break
composite += pos
# Write composite array string.
input_file_lines.append("COMPOSITE_ARRAY " + composite)
# Create input file prefix.
inp_file_prefix = "prime_bldstruct_%d_%d" % (query_index,
template_index)
# Create a unique file based on the input file prefix
try:
with tempfile.NamedTemporaryFile(prefix=inp_file_prefix,
mode="w",
delete=False) as inp_file:
inp_file_name = inp_file.name
except IOError:
dialogs.error_dialog("Cannot Build Homology Model",
"Error creating an input file.")
status = False
break
# Use new file name as a prefix and job name
inp_file_prefix = os.path.basename(inp_file_name)
# Create input file name.
inp_file_name = inp_file_prefix + ".inp"
# Write input file.
try:
inp_file = open(inp_file_name, 'w')
inp_file.writelines(input_file_lines)
inp_file.close()
except Exception:
dialogs.error_dialog("Cannot Build Homology Model",
"Error writing input file.")
status = False
break
# Append this file name prefix to the list.
input_file_list.append(inp_file_prefix)
for template in template_list:
all_template_names += " " + \
template.short_name + "_" + template.chain_id
if status:
# We cannot continue if there were not input files written.
if len(input_file_list) == 0:
dialogs.error_dialog("Cannot Build Homology Model",
"No valid template structures were found.")
status = False
if status:
if maestro:
current_entries = maestro_helpers.maestroGetListOfEntryIDs()
all_references = ""
# Generate a description string.
if len(group_list) > 1:
description = "Building hetero-multimer model of "
for group in group_list:
all_references += group.reference.short_name + "_" + \
group.reference.chain_id + " "
else:
if len(selected_template_list) > 1:
description = "Building homo-multimer model of "
all_references = sequence_group.reference.short_name + \
"_" + sequence_group.reference.chain_id
elif len(marked_template_list) > 1:
description = "Building composite model of "
all_references = sequence_group.reference.short_name + \
"_" + sequence_group.reference.chain_id
else:
description = "Building single chain model of "
all_references = sequence_group.reference.short_name + \
"_" + sequence_group.reference.chain_id
description += all_references + "\nbased on " + \
all_template_names + "\n\n"
# Run Prime bldstruct program.
job_command = schrodinger_path + "prime"
# First input file prefix will be used for input, log
# and model file names.
inp_file_prefix = input_file_list[0]
# Launch the job and wait until it incorporates. Pass all input
# file names to Prime as command line parameters.
job_result = jobs.run_job_via_jobcontrol(
[job_command] + input_file_list,
inp_file_prefix + ".log",
dialog_title="Building Homology Model",
initial_text=description,
progress_dialog=progress_dialog,
no_jobid=quick_build_mode,
settings=job_settings)
# print "DEBUG PSP job result = ", job_result
# Check the job return status.
if job_result == jobs.JOB_STATUS_MISSING:
# Missing or invalid job control module.
dialogs.error_dialog("Job Failed",
"Could not run homology modeling job.")
status = False
elif job_result == jobs.JOB_STATUS_FAILED:
# Job could not be launched (probably missing backend)
dialogs.error_dialog(
"Job Failed", "Could not build homology model.\n"
"Do you have Prime installed?")
status = False
elif job_result == jobs.JOB_STATUS_KILLED:
# Job was interrupted.
dialogs.error_dialog("Job Interrupted",
"Homology modeling job was interrupted.")
status = False
if status:
# Incorporate built model.
model_incorporated = False
if maestro:
# Incorporate the model into Maestro.
model_file_name = inp_file_prefix + "-out.mae"
if os.path.isfile(model_file_name):
try:
# Get Maestro entry of the built model.
entry_id = maestro_helpers.getEntryByJobName(
inp_file_prefix)
if not entry_id:
# Preserve wsreplace setting.
wsreplace = maestro.get_command_option(
"entryimport", "wsreplace")
# Incorporate model, but leave other structures included
# in workspace.
maestro.command(
"entryimport wsreplace=true format=maestro \"" +
model_file_name + "\"")
# Restore original value for wsreplace.
maestro.command("entryimport wsreplace=" + wsreplace)
# Get entry ID of the incorporated model
entry_id = maestro_helpers.getEntryByName(
inp_file_prefix + "-out.1")
if entry_id:
model_incorporated = True
# Create a model name.
model_name = "Model of " + all_references
if all_template_names:
model_name += " based on" + all_template_names
model_name = model_name.rstrip()
# Rename the entry and set a new title.
maestro.command("entrysetprop "
"property=s_m_title value=\"" + \
model_name + "\" entry \"" + \
str(entry_id) + "\"")
maestro.command("entrysetprop "
"property=s_m_entry_name value=\"" + \
model_name + "\" entry \"" + \
str(entry_id) + "\"")
# Propagate current MSV colors to the structure.
for group in group_list:
group.unmarkTemplateRegions()
reference = group.reference
if not reference:
continue
model_name = "Model of " + reference.short_name
if all_template_names:
model_name += " based on" + all_template_names
model_name = model_name.rstrip()
# Incorporate the model entry into a current group.
maestro_helpers.maestroIncorporateEntries(
group, what="all", ignore=current_entries)
# Get all sequences associated with this entry.
sequences = group.getMaestroSequencesForEntryId(
entry_id)
for seq in sequences:
if not seq.residues:
continue
seq.name = model_name
seq.short_name = model_name
# Propagate gaps from query sequence to the model
# sequence.
new_residues = reference.propagateGaps(
seq, parent_sequence=seq)
if new_residues:
seq.residues = new_residues
seq.propagateGapsToChildren()
# Fit to workspace.
maestro.command("fit")
if viewer:
maestro_helpers.synchronizePropertiesWithMaestro(
viewer, colors=True)
viewer.setColorMode(constants.COLOR_MAESTRO)
viewer.contents_changed = True
viewer.updateView()
except:
pass
else:
# MSV is running outside of Maestro.
# Incorporate the final model PDB file into MSV.
model_file_name = inp_file_prefix + "-out.pdb"
if os.path.isfile(model_file_name):
# Import the PDB file into a temporary group.
tmp_group = sequence_group.SequenceGroup()
if fileio.load_PDB_file(tmp_group, model_file_name):
reference = sequence_group.reference
if len(tmp_group.sequences) > 0:
# Align all model sequences with the reference
# sequence.
for seq in tmp_group.sequences:
# Rename the sequence.
seq.short_name = "Model_of_" + reference.short_name
seq.name = seq.short_name
# Propagate gaps from query sequence to the model
# sequence.
new_residues = reference.propagateGaps(
seq, parent_sequence=seq)
if new_residues:
seq.residues = new_residues
seq.propagateGapsToChildren()
# Color sequences using a current color mode.
if viewer:
sequence_group.colorSequences(
sequence_group.color_mode)
# Append temporary group to the current sequence group.
sequence_group.sequences += tmp_group.sequences
model_incorporated = True
if viewer:
viewer.contents_changed = True
viewer.updateView()
if not model_incorporated:
dialogs.error_dialog("Job Failed",
"Could not incorporate the homology model.")
# Change current directory back to the original directory and remove
# temporary files and directory.
try:
os.chdir(cwd)
if job_settings:
keep_files = job_settings["keep_files"]
else:
keep_files = False
if tmpdir and not keep_files:
jobs.removeTmpJobDir(tmpdir, keep=[model_file_name])
except:
dialogs.error_dialog("Cannot Remove Temporary Files",
"Cannot remove temporary Prime job files."),
status = False
return status