Update app.py
Browse files
app.py
CHANGED
@@ -344,163 +344,148 @@ def main():
|
|
344 |
progress_bar.progress(40)
|
345 |
st.subheader("Speech Trajectory Analysis")
|
346 |
|
347 |
-
compare_mode = st.toggle("Enable Side-by-Side Comparison", value=False)
|
348 |
-
|
349 |
viz_options = st.multiselect(
|
350 |
"Select visualizations to display:",
|
351 |
["Sentiment Flow", "Moral Foundations Flow", "Basic Emotions Flow"],
|
352 |
default=["Sentiment Flow"]
|
353 |
)
|
354 |
|
355 |
-
if len(viz_options) > 1 and compare_mode:
|
356 |
-
cols = st.columns(len(viz_options))
|
357 |
-
else:
|
358 |
-
cols = [st] # Single column mode
|
359 |
-
|
360 |
# Create consistent segments for analyses
|
361 |
segments = analyzer.split_text(text, max_length=512)
|
362 |
num_segments = len(segments)
|
363 |
segment_labels = [f"{i+1}" for i in range(num_segments)]
|
364 |
|
365 |
-
current_col = 0
|
366 |
-
|
367 |
if "Sentiment Flow" in viz_options:
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
)
|
381 |
-
))
|
382 |
-
|
383 |
-
trajectory_fig.update_layout(
|
384 |
-
title='Emotional Flow Throughout the Speech',
|
385 |
-
xaxis_title='Speech Segments',
|
386 |
-
yaxis_title='Emotional Tone',
|
387 |
-
yaxis=dict(
|
388 |
-
ticktext=['Very Negative', 'Negative', 'Neutral', 'Positive', 'Very Positive'],
|
389 |
-
tickvals=[-1, -0.5, 0, 0.5, 1],
|
390 |
-
range=[-1.1, 1.1],
|
391 |
-
gridcolor='lightgray'
|
392 |
-
),
|
393 |
-
hovermode='x unified',
|
394 |
-
showlegend=False,
|
395 |
-
plot_bgcolor='white',
|
396 |
-
height=500
|
397 |
-
)
|
398 |
-
|
399 |
-
trajectory_fig.update_traces(
|
400 |
-
hovertemplate="Segment: %{x}<br>Score: %{y:.2f}<extra></extra>"
|
401 |
)
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
406 |
|
407 |
if "Moral Foundations Flow" in viz_options:
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
)
|
448 |
-
)
|
449 |
-
|
450 |
-
moral_fig.update_traces(
|
451 |
-
hovertemplate="Segment: %{x}<br>Strength: %{y:.2f}<extra></extra>"
|
452 |
)
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
|
|
|
|
|
|
457 |
|
458 |
if "Basic Emotions Flow" in viz_options:
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
)
|
495 |
-
)
|
496 |
-
|
497 |
-
emotions_fig.update_traces(
|
498 |
-
hovertemplate="Segment: %{x}<br>Emotion: %{y}<extra></extra>"
|
499 |
)
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
|
|
|
|
|
|
504 |
|
505 |
# Add download button
|
506 |
if viz_options:
|
|
|
344 |
progress_bar.progress(40)
|
345 |
st.subheader("Speech Trajectory Analysis")
|
346 |
|
|
|
|
|
347 |
viz_options = st.multiselect(
|
348 |
"Select visualizations to display:",
|
349 |
["Sentiment Flow", "Moral Foundations Flow", "Basic Emotions Flow"],
|
350 |
default=["Sentiment Flow"]
|
351 |
)
|
352 |
|
|
|
|
|
|
|
|
|
|
|
353 |
# Create consistent segments for analyses
|
354 |
segments = analyzer.split_text(text, max_length=512)
|
355 |
num_segments = len(segments)
|
356 |
segment_labels = [f"{i+1}" for i in range(num_segments)]
|
357 |
|
|
|
|
|
358 |
if "Sentiment Flow" in viz_options:
|
359 |
+
st.write("### Sentiment Flow")
|
360 |
+
sentiment_scores = analyzer.analyze_emotional_trajectory(text)
|
361 |
+
|
362 |
+
trajectory_fig = go.Figure(data=go.Scatter(
|
363 |
+
x=segment_labels,
|
364 |
+
y=sentiment_scores,
|
365 |
+
mode='lines+markers',
|
366 |
+
line=dict(color='#1f77b4', width=3),
|
367 |
+
marker=dict(
|
368 |
+
size=8,
|
369 |
+
color=['#ff4444' if score < -0.3 else '#44ff44' if score > 0.3 else '#888888' for score in sentiment_scores],
|
370 |
+
symbol='circle'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
371 |
)
|
372 |
+
))
|
373 |
+
|
374 |
+
trajectory_fig.update_layout(
|
375 |
+
title='Emotional Flow Throughout the Speech',
|
376 |
+
xaxis_title='Speech Segments',
|
377 |
+
yaxis_title='Emotional Tone',
|
378 |
+
yaxis=dict(
|
379 |
+
ticktext=['Very Negative', 'Negative', 'Neutral', 'Positive', 'Very Positive'],
|
380 |
+
tickvals=[-1, -0.5, 0, 0.5, 1],
|
381 |
+
range=[-1.1, 1.1],
|
382 |
+
gridcolor='lightgray'
|
383 |
+
),
|
384 |
+
hovermode='x unified',
|
385 |
+
showlegend=False,
|
386 |
+
plot_bgcolor='white',
|
387 |
+
height=500
|
388 |
+
)
|
389 |
+
|
390 |
+
trajectory_fig.update_traces(
|
391 |
+
hovertemplate="Segment: %{x}<br>Score: %{y:.2f}<extra></extra>"
|
392 |
+
)
|
393 |
+
|
394 |
+
st.plotly_chart(trajectory_fig, use_container_width=True)
|
395 |
|
396 |
if "Moral Foundations Flow" in viz_options:
|
397 |
+
st.write("### Moral Foundations Flow")
|
398 |
+
moral_trajectories = {
|
399 |
+
'care': [], 'fairness': [], 'loyalty': [],
|
400 |
+
'authority': [], 'sanctity': []
|
401 |
+
}
|
402 |
+
|
403 |
+
for segment in segments:
|
404 |
+
moral_scores = analyzer.analyze_moral_foundations(segment)
|
405 |
+
for foundation in moral_trajectories.keys():
|
406 |
+
moral_trajectories[foundation].append(moral_scores[foundation])
|
407 |
+
|
408 |
+
moral_fig = go.Figure()
|
409 |
+
colors = px.colors.qualitative.Set3[:5]
|
410 |
+
|
411 |
+
for idx, (foundation, scores) in enumerate(moral_trajectories.items()):
|
412 |
+
moral_fig.add_trace(go.Scatter(
|
413 |
+
x=segment_labels,
|
414 |
+
y=scores,
|
415 |
+
name=MORAL_FOUNDATIONS[foundation],
|
416 |
+
mode='lines+markers',
|
417 |
+
line=dict(color=colors[idx], width=2),
|
418 |
+
marker=dict(size=6, color=colors[idx])
|
419 |
+
))
|
420 |
+
|
421 |
+
moral_fig.update_layout(
|
422 |
+
title='Moral Foundations Flow',
|
423 |
+
xaxis_title='Speech Segments',
|
424 |
+
yaxis_title='Foundation Strength',
|
425 |
+
yaxis=dict(range=[0, 1]),
|
426 |
+
hovermode='x unified',
|
427 |
+
plot_bgcolor='white',
|
428 |
+
showlegend=True,
|
429 |
+
height=500,
|
430 |
+
legend=dict(
|
431 |
+
orientation="h",
|
432 |
+
yanchor="bottom",
|
433 |
+
y=1.02,
|
434 |
+
xanchor="right",
|
435 |
+
x=1
|
|
|
|
|
|
|
|
|
|
|
436 |
)
|
437 |
+
)
|
438 |
+
|
439 |
+
moral_fig.update_traces(
|
440 |
+
hovertemplate="Segment: %{x}<br>Strength: %{y:.2f}<extra></extra>"
|
441 |
+
)
|
442 |
+
|
443 |
+
st.plotly_chart(moral_fig, use_container_width=True)
|
444 |
|
445 |
if "Basic Emotions Flow" in viz_options:
|
446 |
+
st.write("### Basic Emotions Flow")
|
447 |
+
emotions = []
|
448 |
+
for segment in segments:
|
449 |
+
try:
|
450 |
+
result = analyzer.emotion_classifier(segment[:512])[0]
|
451 |
+
emotions.append(result['label'])
|
452 |
+
except:
|
453 |
+
emotions.append('neutral')
|
454 |
+
|
455 |
+
emotions_df = pd.DataFrame({
|
456 |
+
'Segment': segment_labels,
|
457 |
+
'Emotion': emotions
|
458 |
+
})
|
459 |
+
|
460 |
+
emotions_fig = px.bar(
|
461 |
+
emotions_df,
|
462 |
+
x='Segment',
|
463 |
+
y='Emotion',
|
464 |
+
color='Emotion',
|
465 |
+
title='Basic Emotions Flow',
|
466 |
+
color_discrete_sequence=px.colors.qualitative.Set2
|
467 |
+
)
|
468 |
+
|
469 |
+
emotions_fig.update_layout(
|
470 |
+
xaxis_title='Speech Segments',
|
471 |
+
yaxis_title='Emotion',
|
472 |
+
showlegend=True,
|
473 |
+
plot_bgcolor='white',
|
474 |
+
height=500,
|
475 |
+
legend=dict(
|
476 |
+
orientation="h",
|
477 |
+
yanchor="bottom",
|
478 |
+
y=1.02,
|
479 |
+
xanchor="right",
|
480 |
+
x=1
|
|
|
|
|
|
|
|
|
|
|
481 |
)
|
482 |
+
)
|
483 |
+
|
484 |
+
emotions_fig.update_traces(
|
485 |
+
hovertemplate="Segment: %{x}<br>Emotion: %{y}<extra></extra>"
|
486 |
+
)
|
487 |
+
|
488 |
+
st.plotly_chart(emotions_fig, use_container_width=True)
|
489 |
|
490 |
# Add download button
|
491 |
if viz_options:
|