BodduSriPavan111 commited on
Commit
87d2252
Β·
verified Β·
1 Parent(s): ca4b9c6

feat: fully-updated-genome-grid-plot

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +273 -37
src/streamlit_app.py CHANGED
@@ -1,58 +1,294 @@
1
  # Import necessary libraries
2
  import streamlit as st
3
-
4
  from io import StringIO, BytesIO
5
  from Bio import SeqIO
6
-
7
  from kitikiplot.genomics import grid
8
 
 
 
 
 
 
 
 
9
 
10
- st.set_page_config(layout="wide")
11
-
12
- col1, _, col2 = st.columns([18, 2, 80]) # 20% : 80%
13
-
14
- # Column: 1
15
- # Area where user uploads '.fasta' file
16
- with col1:
17
-
18
- data= ""
 
19
 
20
- st.markdown("### Upload your Genome File")
21
- uploaded_file= st.file_uploader("Upload a file (Format: .fasta)")
22
-
23
- if uploaded_file is not None:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
 
25
- data= str(list( SeqIO.parse(StringIO(uploaded_file.getvalue().decode("utf-8")), "fasta") )[0].seq)
 
 
26
 
27
- window_length= st.number_input( key= "window_length", label= "Window/ Chunk Length", min_value= 0, max_value= 200, value= 50)
 
 
 
 
 
 
28
 
29
- submit = st.button("Submit", type="primary")
 
 
 
 
30
 
31
- st.markdown("<div style='margin-top: 30px;'></div>", unsafe_allow_html=True)
32
 
33
- st.image("src/banner.png", use_container_width =True)
 
 
 
 
 
 
34
 
35
- figure= grid.plot( nucleotide_sequence= data, window_length= window_length )
 
36
 
37
- st.markdown("</div>", unsafe_allow_html=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
 
39
- # Column: 2
40
- # Output Area where the kitikiplot is displayed
41
  with col2:
42
- st.markdown("## Genome Grid Plot")
 
43
 
44
- if submit and uploaded_file is not None:
45
 
46
- st.pyplot( figure )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
 
48
- if figure!= None:
49
- img_bytes = BytesIO()
50
- figure.savefig(img_bytes, format="png")
51
- img_bytes.seek(0)
52
 
53
- st.download_button(
54
- label="Download Plot as PNG",
55
- data=img_bytes,
56
- file_name= uploaded_file.name+"GridPlot.png",
57
- mime="image/png"
58
- )
 
 
1
  # Import necessary libraries
2
  import streamlit as st
 
3
  from io import StringIO, BytesIO
4
  from Bio import SeqIO
 
5
  from kitikiplot.genomics import grid
6
 
7
+ # Page configuration
8
+ st.set_page_config(
9
+ page_title="Genome Grid Plot",
10
+ page_icon="🧬",
11
+ layout="wide",
12
+ initial_sidebar_state="collapsed"
13
+ )
14
 
15
+ # Professional styling with blue navigation bar
16
+ st.markdown("""
17
+ <style>
18
+ /* Remove default Streamlit padding and margins */
19
+ .block-container {
20
+ padding-top: 0rem;
21
+ padding-bottom: 0rem;
22
+ padding-left: 1rem;
23
+ padding-right: 1rem;
24
+ }
25
 
26
+ /* Hide Streamlit header and footer */
27
+ header[data-testid="stHeader"] {
28
+ display: none;
29
+ }
30
+
31
+ .main > div {
32
+ padding-top: 0rem;
33
+ }
34
+
35
+ /* Professional navigation bar */
36
+ .nav-bar {
37
+ background: linear-gradient(135deg, #1e3c72 0%, #2a5298 100%);
38
+ padding: 0.05rem 2rem;
39
+ color: white;
40
+ display: flex;
41
+ align-items: center;
42
+ margin: -1rem -1rem 2rem -1rem;
43
+ box-shadow: 0 2px 10px rgba(0,0,0,0.1);
44
+ }
45
+
46
+ .nav-logo {
47
+ height: 40px;
48
+ margin-right: 15px;
49
+ border: 1px solid #9ef2bd;
50
+ border-radius: 2px; /* Optional: smooth corners */
51
+ }
52
+
53
+ .nav-title {
54
+ font-size: 28px;
55
+ font-weight: 600;
56
+ color: white;
57
+ margin: 0;
58
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
59
+ }
60
+
61
+ /* Professional card styling */
62
+ .upload-card {
63
+ background: white;
64
+ border-radius: 12px;
65
+ padding: 2rem;
66
+ box-shadow: 0 4px 20px rgba(0,0,0,0.08);
67
+ border: 1px solid #e8eaed;
68
+ }
69
+
70
+ .plot-card {
71
+ background: white;
72
+ border-radius: 12px;
73
+ padding: 2rem;
74
+ box-shadow: 0 4px 20px rgba(0,0,0,0.08);
75
+ border: 1px solid #e8eaed;
76
+ min-height: 600px;
77
+ }
78
+
79
+ /* Professional button styling */
80
+ .stButton > button {
81
+ background: linear-gradient(135deg, #1e3c72 0%, #2a5298 100%);
82
+ color: white;
83
+ border: none;
84
+ border-radius: 8px;
85
+ padding: 0.75rem 2rem;
86
+ font-weight: 600;
87
+ font-size: 16px;
88
+ transition: all 0.3s ease;
89
+ width: 100%;
90
+ }
91
+
92
+ .stButton > button:hover {
93
+ transform: translateY(-2px);
94
+ box-shadow: 0 6px 20px rgba(30,60,114,0.3);
95
+ }
96
+
97
+ /* Download button styling */
98
+ .stDownloadButton > button {
99
+ background: linear-gradient(135deg, #28a745 0%, #20c997 100%);
100
+ color: white;
101
+ border: none;
102
+ border-radius: 8px;
103
+ padding: 0.75rem 2rem;
104
+ font-weight: 600;
105
+ font-size: 16px;
106
+ transition: all 0.3s ease;
107
+ width: 30%;
108
+ }
109
+
110
+ .stDownloadButton > button:hover {
111
+ transform: translateY(-2px);
112
+ box-shadow: 0 6px 20px rgba(40,167,69,0.3);
113
+ }
114
+
115
+ /* File uploader styling */
116
+ .stFileUploader > div > div {
117
+ border: 2px dashed #2a5298;
118
+ border-radius: 8px;
119
+ padding: 2rem;
120
+ text-align: center;
121
+ background: #f8f9ff;
122
+ }
123
+
124
+ /* Number input styling */
125
+ .stNumberInput > div > div > input {
126
+ border-radius: 8px;
127
+ border: 2px solid #e8eaed;
128
+ padding: 0.75rem;
129
+ font-size: 16px;
130
+ }
131
+
132
+ /* Section headers */
133
+ .section-header {
134
+ color: #1e3c72;
135
+ font-size: 24px;
136
+ font-weight: 600;
137
+ margin-bottom: 1rem;
138
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
139
+ }
140
+
141
+ /* Info text */
142
+ .info-text {
143
+ color: #6c757d;
144
+ font-size: 14px;
145
+ margin-top: 0.5rem;
146
+ }
147
+ </style>
148
+ """, unsafe_allow_html=True)
149
 
150
+ import base64
151
+ with open("logo.png", "rb") as img_file:
152
+ encoded = base64.b64encode(img_file.read()).decode()
153
 
154
+ # Display using HTML
155
+ st.markdown(f"""
156
+ <div class="nav-bar">
157
+ <img src="data:image/png;base64,{encoded}" class="nav-logo" alt="Logo" style="height:40px;">
158
+ <h2 class="nav-title">Genome Grid Plot</h2>
159
+ </div>
160
+ """, unsafe_allow_html=True)
161
 
162
+ # st.markdown("""
163
+ # <div class="nav-bar">
164
+ # <h1 class="nav-title">Genome Grid Plot</h1>
165
+ # </div>
166
+ # """, unsafe_allow_html=True)
167
 
168
+ # st.image("banner.png", width=60)
169
 
170
+ # Initialize session state
171
+ if 'figure' not in st.session_state:
172
+ st.session_state.figure = None
173
+ if 'data' not in st.session_state:
174
+ st.session_state.data = ""
175
+ if 'plot_generated' not in st.session_state:
176
+ st.session_state.plot_generated = False
177
 
178
+ # Main layout
179
+ col1, col2 = st.columns([30, 70])
180
 
181
+ # Column 1: Upload and Controls
182
+ with col1:
183
+ st.markdown('<h3 class="section-header">πŸ“ Upload Genome File</h3>', unsafe_allow_html=True)
184
+
185
+ uploaded_file = st.file_uploader(
186
+ "Choose a FASTA file",
187
+ type=['fasta', 'fa', 'fas'],
188
+ help="Upload your genome sequence in FASTA format"
189
+ )
190
+
191
+ if uploaded_file is not None:
192
+ # Process file
193
+ try:
194
+ data = str(list(SeqIO.parse(StringIO(uploaded_file.getvalue().decode("utf-8")), "fasta"))[0].seq)
195
+ st.session_state.data = data
196
+
197
+ # Show file info
198
+ st.success(f"βœ… Sequence length: {len(data):,} nucleotides")
199
+
200
+ # Window length input
201
+ st.markdown('<h4 class="section-header">βš™οΈ Parameters</h4>', unsafe_allow_html=True)
202
+ window_length = st.number_input(
203
+ label="Window/Chunk Length",
204
+ min_value=1,
205
+ max_value=200,
206
+ value=50,
207
+ key="window_length",
208
+ help="Size of each analysis window for the grid plot"
209
+ )
210
+ st.markdown('<p class="info-text">Recommended: sequence length <1000 for detailed analysis</p>', unsafe_allow_html=True)
211
+
212
+ # Submit button
213
+ submit = st.button("πŸ”¬ Generate Plot", type="primary", key="submit_btn")
214
+
215
+ if submit:
216
+ with st.spinner("🧬 Generating genome grid plot..."):
217
+ st.session_state.figure = grid.plot(
218
+ nucleotide_sequence=data,
219
+ window_length=window_length
220
+ )
221
+ st.session_state.plot_generated = True
222
+
223
+ except Exception as e:
224
+ st.error(f"❌ Error processing file: {str(e)}")
225
+
226
+ else:
227
+ st.info("πŸ‘† Please upload a FASTA file to begin visualization")
228
+
229
+ # Banner image at bottom with error handling
230
+ try:
231
+ st.image("src/banner.png", use_container_width=True)
232
+ except:
233
+ pass # Silently ignore if banner not found
234
+
235
+ st.markdown('</div>', unsafe_allow_html=True)
236
 
237
+ # Column 2: Plot Display
 
238
  with col2:
239
+
240
+ if st.session_state.figure is not None and st.session_state.plot_generated:
241
 
242
+ st.markdown('<h3 class="section-header">Visualization Results</h3>', unsafe_allow_html=True)
243
 
244
+ # Display plot
245
+ st.pyplot(st.session_state.figure, use_container_width=True)
246
+
247
+ # Download section
248
+ st.markdown("---")
249
+
250
+ # Prepare download
251
+ img_bytes = BytesIO()
252
+ st.session_state.figure.savefig(img_bytes, format="png", dpi=300, bbox_inches='tight',
253
+ facecolor='white', edgecolor='none')
254
+ img_bytes.seek(0)
255
+
256
+ # Download button
257
+ filename = uploaded_file.name.replace('.fasta', '').replace('.fa', '').replace('.fas', '') if uploaded_file else "genome"
258
+ st.download_button(
259
+ label="πŸ“₯ Download Plot as PNG",
260
+ data=img_bytes.getvalue(),
261
+ file_name=f"{filename}_GridPlot.png",
262
+ mime="image/png"
263
+ )
264
+
265
+ else:
266
+ # Empty state with instructions
267
+ st.markdown("""
268
+ <div style="text-align: center; padding: 4rem 2rem; color: #343a40; font-family: 'Segoe UI', sans-serif;">
269
+ <h4 style="margin-bottom: 1rem;">🧬 Ready for Analysis <b>?</b></h4>
270
+ <p style="font-size: 1rem;">Upload a FASTA file and click <strong>"Generate Plot"</strong> to visualize your genome sequence.</p>
271
+ <br>
272
+ <div style="background: #ffffff; padding: 2rem; border-radius: 10px; border: 1px solid #e0e0e0; box-shadow: 0 2px 8px rgba(0,0,0,0.05); max-width: 700px; margin: 0 auto;">
273
+ <h5 style="color: #2a5298; font-size: 1.3rem; text-align: left;">About</h5>
274
+ <ul style="text-align: left; padding-left: 1.2rem; margin: 0; line-height: 1.8; color: #495057; font-size: 0.95rem;">
275
+ <li>Visualize nucleotide composition patterns</li>
276
+ <li>Analyze sequence complexity and structure</li>
277
+ <li>Identify repetitive regions and motifs</li>
278
+ <li>Intuitive for genomics research and education</li>
279
+ <li>Powered by <i>kitikiplot</i></li>
280
+ </ul>
281
+ </div>
282
+ </div>
283
+ """, unsafe_allow_html=True)
284
 
285
+
286
+ st.markdown('</div>', unsafe_allow_html=True)
 
 
287
 
288
+ # Footer
289
+ st.markdown("---")
290
+ st.markdown("""
291
+ <div style="text-align: center; color: #2a5298; padding: 0.01rem;">
292
+ <p><strong>Genome Grid Plot</strong> β€’ Intuitive genomics visualization tool β€’ Built with Streamlit</p>
293
+ </div>
294
+ """, unsafe_allow_html=True)