forked from biopython/biopython
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathxbb_blast.py
More file actions
212 lines (177 loc) · 7.71 KB
/
Copy pathxbb_blast.py
File metadata and controls
212 lines (177 loc) · 7.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
#!/usr/bin/env python
# Copyright 2000 by Thomas Sicheritz-Ponten.
# Copyrigth 2016 by Markus Piotrowski.
# All rights reserved.
# This code is part of the Biopython distribution and governed by its
# license. Please see the LICENSE file that should have been included
# as part of this package.
# Created: Thu Jul 13 14:07:25 2000
# thomas@cbs.dtu.dk, http://www.cbs.dtu.dk/thomas
"""BLAST code for graphical Xbbtools tool."""
from __future__ import print_function
import glob
import os
import sys
try: # Python 2
import Tkinter as tk
import ttk
import tkFileDialog as filedialog
import tkMessageBox as messagebox
except ImportError: # Python 3
import tkinter as tk
import tkinter.ttk as ttk
from tkinter import filedialog
from tkinter import messagebox
from xbb_utils import NotePad
import xbb_blastbg
class BlastIt(object):
"""Local BLAST integration for xbbtools."""
nin, pin = [], []
blast_ok = False
blast_path = ""
def __init__(self, seq, parent=None):
"""Set up new top-level window for BLAST search."""
self.seq = seq
self.parent = parent
self.toplevel = tk.Toplevel(parent)
self.toplevel.title("BLAST parameters")
if not self.get_blast_databases() or not self.get_blast_binaries():
return
self.Choices()
self.dbs.bind("<<ComboboxSelected>>", self.Validate)
self.blasts.bind("<<ComboboxSelected>>", self.Validate)
def get_blast_databases(self):
"""Try to locate the BLAST databases and put into lists."""
if not (BlastIt.nin and BlastIt.pin):
pin, nin = [], []
try:
pin.extend(glob.glob(os.environ["BLASTDB"] + "/*.pin"))
except KeyError:
pass
pin.extend(glob.glob("C:*.pin"))
try:
nin.extend(glob.glob(os.environ["BLASTDB"] + "/*.nin"))
except KeyError:
pass
# If no system variable BLASTDB exists, give user the chance to
# locate his database folder:
if not(nin and pin):
database_folder = filedialog.askdirectory(
title="Please locate your BLAST database(s) folder:")
nin.extend(glob.glob(database_folder + "/*.nin"))
pin.extend(glob.glob(database_folder + "/*.pin"))
if not (nin and pin):
messagebox.showerror("xbb tools", "This folder does not"
" contain any BLAST databases!")
self.toplevel.destroy()
return False
self.pin = [os.path.splitext(x)[0] for x in pin]
self.nin = [os.path.splitext(x)[0] for x in nin]
BlastIt.pin = self.pin
BlastIt.nin = self.nin
return True
def get_blast_binaries(self):
"""Test if BLAST binaries are in PATH or let user locate them."""
if not BlastIt.blast_ok:
# Test if blast binaries are in path
if os.system("blastn -version"): # Return of non-zero means error
self.blast_path = filedialog.askdirectory(
title="Please locate your BLAST program folder:")
self.blast_path += os.sep
if os.system("{}blastn -version".format(self.blast_path)):
messagebox.showerror(
"xbb tools", "Wrong folder or missing BLAST"
" binaries!\n To run BLAST you must install the "
" standalone BLAST binaries.")
self.toplevel.destroy()
return False
else:
BlastIt.blast_ok = True
else: # BLAST binaries are in PATH
BlastIt.blast_ok = True
self.blast_path = ""
BlastIt.blast_path = self.blast_path
self.toplevel.lift()
return True
def database_readable(self, db_paths):
"""Return the name of the blast database without path and extension."""
db_names = [entry.split(os.sep)[-1].split(".")[0]
for entry in db_paths]
return db_names
def convert_dbname_to_dbpath(self, db_name):
"""Return the full path for a given blast database name."""
database_path = ""
for database in self.nin:
if database.endswith(db_name):
database_path = database
break
for database in self.pin:
if database.endswith(db_name):
database_path = database
break
return database_path
def Choices(self):
"""Set up window to select BLAST program and database."""
self.blast_string = tk.StringVar()
self.blast_string.set("blastn")
self.cf = ttk.Frame(self.toplevel)
self.cf.pack(side="top", expand=1, fill="x")
self.dbs_frame = ttk.LabelFrame(self.cf, text="Databases")
self.dbs_frame.pack(side="left", padx=5, pady=5, expand=1, fill="x")
nin_values = self.database_readable(self.nin)
pin_values = self.database_readable(self.pin)
self.dbs = ttk.Combobox(self.dbs_frame, exportselection=0,
values=nin_values + pin_values)
self.dbs.current(0)
self.blast_frame = ttk.LabelFrame(self.cf, text="BLAST programs")
self.blast_frame.pack(side="left", padx=5, pady=5, expand=1, fill="x")
self.blasts = ttk.Combobox(self.blast_frame, exportselection=0,
textvariable=self.blast_string,
values=["blastn", "blastp", "blastx",
"tblastn", "tblastx"])
self.dbs.pack(side="left", padx=5, pady=5, expand=1, fill="x")
self.blasts.pack(side="left", padx=5, pady=5, expand=1, fill="x")
self.option_f = ttk.LabelFrame(self.cf, text="Command line options")
self.option_f.pack(side="left", padx=5, pady=5, expand=1, fill="x")
self.option = ttk.Entry(self.option_f)
self.option.pack(side="left", padx=5, pady=5, fill="x", expand=1)
self.ok = ttk.Button(self.cf, text="Run", command=self._Run,
state="disabled")
self.ok.pack(side="right")
self.Validate()
def Validate(self, *args):
"""Check everything and enable/disable 'Run' button."""
db = self.convert_dbname_to_dbpath(self.dbs.get())
prog = self.blasts.get()
if (prog in ["blastn", "tblastx", "tblastn"]) == (db in self.nin):
self.ok.config(state="normal")
elif (prog in ["blastp", "blastx"]) == (db in self.pin):
self.ok.config(state="normal")
else:
self.ok.config(state="disabled")
def _Run(self):
"""Initialise options for Blast commandline (PRIVATE)."""
command_options = self.option.get()
options = ""
if len(command_options.strip()):
options = command_options.strip()
db = self.convert_dbname_to_dbpath(self.dbs.get())
prog = self.blast_path + self.blasts.get()
self.command_data = [self.seq, prog, db, options]
self.Run()
def Run(self):
"""Open new notepad and initialize running BLAST."""
self.notepad = NotePad()
tid = self.notepad.tid
self.toplevel.destroy()
blastbg = xbb_blastbg.BlastDisplayer(self.command_data, tid)
blastbg.RunCommand()
if __name__ == "__main__":
try:
seq = sys.argv[1]
except IndexError: # Started script without providing a sequence
seq = "ATGACAAAGCTAATTATTCACTTGGTTTCAGACTCTTCTGTGCAAACTGC"
win = tk.Tk()
win.title("Dummy windows for BLAST test")
test = BlastIt(seq)
win.mainloop()