Update app.py
Browse files
app.py
CHANGED
@@ -344,167 +344,88 @@ def main():
|
|
344 |
progress_bar.progress(40)
|
345 |
st.subheader("Speech Trajectory Analysis")
|
346 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
347 |
viz_options = st.multiselect(
|
348 |
-
"Select
|
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 |
-
|
360 |
-
sentiment_scores, _ = analyzer.analyze_emotional_trajectory(text) # Unpack the tuple
|
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 |
-
trajectory_fig.update_layout(
|
374 |
-
title='Emotional Flow Throughout the Speech',
|
375 |
-
xaxis_title='Speech Segments',
|
376 |
-
yaxis_title='Emotional Tone',
|
377 |
-
yaxis=dict(
|
378 |
-
ticktext=['Very Negative', 'Negative', 'Neutral', 'Positive', 'Very Positive'],
|
379 |
-
tickvals=[-1, -0.5, 0, 0.5, 1],
|
380 |
-
range=[-1.1, 1.1],
|
381 |
-
gridcolor='lightgray'
|
382 |
-
),
|
383 |
-
hovermode='x unified',
|
384 |
-
showlegend=False,
|
385 |
-
plot_bgcolor='white',
|
386 |
-
height=500
|
387 |
-
)
|
388 |
-
|
389 |
-
trajectory_fig.update_traces(
|
390 |
-
hovertemplate="Segment: %{x}<br>Score: %{y:.2f}<extra></extra>"
|
391 |
-
)
|
392 |
-
|
393 |
-
st.plotly_chart(trajectory_fig, use_container_width=True)
|
394 |
|
395 |
if "Moral Foundations Flow" in viz_options:
|
396 |
-
st.write("### Moral Foundations Flow")
|
397 |
-
moral_trajectories = {
|
398 |
-
'care': [], 'fairness': [], 'loyalty': [],
|
399 |
-
'authority': [], 'sanctity': []
|
400 |
-
}
|
401 |
-
|
402 |
-
for segment in segments:
|
403 |
-
moral_scores = analyzer.analyze_moral_foundations(segment)
|
404 |
-
for foundation in moral_trajectories.keys():
|
405 |
-
moral_trajectories[foundation].append(moral_scores[foundation])
|
406 |
-
|
407 |
-
moral_fig = go.Figure()
|
408 |
colors = px.colors.qualitative.Set3[:5]
|
409 |
-
|
410 |
for idx, (foundation, scores) in enumerate(moral_trajectories.items()):
|
411 |
-
|
412 |
x=segment_labels,
|
413 |
y=scores,
|
414 |
name=MORAL_FOUNDATIONS[foundation],
|
415 |
mode='lines+markers',
|
416 |
line=dict(color=colors[idx], width=2),
|
417 |
-
marker=dict(size=6
|
418 |
))
|
419 |
-
|
420 |
-
moral_fig.update_layout(
|
421 |
-
title='Moral Foundations Flow',
|
422 |
-
xaxis_title='Speech Segments',
|
423 |
-
yaxis_title='Foundation Strength',
|
424 |
-
yaxis=dict(range=[0, 1]),
|
425 |
-
hovermode='x unified',
|
426 |
-
plot_bgcolor='white',
|
427 |
-
showlegend=True,
|
428 |
-
height=500,
|
429 |
-
legend=dict(
|
430 |
-
orientation="h",
|
431 |
-
yanchor="bottom",
|
432 |
-
y=1.02,
|
433 |
-
xanchor="right",
|
434 |
-
x=1
|
435 |
-
)
|
436 |
-
)
|
437 |
-
|
438 |
-
moral_fig.update_traces(
|
439 |
-
hovertemplate="Segment: %{x}<br>Strength: %{y:.2f}<extra></extra>"
|
440 |
-
)
|
441 |
-
|
442 |
-
st.plotly_chart(moral_fig, use_container_width=True)
|
443 |
-
|
444 |
if "Basic Emotions Flow" in viz_options:
|
445 |
-
st.write("### Basic Emotions Flow")
|
446 |
-
emotions = []
|
447 |
-
for segment in segments:
|
448 |
-
try:
|
449 |
-
result = analyzer.emotion_classifier(segment[:512])[0]
|
450 |
-
emotions.append(result['label'])
|
451 |
-
except:
|
452 |
-
emotions.append('neutral')
|
453 |
-
|
454 |
emotions_df = pd.DataFrame({
|
455 |
'Segment': segment_labels,
|
456 |
-
'Emotion':
|
457 |
})
|
458 |
-
|
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 |
-
hovertemplate="Segment: %{x}<br>Emotion: %{y}<extra></extra>"
|
485 |
-
)
|
486 |
-
|
487 |
-
st.plotly_chart(emotions_fig, use_container_width=True)
|
488 |
-
|
489 |
-
# Add download button
|
490 |
-
if viz_options:
|
491 |
-
results_df = pd.DataFrame({
|
492 |
-
'Segment': segment_labels,
|
493 |
-
'Sentiment': sentiment_scores if "Sentiment Flow" in viz_options else None,
|
494 |
-
'Emotion': emotions if "Basic Emotions Flow" in viz_options else None
|
495 |
-
})
|
496 |
-
|
497 |
-
if "Moral Foundations Flow" in viz_options:
|
498 |
-
for foundation, scores in moral_trajectories.items():
|
499 |
-
results_df[f'Moral_{foundation}'] = scores
|
500 |
-
|
501 |
-
csv = results_df.to_csv(index=False)
|
502 |
-
st.download_button(
|
503 |
-
label="Download Analysis Results",
|
504 |
-
data=csv,
|
505 |
-
file_name="speech_analysis_results.csv",
|
506 |
-
mime="text/csv"
|
507 |
-
)
|
508 |
|
509 |
with tab3:
|
510 |
status_text.text('Analyzing Linguistic Features...')
|
|
|
344 |
progress_bar.progress(40)
|
345 |
st.subheader("Speech Trajectory Analysis")
|
346 |
|
347 |
+
# Create consistent segments and get all data upfront
|
348 |
+
segments = analyzer.split_text(text, max_length=512)
|
349 |
+
num_segments = len(segments)
|
350 |
+
segment_labels = [f"{i+1}" for i in range(num_segments)]
|
351 |
+
sentiment_scores, basic_emotions = analyzer.analyze_emotional_trajectory(text)
|
352 |
+
|
353 |
+
# Get moral foundations data
|
354 |
+
moral_trajectories = {
|
355 |
+
'care': [], 'fairness': [], 'loyalty': [],
|
356 |
+
'authority': [], 'sanctity': []
|
357 |
+
}
|
358 |
+
for segment in segments:
|
359 |
+
moral_scores = analyzer.analyze_moral_foundations(segment)
|
360 |
+
for foundation in moral_trajectories.keys():
|
361 |
+
moral_trajectories[foundation].append(moral_scores[foundation])
|
362 |
+
|
363 |
+
# Create unified figure
|
364 |
+
unified_fig = go.Figure()
|
365 |
+
|
366 |
+
# Add traces for each analysis type
|
367 |
viz_options = st.multiselect(
|
368 |
+
"Select analyses to display:",
|
369 |
["Sentiment Flow", "Moral Foundations Flow", "Basic Emotions Flow"],
|
370 |
default=["Sentiment Flow"]
|
371 |
)
|
372 |
|
|
|
|
|
|
|
|
|
|
|
373 |
if "Sentiment Flow" in viz_options:
|
374 |
+
unified_fig.add_trace(go.Scatter(
|
|
|
|
|
|
|
375 |
x=segment_labels,
|
376 |
y=sentiment_scores,
|
377 |
+
name='Sentiment',
|
378 |
mode='lines+markers',
|
379 |
line=dict(color='#1f77b4', width=3),
|
380 |
marker=dict(
|
381 |
+
size=8,
|
382 |
+
color=['#ff4444' if score < -0.3 else '#44ff44' if score > 0.3 else '#888888' for score in sentiment_scores]
|
|
|
383 |
)
|
384 |
+
))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
385 |
|
386 |
if "Moral Foundations Flow" in viz_options:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
387 |
colors = px.colors.qualitative.Set3[:5]
|
|
|
388 |
for idx, (foundation, scores) in enumerate(moral_trajectories.items()):
|
389 |
+
unified_fig.add_trace(go.Scatter(
|
390 |
x=segment_labels,
|
391 |
y=scores,
|
392 |
name=MORAL_FOUNDATIONS[foundation],
|
393 |
mode='lines+markers',
|
394 |
line=dict(color=colors[idx], width=2),
|
395 |
+
marker=dict(size=6)
|
396 |
))
|
397 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
398 |
if "Basic Emotions Flow" in viz_options:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
399 |
emotions_df = pd.DataFrame({
|
400 |
'Segment': segment_labels,
|
401 |
+
'Emotion': basic_emotions
|
402 |
})
|
403 |
+
unified_fig.add_trace(go.Bar(
|
404 |
+
x=segment_labels,
|
405 |
+
y=[1 if e == 'joy' else 0.5 if e == 'neutral' else -0.5 for e in basic_emotions],
|
406 |
+
name='Emotions',
|
407 |
+
marker_color='#2ecc71',
|
408 |
+
opacity=0.6
|
409 |
+
))
|
410 |
+
|
411 |
+
unified_fig.update_layout(
|
412 |
+
title='Speech Analysis Flow',
|
413 |
+
xaxis_title='Speech Segments',
|
414 |
+
yaxis_title='Analysis Values',
|
415 |
+
plot_bgcolor='white',
|
416 |
+
height=600,
|
417 |
+
showlegend=True,
|
418 |
+
legend=dict(
|
419 |
+
orientation="h",
|
420 |
+
yanchor="bottom",
|
421 |
+
y=1.02,
|
422 |
+
xanchor="right",
|
423 |
+
x=1
|
424 |
+
),
|
425 |
+
hovermode='x unified'
|
426 |
+
)
|
427 |
+
|
428 |
+
st.plotly_chart(unified_fig, use_container_width=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
429 |
|
430 |
with tab3:
|
431 |
status_text.text('Analyzing Linguistic Features...')
|