diff options
author | Mark Sims <mark@nanorex.com> | 2008-12-15 08:19:00 +0000 |
---|---|---|
committer | Mark Sims <mark@nanorex.com> | 2008-12-15 08:19:00 +0000 |
commit | 45b38837bab330154258b546ab21c32d3b3118cf (patch) | |
tree | ffcb27745b7a2f4f8abeed8996ca27e59142de40 | |
parent | d075219cd37628fed2e71a508bd2deea9dc06691 (diff) | |
download | nanoengineer-theirix-45b38837bab330154258b546ab21c32d3b3118cf.tar.gz nanoengineer-theirix-45b38837bab330154258b546ab21c32d3b3118cf.zip |
Better support for the "Compare Proteins" command. Also removed deprecated methods.
-rw-r--r-- | cad/src/commandSequencer/CommandSequencer.py | 2 | ||||
-rwxr-xr-x | cad/src/model/chunk.py | 2 | ||||
-rwxr-xr-x | cad/src/ne1_ui/MWsemantics.py | 2 | ||||
-rw-r--r-- | cad/src/protein/ProteinSequenceEditor/ProteinSequenceEditor.py | 1 | ||||
-rw-r--r-- | cad/src/protein/commands/BuildProtein/BuildProtein_PropertyManager.py | 226 | ||||
-rw-r--r-- | cad/src/protein/commands/CompareProteins/CompareProteins_PropertyManager.py | 262 | ||||
-rw-r--r-- | cad/src/protein/commands/EditRotamers/EditRotamers_PropertyManager.py | 126 | ||||
-rw-r--r-- | cad/src/protein/model/Protein.py | 24 |
8 files changed, 279 insertions, 366 deletions
diff --git a/cad/src/commandSequencer/CommandSequencer.py b/cad/src/commandSequencer/CommandSequencer.py index 3320c5c7b..a0a8086ca 100644 --- a/cad/src/commandSequencer/CommandSequencer.py +++ b/cad/src/commandSequencer/CommandSequencer.py @@ -932,7 +932,7 @@ class CommandSequencer(object): or None if no such command is found. @rtype: an active command object, or None - @param commandName: name of command we're searching for (e.g. 'BUILD_PROTEIN') + @param commandName: name of command we're searching for (e.g. 'MODEL_AND_SIMULATE_PROTEIN') @type: string @param starting_from: if provided, start the search at this command diff --git a/cad/src/model/chunk.py b/cad/src/model/chunk.py index fc89a16b7..2d7defadf 100755 --- a/cad/src/model/chunk.py +++ b/cad/src/model/chunk.py @@ -552,7 +552,7 @@ class Chunk(NodeWithAtomContents, InvalMixin, return #Urmi 20080730: edit properties for protein for context menu in gl pane - if command.commandName in ('SELECTMOLS', 'BUILD_PROTEIN'): + if command.commandName in ('SELECTMOLS', 'MODEL_AND_SIMULATE_PROTEIN'): if self.isProteinChunk(): try: protein = self.protein diff --git a/cad/src/ne1_ui/MWsemantics.py b/cad/src/ne1_ui/MWsemantics.py index f6be710c4..62f19d223 100755 --- a/cad/src/ne1_ui/MWsemantics.py +++ b/cad/src/ne1_ui/MWsemantics.py @@ -1404,7 +1404,7 @@ class MWsemantics(QMainWindow, @type otherOptionsText: str """ protein = "" - if self.commandSequencer.currentCommand.commandName == 'BUILD_PROTEIN' or \ + if self.commandSequencer.currentCommand.commandName == 'MODEL_AND_SIMULATE_PROTEIN' or \ self.commandSequencer.currentCommand.commandName == 'EDIT_ROTAMERS' or \ self.commandSequencer.currentCommand.commandName == 'EDIT_RESIDUES': protein = self.commandSequencer.currentCommand.propMgr.current_protein diff --git a/cad/src/protein/ProteinSequenceEditor/ProteinSequenceEditor.py b/cad/src/protein/ProteinSequenceEditor/ProteinSequenceEditor.py index 4a4bcbebb..55cf5fc34 100644 --- a/cad/src/protein/ProteinSequenceEditor/ProteinSequenceEditor.py +++ b/cad/src/protein/ProteinSequenceEditor/ProteinSequenceEditor.py @@ -508,7 +508,6 @@ class ProteinSequenceEditor(Ui_ProteinSequenceEditor): current_command = self.win.commandSequencer.currentCommand.commandName commandSet = ('EDIT_ROTAMERS', \ 'EDIT_RESIDUES', \ - 'BUILD_PROTEIN', \ 'MODEL_AND_SIMULATE_PROTEIN', \ 'MODEL_PROTEIN', \ 'SIMULATE_PROTEIN') diff --git a/cad/src/protein/commands/BuildProtein/BuildProtein_PropertyManager.py b/cad/src/protein/commands/BuildProtein/BuildProtein_PropertyManager.py index 545b21ea9..062bc7d54 100644 --- a/cad/src/protein/commands/BuildProtein/BuildProtein_PropertyManager.py +++ b/cad/src/protein/commands/BuildProtein/BuildProtein_PropertyManager.py @@ -21,6 +21,9 @@ To do list: - Special peptide icons for MT and PM list widget. - Deprecate set_current_protein_chunk_name() and get_current_protein_chunk_name. Use ops_select_Mixin's getSelectedProteinChunk() instead. +- Bug: Returning from Compare command unselects the two selected protein chunks. + The PM list widget shows them as selected and the compare button is enabled, + but they are not selected in the graphics area. """ import foundation.env as env from PyQt4.Qt import SIGNAL @@ -34,6 +37,7 @@ from PM.PM_Constants import PM_DONE_BUTTON from PM.PM_Constants import PM_WHATS_THIS_BUTTON from PM.PM_Constants import PM_CANCEL_BUTTON from utilities.Comparison import same_vals +from protein.model.Protein import getAllProteinChunksInPart _superclass = EditCommand_PM class BuildProtein_PropertyManager(EditCommand_PM): @@ -57,15 +61,13 @@ class BuildProtein_PropertyManager(EditCommand_PM): pmName = title iconPath = "ui/actions/Command Toolbar/BuildProtein/BuildProtein.png" - current_protein = "" # name of the single selected peptide. + current_protein = "" # name of the single selected peptide. To be deprecated soon. --Mark 2008-12-14 def __init__( self, command): """ Constructor for the Build Protein property manager. """ - self.sequenceEditor = command.win.createProteinSequenceEditorIfNeeded() - #Attributes for self._update_UI_do_updates() to keep track of changes #in these , since the last call of that method. These are used to #determine whether certain UI updates are needed. @@ -112,6 +114,11 @@ class BuildProtein_PropertyManager(EditCommand_PM): change_connect(self.editPeptidePropertiesButton, SIGNAL("clicked()"), self._editPeptide) + + change_connect(self.compareProteinsButton, + SIGNAL("clicked()"), + self._compareProteins) + return def enable_or_disable_gui_actions(self, bool_enable = False): @@ -133,7 +140,7 @@ class BuildProtein_PropertyManager(EditCommand_PM): Overrides superclass method. @see: Command_PropertyManager._update_UI_do_updates() - """ + """ newSelectionParams = self._currentSelectionParams() @@ -159,7 +166,7 @@ class BuildProtein_PropertyManager(EditCommand_PM): #parameters remained unchanged since last call. --- [CONDITION A] if selection_params_unchanged and structure_params_unchanged and command_stack_params_unchanged: #This second condition above fixes bug 2888 - print "_update_UI_do_updates(): RETURNING 1" + print "Build Protein: _update_UI_do_updates(): DO NOTHING" return self._previousStructureParams = current_struct_params @@ -188,7 +195,12 @@ class BuildProtein_PropertyManager(EditCommand_PM): self.editPeptidePropertiesButton.setEnabled(True) else: self.editPeptidePropertiesButton.setEnabled(False) - self.sequenceEditor.hide() + + # Enable/disable "Compare Proteins" button. + if len(selectedProteins) == 2: + self.compareProteinsButton.setEnabled(True) + else: + self.compareProteinsButton.setEnabled(False) return @@ -197,11 +209,11 @@ class BuildProtein_PropertyManager(EditCommand_PM): def _currentCommandStackParams(self): """ - The return value is supposed to be used by BUILD_PROTEIN command PM ONLY + The return value is supposed to be used by MODEL_AND_SIMULATE_PROTEIN command PM ONLY and NOT by any subclasses. Returns a tuple containing current command stack change indicator and - the name of the command 'BUILD_PROTEIN'. These + the name of the command 'MODEL_AND_SIMULATE_PROTEIN'. These parameters are then used to decide whether updating widgets in this property manager is needed, when self._update_UI_do_updates() is called. @@ -219,11 +231,11 @@ class BuildProtein_PropertyManager(EditCommand_PM): @see: self._update_UI_do_updates() """ commandStackCounter = self.command.assy.command_stack_change_indicator() - #Append 'BUILD_PROTEIN to the tuple to be returned. This is just to remind - #us that this method is meant for BUILD_PROTEIN command PM only. (and not + #Append 'MODEL_AND_SIMULATE_PROTEIN to the tuple to be returned. This is just to remind + #us that this method is meant for MODEL_AND_SIMULATE_PROTEIN command PM only. (and not #by any subclasses) Should we assert this? I think it will slow things #down so this comment is enough -- Ninad 2008-09-30 - return (commandStackCounter, 'BUILD_PROTEIN') + return (commandStackCounter, 'MODEL_AND_SIMULATE_PROTEIN') def _currentSelectionParams(self): """ @@ -244,7 +256,7 @@ class BuildProtein_PropertyManager(EditCommand_PM): if self.command is not None: # and self.command.hasValidStructure(): selectedPeptides = self.win.assy.getSelectedProteinChunks() - print "_currentSelectionParams(): Number of selected peptides:", len(selectedPeptides) + #print "_currentSelectionParams(): Number of selected peptides:", len(selectedPeptides) return (selectedPeptides) def _currentStructureParams(self): @@ -263,7 +275,7 @@ class BuildProtein_PropertyManager(EditCommand_PM): if self.command: # and self.command.hasValidStructure(): peptideList = [] - peptideList = self.getAllProteinChunksInPart() + peptideList = getAllProteinChunksInPart(self.win.assy) params = len(peptideList) print "_currentStructureParams(): params:", params @@ -275,22 +287,23 @@ class BuildProtein_PropertyManager(EditCommand_PM): """ #Clear tags, if any, due to the selection in the self.strandListWidget. #self.peptideListWidget.clear() - self.sequenceEditor.hide() env.history.statusbar_msg("") EditCommand_PM.close(self) return def show(self): """ - Show this PM. It also shows the Sequence Editor widget and hides - the history widget. + Show the PM. Extends superclass method. + @note: _update_UI_do_updates() gets called immediately after this and + updates PM widgets with their correct values/settings. """ env.history.statusbar_msg("") - self._showPeptideSequenceEditor() - EditCommand_PM.show(self) + # NOTE: Think about moving this msg to _update_UI_do_updates() where + # custom msgs can be created based on the current selection, etc. + # Mark 2008-12-14 msg = "Select <b>Insert Peptide</b> to create a peptide chain or "\ "select another modeling tool to modify an existing protein." self.updateMessage(msg) @@ -298,29 +311,23 @@ class BuildProtein_PropertyManager(EditCommand_PM): def _editPeptide(self): """ - Opens the sequence editor for the selected peptide. + Slot for the "Edit Properties" button. """ + #if not self.command.hasValidStructure(): + # return + peptideChunk = self.getSelectedProteinChunk() if peptideChunk: - sequence = peptideChunk.protein.get_sequence_string() - self.sequenceEditor.setSequence(sequence) - secStructure = peptideChunk.protein.get_secondary_structure_string() - self.sequenceEditor.setSecondaryStructure(secStructure) - self.sequenceEditor.setRuler(len(secStructure)) - self.sequenceEditor.show() + peptideChunk.protein.edit(self.win) return - def _showPeptideSequenceEditor(self): + def _compareProteins(self): """ - Show/hide sequence editor. It is only displayed if there is - a single peptide selected. Otherwise it is hidden. + Slot for the "Compare Proteins" button. """ - if self.getSelectedProteinChunk(): - self.sequenceEditor.show() - else: - self.sequenceEditor.hide() + self.win.commandSequencer.userEnterCommand('COMPARE_PROTEINS') return def _addWhatsThisText( self ): @@ -357,15 +364,21 @@ class BuildProtein_PropertyManager(EditCommand_PM): self.editPeptidePropertiesButton = PM_PushButton(pmGroupBox, label = "", - text = "Edit Sequence" ) + text = "Edit Properties..." ) self.editPeptidePropertiesButton.setEnabled(False) + + self.compareProteinsButton = PM_PushButton(pmGroupBox, + label = "", + text = "Compare Proteins..." ) + self.compareProteinsButton.setEnabled(False) + return def updatePeptideListWidget(self): """ Update the peptide list widget. It shows all peptides in the part. """ - peptideChunkList = self.getAllProteinChunksInPart() + peptideChunkList = getAllProteinChunksInPart(self.win.assy) if peptideChunkList: self.peptideListWidget.insertItems( @@ -427,11 +440,9 @@ class BuildProtein_PropertyManager(EditCommand_PM): return None return - # getAllProteinChunksInPart() should eventually be moved to assy or some other class. - # This should wait until we have a data model implemented for - # peptides/proteins. - # Ask Bruce. Mark 2008-12-12 - def getAllProteinChunksInPart(self): + # getAllProteinChunksInPart() has been moved to Protein.py + # Mark 2008-12-14 + def getAllProteinChunksInPart_MOVED(self): """ Returns a list of all the protein chunks in the current assy. @@ -444,141 +455,4 @@ class BuildProtein_PropertyManager(EditCommand_PM): peptideList.append(mol) return peptideList - # -------------------------------------------------------------------- - # Deprecated methods to keep until we're certain this is working. - # --Mark 2008-12-12. - - - def _editPeptide_DEPRECATED(self): - """ - Opens the sequence editor for the selected peptide. - """ - - selectedPeptideList = self.win.assy.getSelectedProteinChunks() - - if len(selectedPeptideList) == 1: - peptideChunk = selectedPeptideList[0] - sequence = peptideChunk.protein.get_sequence_string() - self.sequenceEditor.setSequence(sequence) - secStructure = peptideChunk.protein.get_secondary_structure_string() - self.sequenceEditor.setSecondaryStructure(secStructure) - self.sequenceEditor.setRuler(len(secStructure)) - self.sequenceEditor.show() - return - - def _updateProteinParameters_DEPRECATED(self, index): - """ - Update number of amino acids and sequence editor, as well as set the - current protein pdb id which will be used in the child commands and for - rosetta simulation from inside the build protein mode. - @param index: index of the protein combo box - @type index: int - """ - for mol in self.protein_chunk_list: - if mol.name == self.peptideListComboBox.currentText(): - self._numberOfAA = len(mol.protein.get_sequence_string()) - self.numberOfAASpinBox.setValue(self._numberOfAA) - sequence = mol.protein.get_sequence_string() - self.sequenceEditor.setSequence(sequence) - secStructure = mol.protein.get_secondary_structure_string() - self.sequenceEditor.setSecondaryStructure(secStructure) - self.sequenceEditor.setRuler(len(secStructure)) - break - self.set_current_protein_chunk_name(mol.name) - env.history.statusbar_msg("") - - self._editPeptideSequence() #@@@ - - return - - def _updateProteinList_DEPRECATED(self): - """ - Update the list of proteins so that the protein name combo box in this - PM can be populated. - """ - self.protein_chunk_list = [] - self.protein_name_list = [] - for mol in self.win.assy.molecules: - if mol.isProteinChunk(): - self.protein_chunk_list.append(mol) - self.protein_name_list.append(mol.name) - return - - - def _showProteinParametersAndSequenceEditor_DEPRECATED(self): - """ - Show/ Hide protein parameters and sequence editor based on if there's - any protein in NE-1 part. - """ - part = self.win.assy.part - proteinExists, proteinChunk = checkIfProteinChunkInPart(part) - if proteinExists: - #check to see if current_protein is still in part, otherwise set - # this to first available protein - try: - index = self.peptideListComboBox.findText(self.current_protein) - index1 = self.protein_name_list.index(self.current_protein) - except ValueError: - index = 0 - index1 = 0 - self.set_current_protein_chunk_name(self.protein_name_list[index1]) - - self.peptideListComboBox.setCurrentIndex(index) - proteinChunk = self.protein_chunk_list[index1] - self._numberOfAA = len(proteinChunk.protein.get_sequence_string()) - else: - #remove all items from the combo box - count = self.peptideListComboBox.count() - for i in range(count): - self.peptideListComboBox.removeItem(0) - self._numberOfAA = 0 - self.set_current_protein_chunk_name("") - self.numberOfAASpinBox.setValue(self._numberOfAA) - - - #get the sequence for this protein chunk - if proteinExists: - sequence = proteinChunk.protein.get_sequence_string() - self.sequenceEditor.setSequence(sequence) - secStructure = proteinChunk.protein.get_secondary_structure_string() - self.sequenceEditor.setSecondaryStructure(secStructure) - self.sequenceEditor.setRuler(len(secStructure)) - self.editPropertiesPushButton.setEnabled(True) - else: - self.editPropertiesPushButton.setEnabled(False) - self.sequenceEditor.hide() - return - - def _updateProteinListForShow_DEPRECATED(self): - """ - Update the list of proteins in the combo box in the PM. - """ - #first remove from combo box all the proteins that do not exist in NE-1 - #part anymore - currentProteinNameList = [] - for mol in self.win.assy.molecules: - currentProteinNameList.append(mol.name) - - for name in self.protein_name_list: - try: - index = currentProteinNameList.index(name) - except ValueError: - #protein does not exist any more, need to remove it - i = self.protein_name_list.index(name) - self.protein_chunk_list.pop(i) - self.protein_name_list.pop(i) - j = self.peptideListComboBox.findText(name) - self.peptideListComboBox.removeItem(j) - - for mol in self.win.assy.molecules: - #if molecules does not already exist in combo box list, need to add - #them - if mol.isProteinChunk(): - try: - self.protein_name_list.index(mol.name) - except ValueError: - self.protein_chunk_list.append(mol) - self.protein_name_list.append(mol.name) - self.peptideListComboBox.addItem(mol.name) - return
\ No newline at end of file diff --git a/cad/src/protein/commands/CompareProteins/CompareProteins_PropertyManager.py b/cad/src/protein/commands/CompareProteins/CompareProteins_PropertyManager.py index 8540e4370..85a13baf4 100644 --- a/cad/src/protein/commands/CompareProteins/CompareProteins_PropertyManager.py +++ b/cad/src/protein/commands/CompareProteins/CompareProteins_PropertyManager.py @@ -10,6 +10,11 @@ Build > Protein mode. @version: $Id$ @copyright: 2008 Nanorex, Inc. See LICENSE file for details. +To do: +- Switch display styles of selected proteins to diPROTEIN (instead of the GDS). +- fix bug: Leaving Compare command unselects the two selected protein chunks. + The "Build Protein" PM list widget shows them as selected and the compare button is enabled, + but they are not selected in the graphics area. """ import foundation.env as env @@ -21,18 +26,19 @@ from utilities.constants import yellow from PyQt4.Qt import SIGNAL from PM.PM_PushButton import PM_PushButton from PM.PM_GroupBox import PM_GroupBox -from PM.PM_ComboBox import PM_ComboBox +from PM.PM_LineEdit import PM_LineEdit from PM.PM_DoubleSpinBox import PM_DoubleSpinBox from PM.PM_Constants import PM_DONE_BUTTON from PM.PM_Constants import PM_WHATS_THIS_BUTTON - +from protein.model.Protein import getAllProteinChunksInPart +from utilities.constants import diPROTEIN +from utilities.Log import redmsg _superclass = Command_PropertyManager class CompareProteins_PropertyManager(Command_PropertyManager): """ - The ProteinDisplayStyle_PropertyManager class provides a Property Manager - for the B{Display Style} command on the flyout toolbar in the - Build > Protein mode. + The CompareProteins_PropertyManager class provides a Property Manager + for the B{Compare Proteins} command on the Build Protein flyout toolbar. @ivar title: The title that appears in the property manager header. @type title: str @@ -44,62 +50,82 @@ class CompareProteins_PropertyManager(Command_PropertyManager): @ivar iconPath: The relative path to the PNG file that contains a 22 x 22 icon image that appears in the PM header. @type iconPath: str + + @ivar proteinChunk1: The first currently selected protein to be compared. + @type proteinChunk1: protein chunk + + @ivar proteinChunk2: The second currently selected protein to be compared. + @type proteinChunk2: protein chunk """ - title = "Compare Proteins" - pmName = title - iconPath = "ui/actions/Command Toolbar/BuildProtein/Compare.png" - + title = "Compare Proteins" + pmName = title + iconPath = "ui/actions/Command Toolbar/BuildProtein/Compare.png" + proteinChunk1 = None + proteinChunk2 = None def __init__( self, command ): """ Constructor for the property manager. - """ - - - self.currentWorkingDirectory = env.prefs[workingDirectory_prefs_key] - + """ self.threshold = 10.0 _superclass.__init__(self, command) self.showTopRowButtons( PM_DONE_BUTTON | \ PM_WHATS_THIS_BUTTON) - - msg = "Select two protein structures to compare." - self.updateMessage(msg) + return def connect_or_disconnect_signals(self, isConnect = True): if isConnect: change_connect = self.win.connect else: - change_connect = self.win.disconnect + change_connect = self.win.disconnect - #change_connect(self.nextAAPushButton, - # SIGNAL("clicked()"), - # self._expandNextRotamer) + change_connect(self.comparePushButton, + SIGNAL("clicked()"), + self._compareProteins) - #Protein Display methods - - + change_connect(self.thresholdDoubleSpinBox, + SIGNAL("valueChanged(double)"), + self._thresholdChanged) + + change_connect(self.hidePushButton, + SIGNAL("clicked()"), + self._hideDifferences) + return + + def close(self): + """ + Closes the Property Manager. Overrides EditCommand_PM.close() + """ + + env.history.statusbar_msg("") + self._resetAminoAcids() + _superclass.close(self) + + # Restore the original global display style. + self.o.setGlobalDisplayStyle(self.originalDisplayStyle) + return + def show(self): """ - Shows the Property Manager. Extends superclass method. + Show the PM. Extends superclass method. + + @note: _update_UI_do_updates() gets called immediately after this and + updates PM widgets with their correct values/settings. """ - #@REVIEW: Why does it create sequence editor here? Also, is it - #required to be done before the superclass.show call? --Ninad 2008-10-02 - self.sequenceEditor = self.win.createProteinSequenceEditorIfNeeded() - self.sequenceEditor.hide() _superclass.show(self) + env.history.statusbar_msg("") - self._updateProteinList() - self.structure1ComboBox.clear() - self.structure1ComboBox.addItems(self.protein_name_list) - self.structure2ComboBox.clear() - self.structure2ComboBox.addItems(self.protein_name_list) - - + # Force the Global Display Style to "Protein" since this is the only way + # to see comparisons. The global display style will be restored when leaving + # this command (via self.close()). + self.originalDisplayStyle = self.o.displayMode + self.o.setGlobalDisplayStyle(diPROTEIN) + return + def _addGroupBoxes( self ): """ Add the Property Manager group boxes. @@ -107,6 +133,7 @@ class CompareProteins_PropertyManager(Command_PropertyManager): self._pmGroupBox1 = PM_GroupBox( self, title = "Compare") self._loadGroupBox1( self._pmGroupBox1 ) + return def _addWhatsThisText( self ): """ @@ -120,33 +147,22 @@ class CompareProteins_PropertyManager(Command_PropertyManager): """ pass - - def _updateProteinList(self): - """ - """ - self.protein_chunk_list = [] - self.protein_name_list = [] - for mol in self.win.assy.molecules: - if mol.isProteinChunk(): - self.protein_chunk_list.append(mol) - self.protein_name_list.append(mol.name) - def _loadGroupBox1(self, pmGroupBox): """ Load widgets in group box. """ - self._updateProteinList() - - self.structure1ComboBox = PM_ComboBox( pmGroupBox, - label = "First structure:", - choices = self.protein_name_list, - setAsDefault = False) + self.structure1LineEdit = \ + PM_LineEdit( pmGroupBox, + label = "First structure:", + setAsDefault = False) + self.structure1LineEdit.setEnabled(False) - self.structure2ComboBox = PM_ComboBox( pmGroupBox, - label = "Second structure:", - choices = self.protein_name_list, - setAsDefault = False) + self.structure2LineEdit = \ + PM_LineEdit( pmGroupBox, + label = "Second structure:", + setAsDefault = False) + self.structure2LineEdit.setEnabled(False) self.thresholdDoubleSpinBox = \ PM_DoubleSpinBox( pmGroupBox, @@ -159,40 +175,37 @@ class CompareProteins_PropertyManager(Command_PropertyManager): singleStep = 30.0, suffix = " deg", spanWidth = False) - - self.win.connect(self.thresholdDoubleSpinBox, - SIGNAL("valueChanged(double)"), - self._thresholdChanged) self.comparePushButton = \ PM_PushButton( pmGroupBox, text = "Compare", setAsDefault = True) - self.win.connect(self.comparePushButton, - SIGNAL("clicked()"), - self._compareProteins) - self.hidePushButton = \ PM_PushButton( pmGroupBox, text = "Hide differences", setAsDefault = True) - - self.win.connect(self.hidePushButton, - SIGNAL("clicked()"), - self._hideDifferences) + return def _compareProteins(self): """ + Slot for Compare button. + + Compares two selected proteins of the same length. + Amino acids that differ greater than the "threshold" + value are displayed in two colors (red for the first protein + and yellow for the second protein) and are only visible when + the two proteins are displayed in the + reduced display style. """ from utilities.constants import red, orange, green, cyan - if len(self.protein_chunk_list) == 0 or \ - len(self.protein_chunk_list) == 0: + if not self.proteinChunk1 or \ + not self.proteinChunk2: return - protein_1 = self.protein_chunk_list[self.structure1ComboBox.currentIndex()].protein - protein_2 = self.protein_chunk_list[self.structure2ComboBox.currentIndex()].protein + protein_1 = self.proteinChunk1.protein + protein_2 = self.proteinChunk2.protein if protein_1 and \ protein_2: @@ -234,32 +247,119 @@ class CompareProteins_PropertyManager(Command_PropertyManager): self.win.glpane.gl_update() else: - env.history.redmsg("The lengths of compared proteins are not equal.") + msg = "The lengths of compared proteins are not equal." + self.updateMessage(msg) + env.history.redmsg(msg) + return def _hideDifferences(self): """ + Slot for the "Hide differences" button. + + Hides amino acids that differ greater than the "threshold" value. + + @warning: Untested. Code looks suspicious. """ - if len(self.protein_chunk_list) == 0 or \ - len(self.protein_chunk_list) == 0: + if not self.proteinChunk1 or \ + not self.proteinChunk2: return - protein_1 = self.protein_chunk_list[self.structure1ComboBox.currentIndex()].protein - protein_2 = self.protein_chunk_list[self.structure2ComboBox.currentIndex()].protein + protein_1 = self.proteinChunk1.protein + protein_2 = self.proteinChunk2.protein if protein_1 and \ protein_2: aa_list_1 = protein_1.get_amino_acids() aa_list_2 = protein_2.get_amino_acids() if len(aa_list_1) == len(aa_list_2): - protein_1.collapse_all_rotamers() - protein_2.collapse_all_rotamers() + protein_1.collapse_all_rotamers() #@@@ + protein_2.collapse_all_rotamers() #@@@ for aa1, aa2 in zip (aa_list_1, aa_list_2): aa1.color = None aa2.color = None aa1.collapse() aa2.collapse() - + self.win.glpane.gl_update() + return + def _thresholdChanged(self, value): + """ + Slot for Threshold spinbox. + """ self.threshold = value self._compareProteins() + return + + def _resetAminoAcids(self): + """ + Resets the color and collapse all amino acids of all proteins. + """ + + proteinChunkList = getAllProteinChunksInPart(self.win.assy) + + for proteinChunk in proteinChunkList: + proteinChunk.protein.collapse_all_rotamers() + aa_list = proteinChunk.protein.get_amino_acids() + for aa in aa_list: + aa.color = None + aa.collapse() + + self.win.glpane.gl_update() + return + def _update_UI_do_updates(self): + """ + Overrides superclass method. + + @see: Command_PropertyManager._update_UI_do_updates() + """ + + self.proteinChunk1 = None + self.proteinChunk2 = None + self.comparePushButton.setEnabled(False) + self.hidePushButton.setEnabled(False) + + selectedProteinList = self.win.assy.getSelectedProteinChunks() + + if len(selectedProteinList) == 0: + self.structure1LineEdit.setText("") + self.structure2LineEdit.setText("") + msg = "Select two structures of the same length in the graphics area, "\ + "then click the <b>Compare</b> button to compare them." + + elif len(selectedProteinList) == 1: + self.proteinChunk1 = selectedProteinList[0] + aa1_count = " (%d)" % self.proteinChunk1.protein.count_amino_acids() + self.structure1LineEdit.setText(self.proteinChunk1.name + aa1_count) + self.structure2LineEdit.setText("") + msg = "Select one more structure in the graphics area that is the same "\ + "length as <b>" + self.proteinChunk1.name + "</b>. "\ + "Then click the <b>Compare</b> button to compare them." + + elif len(selectedProteinList) == 2: + self.proteinChunk1 = selectedProteinList[0] + aa1_count = " (%d)" % self.proteinChunk1.protein.count_amino_acids() + self.structure1LineEdit.setText(self.proteinChunk1.name + aa1_count) + + self.proteinChunk2 = selectedProteinList[1] + aa2_count = " (%d)" % self.proteinChunk2.protein.count_amino_acids() + self.structure2LineEdit.setText(self.proteinChunk2.name + aa2_count) + + if aa1_count == aa2_count: + self.comparePushButton.setEnabled(True) + self.hidePushButton.setEnabled(True) + msg = "Click the <b>Compare</b> button to compare the two selected structures." + else: + msg = "<b>%s</b> and <b>%s</b> are not the same length." % \ + (self.proteinChunk1.name, self.proteinChunk2.name) + msg = redmsg(msg) + + else: + self.structure1LineEdit.setText("") + self.structure2LineEdit.setText("") + msg = redmsg("Too many proteins selected.") + + self.updateMessage(msg) + env.history.redmsg(msg) + return + diff --git a/cad/src/protein/commands/EditRotamers/EditRotamers_PropertyManager.py b/cad/src/protein/commands/EditRotamers/EditRotamers_PropertyManager.py index e50d29101..6c0631526 100644 --- a/cad/src/protein/commands/EditRotamers/EditRotamers_PropertyManager.py +++ b/cad/src/protein/commands/EditRotamers/EditRotamers_PropertyManager.py @@ -19,6 +19,7 @@ To do: - Add "Number of AA:" field (disabled). - Include name of the current peptide in the title of the Sequence Editor. - Sync Residue combobox and sequence editor (or remove one or the other). +- Add wait (hourglass) cursor when changing the display style of proteins. """ import os, time, fnmatch, string import foundation.env as env @@ -156,10 +157,15 @@ class EditRotamers_PropertyManager(Command_PropertyManager): aa_list = self.current_protein.protein.get_amino_acid_id_list() for j in range(len(aa_list)): self.aminoAcidsComboBox.addItem(aa_list[j]) - + + # This doesn't generate a signal (only 'activate' is connected to + # slot _aminoAcidChanged). self.aminoAcidsComboBox.setCurrentIndex( self.current_protein.protein.get_current_amino_acid_index()) + # Call the slot explicitly. This is needed to draw the rotamer + # on top of the reduced model of the current protein. + # Also see the comments in _update_UI_do_updates(). self._aminoAcidChanged( self.current_protein.protein.get_current_amino_acid_index()) @@ -191,16 +197,17 @@ class EditRotamers_PropertyManager(Command_PropertyManager): if self.current_protein: self.current_protein.setDisplayStyle(self.previous_protein_display_style) self.previous_protein = None - EditCommand_PM.close(self) + _superclass.close(self) return def show(self): """ - Extends superclass method. + Show the PM. Extends superclass method. + @note: _update_UI_do_updates() gets called immediately after this and + updates PM widgets with their correct values/settings. """ _superclass.show(self) - #self._update_UI_do_updates() #@@@ self.updateMessage("Edit...") self.sequenceEditor.show() env.history.statusbar_msg("") @@ -475,6 +482,7 @@ class EditRotamers_PropertyManager(Command_PropertyManager): def _aminoAcidChanged(self, index): """ + Slot for the "Current residue" combobox. """ if not self.current_protein: return @@ -548,6 +556,16 @@ class EditRotamers_PropertyManager(Command_PropertyManager): print "_update_UI_do_updates(): DO NOTHING." return + # NOTE: Changing the display styles of the protein chunks can take some + # time. We should put up the wait (hourglass) cursor here and restore + # before returning. + + # Update all PM widgets that need to be since something has changed. + print "_update_UI_do_updates(): UPDATING the PMGR." + self.update_name_field() + self.update_sequence_editor() + self.update_residue_combobox() + if self.previous_protein: self.previous_protein.setDisplayStyle(self.previous_protein_display_style) @@ -558,104 +576,4 @@ class EditRotamers_PropertyManager(Command_PropertyManager): self.previous_protein_display_style = self.current_protein.getDisplayStyle() self.current_protein.setDisplayStyle(diPROTEIN) - # Update all PM widgets that need to be since something has changed. - # NOTE: This must happen after the display style has been changed, - # or the rotamer doesn't show up on the protein the first time it is - # drawn in diPROTEIN. - print "_update_UI_do_updates(): UPDATING the PMGR." - self.update_name_field() - self.update_residue_combobox() - self.update_sequence_editor() - return - - # ========================================================================= - # Deprecated methods. Keep them below for reference until everything is - # working. - - def _expandNextRotamer_DEPRECATED(self): - """ - """ - for chunk in self.win.assy.molecules: - #Urmi 20080728: slot method for the current protein from build protein mode - if chunk.isProteinChunk() and chunk.name == self.current_protein: - chunk.protein.traverse_forward() - self._display_and_recenter() - self._updateAminoAcidInfo( - chunk.protein.get_current_amino_acid_index()) - return - return - - def _expandPreviousRotamer_DEPRECATED(self): - """ - """ - for chunk in self.win.assy.molecules: - #Urmi 20080728: slot method for the current protein from build protein mode - if chunk.isProteinChunk() and chunk.name == self.current_protein: - chunk.protein.traverse_backward() - self._display_and_recenter() - self._updateAminoAcidInfo( - chunk.protein.get_current_amino_acid_index()) - return - return - - def _collapseAllRotamers_DEPRECATED(self): - """ - """ - for chunk in self.win.assy.molecules: - #Urmi 20080728: slot method for the current protein from build protein mode - if chunk.isProteinChunk() and chunk.name == self.current_protein: - chunk.protein.collapse_all_rotamers() - self.win.glpane.gl_update() - return - return - - def _expandAllRotamers_DEPRECATED(self): - """ - """ - for chunk in self.win.assy.molecules: - #Urmi 20080728: slot method for the current protein from build protein mode - if chunk.isProteinChunk() and chunk.name == self.current_protein: - chunk.protein.expand_all_rotamers() - self.win.glpane.gl_update() - return - return - - def _display_and_recenter_DEPRECATED(self): - """ - """ - for chunk in self.win.assy.molecules: - #Urmi 20080728: display and recenter for the current protein - #from build protein mode - if chunk.isProteinChunk() and chunk.name == self.current_protein: - chunk.protein.collapse_all_rotamers() - current_aa = chunk.protein.get_current_amino_acid() - if current_aa: - chunk.protein.expand_rotamer(current_aa) - self._update_chi_angles(current_aa) - if self.recenterViewCheckBox.isChecked(): - ca_atom = current_aa.get_c_alpha_atom() - if ca_atom: - self.win.glpane.pov = -ca_atom.posn() - - self.win.glpane.gl_update() - return - - def _aminoAcidChanged_DEPRECATED(self, index): - """ - """ - for chunk in self.win.assy.molecules: - #Urmi 20080728: slot method for the current protein from build protein mode - if chunk.isProteinChunk() and chunk.name == self.current_protein: - chunk.protein.set_current_amino_acid_index(index) - - self._display_and_recenter() - - #Urmi 20080728: change the cursor position in the sequence editor - # when current amino acid in the amino acid combo box is changed - cursor = self.sequenceEditor.sequenceTextEdit.textCursor() - if index == -1: - index = 0 - cursor.setPosition(index, QTextCursor.MoveAnchor) - cursor.setPosition(index + 1, QTextCursor.KeepAnchor) - self.sequenceEditor.sequenceTextEdit.setTextCursor( cursor ) return diff --git a/cad/src/protein/model/Protein.py b/cad/src/protein/model/Protein.py index f3b82c195..3a9d4cc10 100644 --- a/cad/src/protein/model/Protein.py +++ b/cad/src/protein/model/Protein.py @@ -384,6 +384,12 @@ class Protein: """ return self.residues_list + def count_amino_acids(self): + """ + Returns the number of amino acids. + """ + return len(self.residues_list) + def assign_helix(self, resId): """ Assign a helical secondary structure to resId. @@ -625,11 +631,27 @@ class Protein: the actual model. Maybe we'll take care of that when we move to the new model """ - win.commandSequencer.userEnterCommand('MODEL_AND_SIMULATE_PROTEIN') + win.commandSequencer.userEnterCommand('EDIT_ROTAMERS') return pass # end of class Protein + +# Protein helper methods should be located here. +# Mark 2008-12-14 +def getAllProteinChunksInPart(assy): + """ + Returns a list of all the protein chunks in assy. + + @return: a list of all the protein chunks in assy. + @rtype: list of chunks + """ + proteinChunkList = [] + for mol in assy.molecules: + if mol.isProteinChunk(): + proteinChunkList.append(mol) + return proteinChunkList + # piotr 082008: This and possibly several Rosetta-related methods of the Protein # class should be re-factored and moved to a separate file in simulations/ROSETTA. |