diff --git a/ete3/coretype/tree.py b/ete3/coretype/tree.py index d0d3e93cd..23bd7b5c3 100644 --- a/ete3/coretype/tree.py +++ b/ete3/coretype/tree.py @@ -68,6 +68,7 @@ DEFAULT_DIST = 1.0 DEFAULT_SUPPORT = 1.0 DEFAULT_NAME = "" +DEFAULT_TEXT_COLOR = "black" class TreeError(Exception): """ @@ -1353,7 +1354,7 @@ def unroot(self, mode='legacy'): else: raise TreeError("Cannot unroot a tree with only two leaves") - def show(self, layout=None, tree_style=None, name="ETE"): + def show(self, layout=None, tree_style=None, name="ETE", child_app = False): """ Starts an interactive session to visualize current node structure using provided layout and TreeStyle. @@ -1361,8 +1362,9 @@ def show(self, layout=None, tree_style=None, name="ETE"): """ from ..treeview import drawer drawer.show_tree(self, layout=layout, - tree_style=tree_style, win_name=name) + tree_style=tree_style, win_name=name, child_app = child_app) + def render(self, file_name, layout=None, w=None, h=None, \ tree_style=None, units="px", dpi=90): """ @@ -2586,6 +2588,13 @@ def phonehome(self): from .. import _ph _ph.call() + def add_leaf_text_color(self, color=None): + # Added the extra function to use the is_leaf() bool + if self.is_leaf(): + if color == None: + color = "#000000" + self.add_feature("text_color",color) + def _translate_nodes(root, *nodes): name2node = dict([ [n, None] for n in nodes if type(n) is str]) if name2node: diff --git a/ete3/treeview/drawer.py b/ete3/treeview/drawer.py index c6785a43e..21c3d29a4 100644 --- a/ete3/treeview/drawer.py +++ b/ete3/treeview/drawer.py @@ -56,23 +56,25 @@ def exit_gui(a, b): _QApp.exit(0) -def init_scene(t, layout, ts): +def init_scene(t, layout, ts, child_app = False): global _QApp ts = init_tree_style(t, ts) if layout: ts.layout_fn = layout - if not _QApp: + if not child_app: _QApp = QApplication(["ETE"]) + else: + _QApp = QMainWindow() scene = _TreeScene() #ts._scale = None return scene, ts -def show_tree(t, layout=None, tree_style=None, win_name=None): +def show_tree(t, layout=None, tree_style=None, win_name=None, child_app=None): """ Interactively shows a tree.""" - scene, img = init_scene(t, layout, tree_style) + scene, img = init_scene(t, layout, tree_style, child_app=child_app) tree_item, n2i, n2f = render(t, img) scene.init_values(t, img, n2i, n2f) @@ -91,7 +93,10 @@ def show_tree(t, layout=None, tree_style=None, win_name=None): signal.signal(signal.SIGALRM, exit_gui) signal.alarm(GUI_TIMEOUT) - _QApp.exec_() + if not child_app: + _QApp.exec_() + else: + pass def render_tree(t, imgName, w=None, h=None, layout=None, tree_style = None, header=None, units="px", @@ -149,10 +154,13 @@ def run(self): def get_img(t, w=None, h=None, layout=None, tree_style = None, - header=None, units="px", dpi=90, return_format="%%return"): + header=None, units="px", dpi=90, return_format="%%return", child_app = False): global _QApp - if not _QApp: + if not child_app and not _QApp: _QApp = QApplication(["ETE"]) + else: + _QApp = QMainWindow() + r = RenderThread(t, layout, tree_style, w, h, dpi, units, return_format) r.start() diff --git a/ete3/treeview/node_gui_actions.py b/ete3/treeview/node_gui_actions.py index 7de5a04e3..10f492afe 100644 --- a/ete3/treeview/node_gui_actions.py +++ b/ete3/treeview/node_gui_actions.py @@ -151,6 +151,8 @@ def mouseDoubleClickEvent(self,e): def showActionPopup(self): contextMenu = QMenu() + contextMenu.addAction( "Ladderize top to bottom", self.ladderize_top) + contextMenu.addAction( "Ladderize bottom to top", self.ladderize_bottom) contextMenu.addAction( "Set as outgroup", self.set_as_outgroup) contextMenu.addAction( "Copy partition", self.copy_partition) contextMenu.addAction( "Cut partition", self.cut_partition) @@ -264,6 +266,14 @@ def toggle_collapse(self): self.node.img_style["draw_descendants"] ^= True self.scene().GUI.redraw() + def ladderize_top(self): + self.node.ladderize(1) + self.scene().GUI.redraw() + + def ladderize_bottom(self): + self.node.ladderize(0) + self.scene().GUI.redraw() + def cut_partition(self): self.scene().view.buffer_node = self.node self.node.detach() diff --git a/ete3/treeview/qt4_gui.py b/ete3/treeview/qt4_gui.py index b33bacea1..ecc92b104 100644 --- a/ete3/treeview/qt4_gui.py +++ b/ete3/treeview/qt4_gui.py @@ -369,9 +369,9 @@ def on_actionOpen_triggered(self): @QtCore.pyqtSlot() def on_actionSave_newick_triggered(self): - fname = QFileDialog.getSaveFileName(self ,"Save File", + fname = QFileDialog.getSaveFileName(self ,"Save Newick File", "/home", - "Newick (*.nh *.nhx *.nw )") + "Newick (*.nh *.nhx *.nw *.nwk *.newick)") nw = self.scene.tree.write() try: OUT = open(fname,"w") @@ -383,27 +383,30 @@ def on_actionSave_newick_triggered(self): @QtCore.pyqtSlot() def on_actionRenderPDF_triggered(self): - F = QFileDialog(self) - if F.exec_(): - imgName = str(F.selectedFiles()[0]) - if not imgName.endswith(".pdf"): - imgName += ".pdf" - save(self.scene, imgName) - + file_filter = "PDF file (*.PDF)" + response = QFileDialog.getSaveFileName(parent=self, + caption = "Save PDF file", + filter = file_filter + ) + if response != "": + save(self.scene, response[0]) + else: + return @QtCore.pyqtSlot() def on_actionRender_selected_region_triggered(self): if not self.scene.selector.isVisible(): return QMessageBox.information(self, "!",\ "You must select a region first") - - F = QFileDialog(self) - if F.exec_(): - imgName = str(F.selectedFiles()[0]) - if not imgName.endswith(".pdf"): - imgName += ".pdf" - save(imgName, take_region=True) - + file_filter = "PDF file (*.PDF)" + response = QFileDialog.getSaveFileName(parent=self, + caption = "Save PDF file", + filter = file_filter + ) + if response != "": + save(self.scene, response[0]) + else: + return @QtCore.pyqtSlot() def on_actionPaste_newick_triggered(self): diff --git a/ete3/treeview/qt4_render.py b/ete3/treeview/qt4_render.py index 10f30aed5..d4444c433 100644 --- a/ete3/treeview/qt4_render.py +++ b/ete3/treeview/qt4_render.py @@ -260,7 +260,12 @@ def render(root_node, img, hide_root=False): faces.add_face_to_node(su_face, n, 0, position="branch-bottom") if _leaf(n) and n.name and img.show_leaf_name: - faces.add_face_to_node(na_face, n, 0, position="branch-right") + if hasattr(n, "_faces") and 0 in n._faces.__dict__["branch-right"]: + pass + # If the node already has a text face in the position branch right in column 0 + # the user already has already added a face in that position (node name with certain color) + else: + faces.add_face_to_node(na_face, n, 0, position="branch-right") if _leaf(n):# or len(n.img_style["_faces"]["aligned"]): virtual_leaves += 1