Andrew Stirn commited on
Commit
5e69dea
·
1 Parent(s): c661b33

app.py overhaul progress

Browse files
Files changed (1) hide show
  1. app.py +154 -76
app.py CHANGED
@@ -1,8 +1,17 @@
1
- import os
2
- import shutil
3
  import pandas as pd
4
  import streamlit as st
5
- from tiger import tiger_exhibit, load_transcripts, TARGET_LEN, NUCLEOTIDE_TOKENS
 
 
 
 
 
 
 
 
 
 
6
 
7
 
8
  @st.cache_data
@@ -11,77 +20,146 @@ def convert_df(df):
11
  return df.to_csv().encode('utf-8')
12
 
13
 
14
- # title and initialization
15
- st.title('TIGER Cas13 Efficacy Prediction')
16
- st.session_state['manual_seq'] = ''
17
- st.session_state['fasta_seq'] = ''
18
-
19
- # run mode selection
20
- with st.form(key='calc_options'):
21
- c1_names = ['On-target', 'On- and off-target']
22
- option = st.radio('Select mode:', c1_names, index=0)
23
- submitButton = st.form_submit_button(label='Choose options')
24
-
25
- # text input
26
- manual_entry = st.form('text')
27
- manual_input = manual_entry.text_input(
28
- label='Enter a target transcript:',
29
- # value='ATGCAGGACGCGGAGAACGTGGCGGTGCCCGAGGCGGCCGAGGAGCGCGC',
30
- placeholder='Upper or lower case')
31
- if manual_input:
32
- if len(manual_input) < TARGET_LEN:
33
- manual_entry.write('Transcript must be at least {:d} bases.'.format(TARGET_LEN))
34
  else:
35
- st.session_state['manual_seq'] = manual_input
36
- manual_mode = manual_entry.form_submit_button(label='calculate')
37
-
38
- # fasta input
39
- fasta_form = st.form('fasta')
40
- fasta_input = fasta_form.file_uploader(label='Upload a fasta file:')
41
- if fasta_input:
42
- if os.path.exists('temp'):
43
- shutil.rmtree('temp')
44
- os.makedirs('temp')
45
- st.write(fasta_input.name)
46
- fpath = os.path.join('temp', fasta_input.name)
47
- with open(fpath, 'w') as f:
48
- f.write(fasta_input.getvalue().decode('utf-8'))
49
- transcript_tbl = load_transcripts([fpath])
50
- fasta_form.text('fasta file contents')
51
- fasta_form.write(transcript_tbl)
52
- seq = transcript_tbl['seq'][0]
53
- st.session_state['fasta_seq'] = seq
54
- fasta_mode = fasta_form.form_submit_button(label='Calculate')
55
-
56
- # input-specific configuration
57
- if manual_mode:
58
- src_seq = st.session_state['manual_seq']
59
- status_text = manual_entry.empty()
60
- status_bar = manual_entry.progress(0)
61
- elif fasta_mode:
62
- src_seq = st.session_state['fasta_seq']
63
- status_text = fasta_form.empty()
64
- status_bar = fasta_form.progress(0)
65
- else:
66
- src_seq = status_bar = status_text = None
67
-
68
- # valid input
69
- if src_seq and all([True if nt.upper() in NUCLEOTIDE_TOKENS.keys() else False for nt in src_seq]):
70
- on_target, off_target = tiger_exhibit(pd.DataFrame(dict(id=['ManualEntry'], seq=[src_seq])),
71
- status_bar, status_text, check_off_targets=option == 'On and Off Target')
72
- on_target.rename(columns={'Guide': '23 nt guide sequence'}, inplace=True)
73
- if len(on_target) > 0:
74
- if on_target.iloc[0]['On-target ID'] == 0:
75
- on_target.drop(['On-target ID'], axis=1, inplace=True)
76
- st.write('On-target predictions: ', on_target)
77
- st.download_button(label='Download', data=convert_df(on_target), file_name='on_target.csv', mime='text/csv')
78
- if option == 'On and Off Target' and len(off_target) > 0:
79
- off_target.rename(columns={'Guide': '23 nt guide sequence'}, inplace=True)
80
- st.write('Off-target predictions: ', off_target)
81
- st.download_button(label='Download', data=convert_df(off_target), file_name='off_target.csv', mime='text/csv')
82
- elif option == 'On and Off Target' and len(off_target) == 0:
83
- st.write('We did not find any off-target effects!')
84
-
85
- # invalid input
86
- elif src_seq is not None:
87
- st.write('Invalid input!')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import tiger
 
2
  import pandas as pd
3
  import streamlit as st
4
+
5
+ ENTRY_METHODS = dict(
6
+ manual='Manual entry of single transcript',
7
+ fasta="Fasta file upload (supports multiple transcripts if they have unique ID's)"
8
+ )
9
+
10
+ # containers
11
+ DOCUMENTATION = st.container()
12
+ MODE_SELECTION = st.container()
13
+ TRANSCRIPT_ENTRY = st.container()
14
+ RESULTS = st.container()
15
 
16
 
17
  @st.cache_data
 
20
  return df.to_csv().encode('utf-8')
21
 
22
 
23
+ def mode_change_callback():
24
+ if st.session_state.mode == tiger.RUN_MODES['all']:
25
+ st.session_state.check_off_targets = False
26
+ st.session_state.disable_off_target_checkbox = True
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  else:
28
+ st.session_state.disable_off_target_checkbox = False
29
+
30
+
31
+ def entry_method_change_callback():
32
+ if st.session_state.entry_method == ENTRY_METHODS['manual']:
33
+ st.session_state.manual_entry_disabled = False
34
+ st.session_state.fasta_entry_disabled = True
35
+ elif st.session_state.entry_method == ENTRY_METHODS['fasta']:
36
+ st.session_state.manual_entry_disabled = True
37
+ st.session_state.fasta_entry_disabled = False
38
+
39
+
40
+ def process_input():
41
+
42
+ # initialize transcript DataFrame
43
+ st.session_state.transcripts = pd.DataFrame()
44
+
45
+ # manual entry
46
+ if st.session_state.entry_method == ENTRY_METHODS['manual']:
47
+ sequence = st.session_state.manual_entry
48
+ if len(sequence) < tiger.TARGET_LEN:
49
+ with TRANSCRIPT_ENTRY:
50
+ st.write('Transcript must be at least {:d} bases.'.format(tiger.TARGET_LEN))
51
+ else:
52
+ st.session_state.transcripts = pd.DataFrame({tiger.ID_COL: ['ManualEntry'], tiger.SEQ_COL: [sequence]})
53
+
54
+ # fasta file upload
55
+ elif st.session_state.entry_method == ENTRY_METHODS['fasta']:
56
+ if st.session_state.fasta_entry is not None:
57
+ fasta_path = st.session_state.fasta_entry.name
58
+ with open(fasta_path, 'w') as f:
59
+ f.write(st.session_state.fasta_entry.getvalue().decode('utf-8'))
60
+ df = tiger.load_transcripts([fasta_path], enforce_unique_ids=False)
61
+ if df.index.has_duplicates:
62
+ with TRANSCRIPT_ENTRY:
63
+ st.write("Duplicate transcript ID's detected in fasta file")
64
+ else:
65
+ st.session_state.transcripts = df
66
+
67
+ # TODO: convert to upper and check for ACGT only
68
+ print(st.session_state.transcripts)
69
+
70
+
71
+ if __name__ == '__main__':
72
+
73
+ # app initialization
74
+ if 'mode' not in st.session_state:
75
+ st.session_state.mode = tiger.RUN_MODES['all']
76
+ st.session_state.disable_off_target_checkbox = True
77
+ if 'entry_method' not in st.session_state:
78
+ st.session_state.entry_method = ENTRY_METHODS['manual']
79
+ st.session_state.manual_entry_disabled = False
80
+ st.session_state.fasta_entry_disabled = True
81
+
82
+ # title and documentation
83
+ with DOCUMENTATION:
84
+ st.title('TIGER Cas13 Efficacy Prediction')
85
+
86
+ # mode selection
87
+ with MODE_SELECTION:
88
+ col1, col2 = st.columns([0.65, 0.35])
89
+ with col1:
90
+ st.radio(
91
+ label='What do you want to predict?',
92
+ options=tuple(tiger.RUN_MODES.values()),
93
+ key='mode',
94
+ on_change=mode_change_callback
95
+ )
96
+ with col2:
97
+ st.checkbox(
98
+ label='Find off-target effects (slow)',
99
+ key='check_off_targets',
100
+ disabled=st.session_state.disable_off_target_checkbox
101
+ )
102
+
103
+ # transcript entry
104
+ with TRANSCRIPT_ENTRY:
105
+ st.selectbox(
106
+ label='How would you like to provide transcripts of interest?',
107
+ options=ENTRY_METHODS.values(),
108
+ key='entry_method',
109
+ on_change=entry_method_change_callback
110
+ )
111
+ st.text_input(
112
+ label='Enter a target transcript:',
113
+ key='manual_entry',
114
+ placeholder='Upper or lower case',
115
+ disabled=st.session_state.manual_entry_disabled
116
+ )
117
+ st.file_uploader(
118
+ label='Upload a fasta file:',
119
+ key='fasta_entry',
120
+ disabled=st.session_state.fasta_entry_disabled
121
+ )
122
+ run = st.button(label='Get predictions!', on_click=process_input)
123
+
124
+ # with RESULTS:
125
+ # if run:
126
+ # on_target, off_target = tiger.tiger_exhibit(
127
+ # transcripts=st.session_state.transcripts,
128
+ # mode=st.session_state.mode,
129
+ # status=st.empty(),
130
+ # progress_bar=st.progress(0),
131
+ # check_off_targets=st.session_state.check_off_targets
132
+ # )
133
+
134
+ # # input-specific configuration
135
+ # if manual_mode:
136
+ # src_seq = st.session_state['manual_seq']
137
+ # status_text = manual_entry.empty()
138
+ # status_bar = manual_entry.progress(0)
139
+ # elif fasta_mode:
140
+ # src_seq = st.session_state['fasta_seq']
141
+ # status_text = fasta_form.empty()
142
+ # status_bar = fasta_form.progress(0)
143
+ # else:
144
+ # src_seq = status_bar = status_text = None
145
+ #
146
+ # # valid input
147
+ # if src_seq and all([True if nt.upper() in NUCLEOTIDE_TOKENS.keys() else False for nt in src_seq]):
148
+ # on_target, off_target = tiger_exhibit(pd.DataFrame(dict(id=['ManualEntry'], seq=[src_seq])),
149
+ # status_bar, status_text, check_off_targets=option == 'On and Off Target')
150
+ # on_target.rename(columns={'Guide': '23 nt guide sequence'}, inplace=True)
151
+ # if len(on_target) > 0:
152
+ # if on_target.iloc[0]['On-target ID'] == 0:
153
+ # on_target.drop(['On-target ID'], axis=1, inplace=True)
154
+ # st.write('On-target predictions: ', on_target)
155
+ # st.download_button(label='Download', data=convert_df(on_target), file_name='on_target.csv', mime='text/csv')
156
+ # if option == 'On and Off Target' and len(off_target) > 0:
157
+ # off_target.rename(columns={'Guide': '23 nt guide sequence'}, inplace=True)
158
+ # st.write('Off-target predictions: ', off_target)
159
+ # st.download_button(label='Download', data=convert_df(off_target), file_name='off_target.csv', mime='text/csv')
160
+ # elif option == 'On and Off Target' and len(off_target) == 0:
161
+ # st.write('We did not find any off-target effects!')
162
+ #
163
+ # # invalid input
164
+ # elif src_seq is not None:
165
+ # st.write('Invalid input!')