1# Copyright 2000 by Katharine Lindner (Cayte). 2# Copyright 2016 by Markus Piotrowski. 3# All rights reserved. 4# This code is part of the Biopython distribution and governed by its 5# license. Please see the LICENSE file that should have been included 6# as part of this package. 7# 8# The original SeqGui was written by Katharine Lindner (Cayte) in 2000 using 9# the wxPython library for the GUI. It was rewritten by Markus Piotrowski in 10# 2016 using tkinter and tkinter's themed widgets (ttk). 11"""A small GUI tool to demonstrate some basic sequence operations. 12 13SeqGui (sequence graphical user interface) is a little tool that allows 14transcription, translation and back translation of a sequence that the 15user can type or copy into a text field. For translation the user can select 16from several codon tables which are implemented in Biopython. 17It runs as a standalone application. 18 19""" 20import tkinter as tk 21import tkinter.ttk as ttk 22 23from Bio.Seq import translate, transcribe, back_transcribe 24from Bio.Data import CodonTable 25 26 27main_window = tk.Tk() 28main_window.title("Greetings from Biopython") 29 30menue = tk.Menu(main_window) 31menue_single = tk.Menu(menue, tearoff=0) 32menue.add_cascade(menu=menue_single, label="File") 33menue_single.add_command(label="About") 34menue_single.add_separator() 35menue_single.add_command(label="Exit", command=main_window.destroy) 36main_window.config(menu=menue) 37 38# Left panel with parameters 39param_panel = ttk.Frame(main_window, relief=tk.GROOVE, padding=5) 40 41codon_panel = ttk.LabelFrame(param_panel, text="Codon Tables") 42codon_scroller = ttk.Scrollbar(codon_panel, orient=tk.VERTICAL) 43codon_list = tk.Listbox( 44 codon_panel, height=5, width=25, yscrollcommand=codon_scroller.set 45) 46 47# Import actual codon tables from Biopython and sort alphabetically 48codon_table_list = sorted( 49 table.names[0] for n, table in CodonTable.generic_by_id.items() 50) 51 52# 'Standard' table should be first in the list 53del codon_table_list[codon_table_list.index("Standard")] 54codon_table_list.insert(0, "Standard") 55 56for codon_table in codon_table_list: 57 codon_list.insert(tk.END, codon_table) 58codon_list.selection_set(0) 59codon_list.configure(exportselection=False) 60codon_scroller.config(command=codon_list.yview) 61 62# Radiobuttons are more appropriate than another listbox here: 63transform_panel = ttk.LabelFrame(param_panel, text="Transformation") 64 65transform_var = tk.StringVar() 66transform_transcribe = ttk.Radiobutton( 67 transform_panel, text="Transcribe", variable=transform_var, value="transcribe" 68) 69transform_translate = ttk.Radiobutton( 70 transform_panel, text="Translate", variable=transform_var, value="translate" 71) 72transform_backtranscribe = ttk.Radiobutton( 73 transform_panel, 74 text="Back transcribe", 75 variable=transform_var, 76 value="back transcribe", 77) 78transform_translate.invoke() 79 80# Right panel with sequence in- and output 81seq_panel = ttk.Frame(main_window, relief=tk.GROOVE, padding=5) 82 83input_panel = ttk.LabelFrame(seq_panel, text="Original Sequence") 84input_scroller = ttk.Scrollbar(input_panel, orient=tk.VERTICAL) 85input_text = tk.Text(input_panel, width=39, height=5, yscrollcommand=input_scroller.set) 86input_scroller.config(command=input_text.yview) 87 88output_panel = ttk.LabelFrame(seq_panel, text="Transformed Sequence") 89output_scroller = ttk.Scrollbar(output_panel, orient=tk.VERTICAL) 90output_text = tk.Text( 91 output_panel, width=39, height=5, yscrollcommand=output_scroller.set 92) 93output_scroller.config(command=output_text.yview) 94 95# Buttons 96apply_button = ttk.Button(seq_panel, text="Apply") 97clear_button = ttk.Button(seq_panel, text="Clear") 98close_button = ttk.Button(seq_panel, text="Close", command=main_window.destroy) 99 100 101# Statusbar 102statustext = tk.StringVar() 103statusbar = ttk.Label(main_window, textvariable=statustext, relief=tk.GROOVE, padding=5) 104statustext.set("This is the statusbar") 105sizegrip = ttk.Sizegrip(statusbar) 106 107 108# Event methods 109def clear_output(): 110 """Clear the output window.""" 111 input_text.delete(1.0, tk.END) 112 output_text.delete(1.0, tk.END) 113 114 115def apply_operation(): 116 """Do the selected operation.""" 117 codon_table = codon_list.get(codon_list.curselection()) 118 print(f"Code: {codon_table}") 119 120 seq = "".join(input_text.get(1.0, tk.END).split()) 121 print(f"Input sequence: {seq}") 122 123 operation = transform_var.get() 124 print(f"Operation: {operation}") 125 126 if operation == "transcribe": 127 result = transcribe(seq) 128 elif operation == "translate": 129 result = translate(seq, table=codon_table, to_stop=True) 130 elif operation == "back transcribe": 131 result = back_transcribe(seq) 132 else: 133 result = "" 134 135 output_text.delete(1.0, tk.END) 136 output_text.insert(tk.END, result) 137 print(f"Result: {result}") 138 139 140def set_statusbar(event): 141 """Show statusbar comments from menu selection.""" 142 index = main_window.call(event.widget, "index", "active") 143 if index == 0: 144 statustext.set("More information about this program") 145 elif index == 2: 146 statustext.set("Terminate the program") 147 else: 148 statustext.set("This is the statusbar") 149 150 151# Set commands and bind events 152menue_single.bind("<<MenuSelect>>", set_statusbar) 153apply_button.config(command=apply_operation) 154clear_button.config(command=clear_output) 155 156# Build GUI 157statusbar.pack(side=tk.BOTTOM, padx=1, fill=tk.X) 158sizegrip.pack(side=tk.RIGHT, padx=3, pady=4) 159 160param_panel.pack(side=tk.LEFT, anchor=tk.N, padx=5, pady=10, fill=tk.Y) 161codon_panel.pack(fill=tk.Y, expand=True) 162codon_scroller.pack(side=tk.RIGHT, fill=tk.Y) 163codon_list.pack(fill=tk.Y, expand=True) 164transform_panel.pack(pady=10, fill=tk.X) 165transform_transcribe.pack(anchor=tk.W) 166transform_translate.pack(anchor=tk.W) 167transform_backtranscribe.pack(anchor=tk.W) 168 169seq_panel.pack(anchor=tk.N, padx=5, pady=10, fill=tk.BOTH, expand=True) 170input_panel.pack(fill=tk.BOTH, expand=True) 171input_scroller.pack(side=tk.RIGHT, fill=tk.Y) 172input_text.pack(fill=tk.BOTH, expand=True) 173output_panel.pack(pady=10, fill=tk.BOTH, expand=True) 174output_scroller.pack(side=tk.RIGHT, fill=tk.Y) 175output_text.pack(fill=tk.BOTH, expand=True) 176apply_button.pack(side=tk.LEFT) 177clear_button.pack(side=tk.LEFT, padx=10) 178close_button.pack(side=tk.LEFT) 179 180main_window.mainloop() 181