Update app.py
Browse files
app.py
CHANGED
@@ -54,17 +54,14 @@ def apply_custom_styling():
|
|
54 |
html, body, [class*="st-"] {
|
55 |
font-family: 'Roboto', sans-serif;
|
56 |
}
|
57 |
-
|
58 |
.stApp {
|
59 |
background-color: rgb(28, 28, 28);
|
60 |
color: white;
|
61 |
}
|
62 |
-
|
63 |
/* Tab styles */
|
64 |
.stTabs [data-baseweb="tab-list"] {
|
65 |
gap: 24px;
|
66 |
}
|
67 |
-
|
68 |
.stTabs [data-baseweb="tab"] {
|
69 |
height: 50px;
|
70 |
white-space: pre-wrap;
|
@@ -79,7 +76,6 @@ def apply_custom_styling():
|
|
79 |
background: #222;
|
80 |
color: #FFF;
|
81 |
}
|
82 |
-
|
83 |
.stTabs [aria-selected="true"] {
|
84 |
border-bottom: 2px solid #00A0FF; /* Highlight color for active tab */
|
85 |
color: #FFF;
|
@@ -96,7 +92,6 @@ def apply_custom_styling():
|
|
96 |
color: #FFF;
|
97 |
background-color: #00A0FF;
|
98 |
}
|
99 |
-
|
100 |
</style>
|
101 |
""",
|
102 |
unsafe_allow_html=True
|
@@ -258,8 +253,8 @@ def plot_properties_dashboard(df: pd.DataFrame):
|
|
258 |
colors = ['#00D4AA', '#FF6B6B'] # Teal for drug-like, coral for non-drug-like
|
259 |
color_mapper = factor_cmap('Category', palette=colors, factors=["Drug-Like", "Non-Drug-Like"])
|
260 |
|
261 |
-
# Enhanced hover tooltip
|
262 |
-
|
263 |
("Compound", "@Molecule"),
|
264 |
("MW", "@MW{0.0} Da"),
|
265 |
("LogP", "@LogP{0.00}"),
|
@@ -269,10 +264,10 @@ def plot_properties_dashboard(df: pd.DataFrame):
|
|
269 |
("Category", "@Category")
|
270 |
])
|
271 |
|
272 |
-
# Common plot configuration - responsive plots with
|
273 |
plot_config = {
|
274 |
-
'tools': [hover, 'pan,wheel_zoom,box_zoom,reset,save'],
|
275 |
'sizing_mode': 'scale_width',
|
|
|
276 |
'background_fill_color': None,
|
277 |
'border_fill_color': None,
|
278 |
'outline_line_color': '#333333',
|
@@ -313,7 +308,7 @@ def plot_properties_dashboard(df: pd.DataFrame):
|
|
313 |
return p
|
314 |
|
315 |
# Plot 1: MW vs LogP with Lipinski guidelines
|
316 |
-
p1 = figure(title="Molecular Weight vs LogP", **plot_config)
|
317 |
p1.scatter('MW', 'LogP', source=source, legend_group='Category',
|
318 |
color=color_mapper, size=12, alpha=0.8, line_color='white', line_width=0.5)
|
319 |
|
@@ -326,7 +321,7 @@ def plot_properties_dashboard(df: pd.DataFrame):
|
|
326 |
style_plot(p1, "Molecular Weight (Da)", "LogP", "Lipinski Rule: MW vs LogP")
|
327 |
|
328 |
# Plot 2: HBD vs HBA
|
329 |
-
p2 = figure(title="Hydrogen Bonding Profile", **plot_config)
|
330 |
p2.scatter('HBD', 'HBA', source=source, legend_group='Category',
|
331 |
color=color_mapper, size=12, alpha=0.8, line_color='white', line_width=0.5)
|
332 |
|
@@ -338,9 +333,8 @@ def plot_properties_dashboard(df: pd.DataFrame):
|
|
338 |
|
339 |
style_plot(p2, "Hydrogen Bond Donors", "Hydrogen Bond Acceptors", "Lipinski Rule: Hydrogen Bonding")
|
340 |
|
341 |
-
# --- MODIFICATION ---
|
342 |
# Plot 3: TPSA vs Rotatable Bonds with guidelines
|
343 |
-
p3 = figure(title="Molecular Flexibility & Polarity", **plot_config)
|
344 |
p3.scatter('TPSA', 'RotBonds', source=source, legend_group='Category',
|
345 |
color=color_mapper, size=12, alpha=0.8, line_color='white', line_width=0.5)
|
346 |
|
@@ -353,8 +347,11 @@ def plot_properties_dashboard(df: pd.DataFrame):
|
|
353 |
style_plot(p3, "Topological Polar Surface Area (Ų)", "Rotatable Bonds", "Drug Permeability Indicators")
|
354 |
|
355 |
# Plot 4: Enhanced Donut Chart
|
|
|
|
|
356 |
p4_config = plot_config.copy()
|
357 |
-
p4_config
|
|
|
358 |
p4 = figure(title="Drug-Likeness Distribution", **p4_config)
|
359 |
|
360 |
# Calculate percentages and create donut chart
|
@@ -363,7 +360,7 @@ def plot_properties_dashboard(df: pd.DataFrame):
|
|
363 |
data = pd.DataFrame({
|
364 |
'category': counts.index,
|
365 |
'value': counts.values,
|
366 |
-
'percentage': (counts.values / total * 100)
|
367 |
'angle': counts.values / total * 2 * pi,
|
368 |
'color': [colors[0] if cat == 'Drug-Like' else colors[1] for cat in counts.index]
|
369 |
})
|
@@ -380,7 +377,7 @@ def plot_properties_dashboard(df: pd.DataFrame):
|
|
380 |
donut_source = ColumnDataSource(data)
|
381 |
|
382 |
# Create donut using annular wedges (outer ring) - sized to fit within boundaries
|
383 |
-
p4.annular_wedge(x=0, y=0, inner_radius=0.25, outer_radius=0.45,
|
384 |
start_angle='start_angle', end_angle='end_angle',
|
385 |
line_color="white", line_width=3, fill_color='color',
|
386 |
legend_field='category', source=donut_source)
|
@@ -403,10 +400,17 @@ def plot_properties_dashboard(df: pd.DataFrame):
|
|
403 |
text_align="center", text_baseline="middle",
|
404 |
text_color="white", text_font_size="14pt", text_font_style="bold")
|
405 |
|
406 |
-
#
|
407 |
-
|
408 |
-
|
409 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
410 |
|
411 |
style_plot(p4, "", "", "Compound Classification")
|
412 |
p4.axis.visible = False
|
|
|
54 |
html, body, [class*="st-"] {
|
55 |
font-family: 'Roboto', sans-serif;
|
56 |
}
|
|
|
57 |
.stApp {
|
58 |
background-color: rgb(28, 28, 28);
|
59 |
color: white;
|
60 |
}
|
|
|
61 |
/* Tab styles */
|
62 |
.stTabs [data-baseweb="tab-list"] {
|
63 |
gap: 24px;
|
64 |
}
|
|
|
65 |
.stTabs [data-baseweb="tab"] {
|
66 |
height: 50px;
|
67 |
white-space: pre-wrap;
|
|
|
76 |
background: #222;
|
77 |
color: #FFF;
|
78 |
}
|
|
|
79 |
.stTabs [aria-selected="true"] {
|
80 |
border-bottom: 2px solid #00A0FF; /* Highlight color for active tab */
|
81 |
color: #FFF;
|
|
|
92 |
color: #FFF;
|
93 |
background-color: #00A0FF;
|
94 |
}
|
|
|
95 |
</style>
|
96 |
""",
|
97 |
unsafe_allow_html=True
|
|
|
253 |
colors = ['#00D4AA', '#FF6B6B'] # Teal for drug-like, coral for non-drug-like
|
254 |
color_mapper = factor_cmap('Category', palette=colors, factors=["Drug-Like", "Non-Drug-Like"])
|
255 |
|
256 |
+
# Enhanced hover tooltip for scatter plots
|
257 |
+
scatter_hover = HoverTool(tooltips=[
|
258 |
("Compound", "@Molecule"),
|
259 |
("MW", "@MW{0.0} Da"),
|
260 |
("LogP", "@LogP{0.00}"),
|
|
|
264 |
("Category", "@Category")
|
265 |
])
|
266 |
|
267 |
+
# Common plot configuration - responsive plots with a 1:1 aspect ratio
|
268 |
plot_config = {
|
|
|
269 |
'sizing_mode': 'scale_width',
|
270 |
+
'aspect_ratio': 1, # Enforce a square aspect ratio for the data area
|
271 |
'background_fill_color': None,
|
272 |
'border_fill_color': None,
|
273 |
'outline_line_color': '#333333',
|
|
|
308 |
return p
|
309 |
|
310 |
# Plot 1: MW vs LogP with Lipinski guidelines
|
311 |
+
p1 = figure(title="Molecular Weight vs LogP", tools=[scatter_hover, 'pan,wheel_zoom,box_zoom,reset,save'], **plot_config)
|
312 |
p1.scatter('MW', 'LogP', source=source, legend_group='Category',
|
313 |
color=color_mapper, size=12, alpha=0.8, line_color='white', line_width=0.5)
|
314 |
|
|
|
321 |
style_plot(p1, "Molecular Weight (Da)", "LogP", "Lipinski Rule: MW vs LogP")
|
322 |
|
323 |
# Plot 2: HBD vs HBA
|
324 |
+
p2 = figure(title="Hydrogen Bonding Profile", tools=[scatter_hover, 'pan,wheel_zoom,box_zoom,reset,save'], **plot_config)
|
325 |
p2.scatter('HBD', 'HBA', source=source, legend_group='Category',
|
326 |
color=color_mapper, size=12, alpha=0.8, line_color='white', line_width=0.5)
|
327 |
|
|
|
333 |
|
334 |
style_plot(p2, "Hydrogen Bond Donors", "Hydrogen Bond Acceptors", "Lipinski Rule: Hydrogen Bonding")
|
335 |
|
|
|
336 |
# Plot 3: TPSA vs Rotatable Bonds with guidelines
|
337 |
+
p3 = figure(title="Molecular Flexibility & Polarity", tools=[scatter_hover, 'pan,wheel_zoom,box_zoom,reset,save'], **plot_config)
|
338 |
p3.scatter('TPSA', 'RotBonds', source=source, legend_group='Category',
|
339 |
color=color_mapper, size=12, alpha=0.8, line_color='white', line_width=0.5)
|
340 |
|
|
|
347 |
style_plot(p3, "Topological Polar Surface Area (Ų)", "Rotatable Bonds", "Drug Permeability Indicators")
|
348 |
|
349 |
# Plot 4: Enhanced Donut Chart
|
350 |
+
# --- MODIFICATION ---
|
351 |
+
# Configure donut plot separately as it doesn't need all scatter tools
|
352 |
p4_config = plot_config.copy()
|
353 |
+
p4_config['tools'] = "hover" # Only need hover for the donut
|
354 |
+
p4_config.update({'x_range': (-1.0, 1.0), 'y_range': (-1.0, 1.0)})
|
355 |
p4 = figure(title="Drug-Likeness Distribution", **p4_config)
|
356 |
|
357 |
# Calculate percentages and create donut chart
|
|
|
360 |
data = pd.DataFrame({
|
361 |
'category': counts.index,
|
362 |
'value': counts.values,
|
363 |
+
'percentage': (counts.values / total * 100), # Keep full precision for hover
|
364 |
'angle': counts.values / total * 2 * pi,
|
365 |
'color': [colors[0] if cat == 'Drug-Like' else colors[1] for cat in counts.index]
|
366 |
})
|
|
|
377 |
donut_source = ColumnDataSource(data)
|
378 |
|
379 |
# Create donut using annular wedges (outer ring) - sized to fit within boundaries
|
380 |
+
wedge_renderer = p4.annular_wedge(x=0, y=0, inner_radius=0.25, outer_radius=0.45,
|
381 |
start_angle='start_angle', end_angle='end_angle',
|
382 |
line_color="white", line_width=3, fill_color='color',
|
383 |
legend_field='category', source=donut_source)
|
|
|
400 |
text_align="center", text_baseline="middle",
|
401 |
text_color="white", text_font_size="14pt", text_font_style="bold")
|
402 |
|
403 |
+
# --- MODIFICATION ---
|
404 |
+
# Custom hover for donut with detailed info
|
405 |
+
donut_hover = HoverTool(
|
406 |
+
tooltips=[
|
407 |
+
("Category", "@category"),
|
408 |
+
("Count", "@value"),
|
409 |
+
("Percentage", "@percentage{0.1f}%")
|
410 |
+
],
|
411 |
+
renderers=[wedge_renderer] # Attach hover tool specifically to the wedge glyph
|
412 |
+
)
|
413 |
+
p4.add_tools(donut_hover)
|
414 |
|
415 |
style_plot(p4, "", "", "Compound Classification")
|
416 |
p4.axis.visible = False
|