Source code for schrodinger.ui.sequencealignment.prime

"""
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