-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
313 lines (273 loc) · 15 KB
/
Copy pathmain.py
File metadata and controls
313 lines (273 loc) · 15 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
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
import streamlit as st
import numpy as np
import pandas as pd
from data_processor import DataProcessor
from visualizations import Visualizer
from text_analyzer import TextAnalyzer
from utils import load_data, filter_dataframe
from typing import Dict, Any
st.set_page_config(page_title="Microbiology Articles Dashboard", layout="wide")
# Initialize session state
if 'data' not in st.session_state:
st.session_state.data = None
if 'processor' not in st.session_state:
st.session_state.processor = None
def create_visualization(func, data, error_message):
"""Wrapper function for creating visualizations with error handling"""
try:
return func(data)
except Exception as e:
st.error(f"{error_message}: {str(e)}")
return None
def main():
st.title("Microbiology Articles Dashboard")
# File uploader
uploaded_file = st.file_uploader("Upload Excel file containing article data", type=['xlsx', 'xls'])
if uploaded_file is not None:
try:
if st.session_state.data is None:
# Load and process data
df = load_data(uploaded_file)
if df.empty:
st.warning("Uploaded file contains no data / Загруженный файл не содержит данных")
return
st.session_state.data = df
st.session_state.processor = DataProcessor(df)
st.session_state.visualizer = Visualizer(df)
st.session_state.text_analyzer = TextAnalyzer(df)
# Initialize filters dictionary and filtered dataframe
filters: Dict[str, Any] = {}
filtered_df = st.session_state.data.copy()
# Sidebar filters
st.sidebar.title("Filters / Фильтры")
# Year filter
years = []
if 'Year' in st.session_state.data.columns:
valid_years = sorted(st.session_state.data['Year'].dropna().unique())
if valid_years:
years = st.sidebar.multiselect("Select Years / Выберите годы", options=valid_years)
if years:
filtered_df = filtered_df[filtered_df['Year'].isin(years)]
# Topic filter
valid_ranks = sorted(st.session_state.data['rank'].dropna().unique())
ranks = st.sidebar.multiselect("Select Topics / Выберите темы", options=valid_ranks)
if ranks:
filtered_df = filtered_df[filtered_df['rank'].isin(ranks)]
# Add numeric range filters
numeric_cols = st.session_state.data.select_dtypes(include=[np.number]).columns
for col in numeric_cols:
if col not in ['Year']: # Skip already handled columns
# Convert to numeric and handle NaN values
valid_values = pd.to_numeric(st.session_state.data[col], errors='coerce').dropna()
if not valid_values.empty:
min_val = float(valid_values.min())
max_val = float(valid_values.max())
if min_val != max_val and not (np.isnan(min_val) or np.isnan(max_val)):
st.sidebar.write(f"{col} Range / Диапазон")
range_vals = st.sidebar.slider(
f"Select range for {col}",
min_value=min_val,
max_value=max_val,
value=(min_val, max_val),
key=f'{col}_range'
)
filtered_df = filtered_df[
(filtered_df[col] >= range_vals[0]) &
(filtered_df[col] <= range_vals[1])
]
# Add categorical filters
categorical_cols = st.session_state.data.select_dtypes(include=['object']).columns
for col in categorical_cols:
if col not in ['rank']: # Skip already handled columns
unique_vals = sorted(st.session_state.data[col].dropna().unique())
if len(unique_vals) > 0 and len(unique_vals) <= 50: # Only show if reasonable number of options
selected_vals = st.sidebar.multiselect(
f"Select {col} / Выберите {col}",
options=unique_vals,
key=f'{col}_filter'
)
if selected_vals:
filtered_df = filtered_df[filtered_df[col].isin(selected_vals)]
if filtered_df.empty:
st.warning("No data matches the selected filters / Нет данных, соответствующих выбранным фильтрам")
return
# Semantic Search Section
st.header("Semantic Search / Семантический поиск")
search_query = st.text_input(
"Enter search term / Введите поисковый запрос",
key="semantic_search"
)
if search_query:
# Define searchable columns
text_columns = ['Title', 'article description', 'Results', 'Conclusions']
available_columns = [col for col in text_columns if col in filtered_df.columns]
# Perform search
search_results = st.session_state.text_analyzer.semantic_search(
search_query,
available_columns
)
if 'error' in search_results:
st.error(f"Search error: {search_results['error']}")
else:
# Show total mentions
st.metric(
"Total Mentions / Всего упоминаний",
search_results['total_mentions']
)
# Show mentions distribution
fig_mentions = st.session_state.visualizer.plot_mentions_distribution(search_results)
st.plotly_chart(fig_mentions, use_container_width=True)
# Show detailed results
for column, info in search_results['mentions_by_column'].items():
with st.expander(f"{column} ({info['count']} mentions)"):
for mention in info['mentions']:
st.write("---")
st.write("**Relevance Score:** {:.2f}".format(mention['similarity']))
for key, value in mention['metadata'].items():
st.write(f"**{key}:** {value}")
st.write("**Text:**")
st.write(mention['text'])
# Main content layout
col1, col2 = st.columns(2)
with col1:
st.subheader("Article Distribution by Topic / Распределение статей по темам")
fig_topics = create_visualization(
st.session_state.visualizer.plot_topic_distribution,
filtered_df,
"Error creating topic distribution / Ошибка создания распределения тем"
)
if fig_topics:
st.plotly_chart(fig_topics, use_container_width=True)
with col2:
if 'TRL' in filtered_df.columns:
st.subheader("TRL Distribution / Распределение УГТ")
fig_trl = create_visualization(
st.session_state.visualizer.plot_trl_distribution,
filtered_df,
"Error creating TRL distribution / Ошибка создания распределения УГТ"
)
if fig_trl:
st.plotly_chart(fig_trl, use_container_width=True)
# Advanced Analysis Section
st.header("Advanced Analysis / Расширенный анализ")
# Categorical Data Analysis with Hierarchical Visualization
st.subheader("Categorical Data Analysis / Анализ категориальных данных")
categorical_columns = ['Method', 'Active Agent', 'Environmental Safety', 'Economic Efficiency', 'rank']
# Add sorting options
sort_options = {
'Frequency (High to Low)': 'frequency_desc',
'Frequency (Low to High)': 'frequency_asc',
'Alphabetical (A-Z)': 'alpha_asc',
'Alphabetical (Z-A)': 'alpha_desc'
}
col1, col2 = st.columns([2, 1])
with col1:
selected_categorical = st.multiselect(
"Select categorical variables to analyze / Выберите категориальные переменные для анализа",
[col for col in categorical_columns if col in filtered_df.columns]
)
with col2:
sort_method = st.selectbox(
"Sort by / Сортировать по",
options=list(sort_options.keys()),
index=0
)
if selected_categorical:
for column in selected_categorical:
# Create hierarchical visualization
fig_tree = create_visualization(
lambda df: st.session_state.visualizer.plot_categorical_tree(df, column),
filtered_df,
f"Error analyzing {column} / Ошибка анализа {column}"
)
if fig_tree:
st.plotly_chart(fig_tree, use_container_width=True)
# Text Analysis
st.subheader("Text Analysis / Анализ текста")
text_columns = ['Conclusions', 'Results', 'article description']
selected_text = st.multiselect(
"Select text fields to analyze / Выберите текстовые поля для анализа",
[col for col in text_columns if col in filtered_df.columns]
)
if selected_text:
for column in selected_text:
fig_text = create_visualization(
lambda df: st.session_state.visualizer.plot_text_analysis(df, column),
filtered_df,
f"Error analyzing {column} / Ошибка анализа {column}"
)
if fig_text:
st.plotly_chart(fig_text, use_container_width=True)
# Correlation Analysis
st.subheader("Correlation Analysis / Корреляционный анализ")
numeric_cols = filtered_df.select_dtypes(include=[np.number]).columns.tolist()
if len(numeric_cols) >= 2:
fig_corr = create_visualization(
lambda df: st.session_state.visualizer.plot_correlation_matrix(df, numeric_cols),
filtered_df,
"Error creating correlation matrix / Ошибка создания корреляционной матрицы"
)
if fig_corr:
st.plotly_chart(fig_corr, use_container_width=True)
else:
st.info("Insufficient numerical variables for correlation analysis / "
"Недостаточно числовых переменных для корреляционного анализа")
# Scatter Plot Analysis
st.subheader("Scatter Plot Analysis / Анализ диаграммы рассеяния")
scatter_container = st.container()
with scatter_container:
# Get numerical and categorical columns
numeric_columns = filtered_df.select_dtypes(include=[np.number]).columns.tolist()
categorical_columns = filtered_df.select_dtypes(include=['object']).columns.tolist()
all_columns = numeric_columns + categorical_columns
# Column selection
col1, col2 = st.columns(2)
with col1:
x_column = st.selectbox(
"Select X-axis variable / Выберите переменную оси X",
options=all_columns,
key="scatter_x"
)
with col2:
y_column = st.selectbox(
"Select Y-axis variable / Выберите переменную оси Y",
options=all_columns,
key="scatter_y"
)
# Optional parameters
col1, col2 = st.columns(2)
with col1:
color_column = st.selectbox(
"Color by (optional) / Цвет по (необязательно)",
options=['None'] + categorical_columns,
key="scatter_color"
)
with col2:
size_column = st.selectbox(
"Size by (optional) / Размер по (необязательно)",
options=['None'] + numeric_columns,
key="scatter_size"
)
# Create scatter plot
if x_column and y_column:
fig_scatter = create_visualization(
lambda df: st.session_state.visualizer.plot_scatter(
df,
x_column,
y_column,
None if color_column == 'None' else color_column,
None if size_column == 'None' else size_column
),
filtered_df,
"Error creating scatter plot / Ошибка создания диаграммы рассеяния"
)
if fig_scatter:
st.plotly_chart(fig_scatter, use_container_width=True)
except Exception as e:
st.error(f"Error: {str(e)}")
st.session_state.data = None
else:
st.info("Please upload an Excel file to begin analysis / "
"Пожалуйста, загрузите файл Excel для начала анализа")
if __name__ == "__main__":
main()