Spaces:
Sleeping
Sleeping
Update src/streamlit_app.py
Browse files- src/streamlit_app.py +74 -51
src/streamlit_app.py
CHANGED
|
@@ -1,6 +1,8 @@
|
|
| 1 |
import streamlit as st
|
| 2 |
import numpy as np
|
| 3 |
import matplotlib.pyplot as plt
|
|
|
|
|
|
|
| 4 |
from kinematics_visualizer import Motion1D, Motion2D, KinematicsVisualizer
|
| 5 |
|
| 6 |
# Configure Streamlit page
|
|
@@ -475,14 +477,15 @@ def show_2d_motion():
|
|
| 475 |
st.pyplot(fig_comp)
|
| 476 |
plt.close()
|
| 477 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 478 |
def show_motion_comparison():
|
| 479 |
st.markdown('<div class="section-header">π Compare Different Trajectories</div>', unsafe_allow_html=True)
|
| 480 |
|
| 481 |
st.markdown("**Compare up to 3 different projectile motions side by side**")
|
| 482 |
|
| 483 |
-
# Clear any existing matplotlib figures to prevent cross-tab contamination
|
| 484 |
-
plt.close('all')
|
| 485 |
-
|
| 486 |
# Use container to isolate this section
|
| 487 |
with st.container():
|
| 488 |
# Use columns instead of tabs to avoid tab-related flickering
|
|
@@ -506,47 +509,76 @@ def show_motion_comparison():
|
|
| 506 |
angle3 = st.slider("Angle 3", 0.0, 90.0, 60.0, key="comp_angle3")
|
| 507 |
height3 = st.slider("Height 3", 0.0, 30.0, 5.0, key="comp_height3")
|
| 508 |
|
| 509 |
-
# Single plot and table section
|
| 510 |
st.markdown("---")
|
| 511 |
|
| 512 |
-
# Create comparison plot
|
| 513 |
-
@st.cache_data
|
| 514 |
-
def
|
| 515 |
-
|
| 516 |
-
|
| 517 |
-
|
| 518 |
-
|
| 519 |
-
trajectories_cached = [
|
| 520 |
-
("Trajectory 1", Motion2D(launch_speed=speed1, launch_angle=angle1, launch_height=height1), 'blue'),
|
| 521 |
-
("Trajectory 2", Motion2D(launch_speed=speed2, launch_angle=angle2, launch_height=height2), 'red'),
|
| 522 |
-
("Trajectory 3", Motion2D(launch_speed=speed3, launch_angle=angle3, launch_height=height3), 'green')
|
| 523 |
]
|
| 524 |
|
| 525 |
-
fig
|
| 526 |
|
| 527 |
-
|
| 528 |
-
for name, motion, color in trajectories_cached:
|
| 529 |
data = motion.trajectory_data(motion.calculate_flight_time())
|
| 530 |
-
ax.plot(data['x'], data['y'], linewidth=3, label=name, color=color)
|
| 531 |
|
| 532 |
-
#
|
| 533 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 534 |
if len(data['x']) > 0:
|
| 535 |
-
|
| 536 |
-
|
| 537 |
-
|
| 538 |
-
|
| 539 |
-
|
| 540 |
-
|
| 541 |
-
|
| 542 |
-
|
| 543 |
-
|
| 544 |
-
|
| 545 |
-
|
| 546 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 547 |
|
| 548 |
# Create cached comparison data
|
| 549 |
-
@st.cache_data
|
| 550 |
def create_comparison_data(speed1, angle1, height1, speed2, angle2, height2, speed3, angle3, height3):
|
| 551 |
trajectories_data = [
|
| 552 |
("Trajectory 1", Motion2D(launch_speed=speed1, launch_angle=angle1, launch_height=height1)),
|
|
@@ -569,23 +601,14 @@ def show_motion_comparison():
|
|
| 569 |
|
| 570 |
return comparison_data
|
| 571 |
|
| 572 |
-
#
|
| 573 |
-
|
| 574 |
-
|
| 575 |
-
|
| 576 |
-
|
| 577 |
-
|
| 578 |
-
|
| 579 |
-
|
| 580 |
-
st.error(f"Error creating plot: {e}")
|
| 581 |
-
|
| 582 |
-
# Display cached comparison table
|
| 583 |
-
st.markdown("### π Trajectory Comparison Table")
|
| 584 |
-
try:
|
| 585 |
-
comparison_data = create_comparison_data(speed1, angle1, height1, speed2, angle2, height2, speed3, angle3, height3)
|
| 586 |
-
st.table(comparison_data)
|
| 587 |
-
except Exception as e:
|
| 588 |
-
st.error(f"Error creating table: {e}")
|
| 589 |
|
| 590 |
if __name__ == "__main__":
|
| 591 |
main()
|
|
|
|
| 1 |
import streamlit as st
|
| 2 |
import numpy as np
|
| 3 |
import matplotlib.pyplot as plt
|
| 4 |
+
import plotly.graph_objects as go
|
| 5 |
+
import plotly.express as px
|
| 6 |
from kinematics_visualizer import Motion1D, Motion2D, KinematicsVisualizer
|
| 7 |
|
| 8 |
# Configure Streamlit page
|
|
|
|
| 477 |
st.pyplot(fig_comp)
|
| 478 |
plt.close()
|
| 479 |
|
| 480 |
+
# Add this import at the top
|
| 481 |
+
import plotly.graph_objects as go
|
| 482 |
+
import plotly.express as px
|
| 483 |
+
|
| 484 |
def show_motion_comparison():
|
| 485 |
st.markdown('<div class="section-header">π Compare Different Trajectories</div>', unsafe_allow_html=True)
|
| 486 |
|
| 487 |
st.markdown("**Compare up to 3 different projectile motions side by side**")
|
| 488 |
|
|
|
|
|
|
|
|
|
|
| 489 |
# Use container to isolate this section
|
| 490 |
with st.container():
|
| 491 |
# Use columns instead of tabs to avoid tab-related flickering
|
|
|
|
| 509 |
angle3 = st.slider("Angle 3", 0.0, 90.0, 60.0, key="comp_angle3")
|
| 510 |
height3 = st.slider("Height 3", 0.0, 30.0, 5.0, key="comp_height3")
|
| 511 |
|
| 512 |
+
# Single plot and table section
|
| 513 |
st.markdown("---")
|
| 514 |
|
| 515 |
+
# Create Plotly comparison plot
|
| 516 |
+
@st.cache_data
|
| 517 |
+
def create_plotly_comparison(speed1, angle1, height1, speed2, angle2, height2, speed3, angle3, height3):
|
| 518 |
+
trajectories_data = [
|
| 519 |
+
("Trajectory 1", Motion2D(launch_speed=speed1, launch_angle=angle1, launch_height=height1), "blue"),
|
| 520 |
+
("Trajectory 2", Motion2D(launch_speed=speed2, launch_angle=angle2, launch_height=height2), "red"),
|
| 521 |
+
("Trajectory 3", Motion2D(launch_speed=speed3, launch_angle=angle3, launch_height=height3), "green")
|
|
|
|
|
|
|
|
|
|
|
|
|
| 522 |
]
|
| 523 |
|
| 524 |
+
fig = go.Figure()
|
| 525 |
|
| 526 |
+
for name, motion, color in trajectories_data:
|
|
|
|
| 527 |
data = motion.trajectory_data(motion.calculate_flight_time())
|
|
|
|
| 528 |
|
| 529 |
+
# Add trajectory line
|
| 530 |
+
fig.add_trace(go.Scatter(
|
| 531 |
+
x=data['x'],
|
| 532 |
+
y=data['y'],
|
| 533 |
+
mode='lines',
|
| 534 |
+
name=name,
|
| 535 |
+
line=dict(color=color, width=3),
|
| 536 |
+
hovertemplate=f'<b>{name}</b><br>X: %{{x:.1f}} m<br>Y: %{{y:.1f}} m<extra></extra>'
|
| 537 |
+
))
|
| 538 |
+
|
| 539 |
+
# Add launch point
|
| 540 |
+
fig.add_trace(go.Scatter(
|
| 541 |
+
x=[motion.launch_x],
|
| 542 |
+
y=[motion.launch_height],
|
| 543 |
+
mode='markers',
|
| 544 |
+
name=f'{name} Launch',
|
| 545 |
+
marker=dict(color=color, size=10, symbol='circle'),
|
| 546 |
+
showlegend=False,
|
| 547 |
+
hovertemplate=f'<b>{name} Launch</b><br>X: %{{x:.1f}} m<br>Y: %{{y:.1f}} m<extra></extra>'
|
| 548 |
+
))
|
| 549 |
+
|
| 550 |
+
# Add landing point
|
| 551 |
if len(data['x']) > 0:
|
| 552 |
+
fig.add_trace(go.Scatter(
|
| 553 |
+
x=[data['x'][-1]],
|
| 554 |
+
y=[data['y'][-1]],
|
| 555 |
+
mode='markers',
|
| 556 |
+
name=f'{name} Landing',
|
| 557 |
+
marker=dict(color=color, size=10, symbol='square'),
|
| 558 |
+
showlegend=False,
|
| 559 |
+
hovertemplate=f'<b>{name} Landing</b><br>X: %{{x:.1f}} m<br>Y: %{{y:.1f}} m<extra></extra>'
|
| 560 |
+
))
|
| 561 |
+
|
| 562 |
+
# Update layout
|
| 563 |
+
fig.update_layout(
|
| 564 |
+
title=dict(text="Trajectory Comparison", font=dict(size=18, color="black")),
|
| 565 |
+
xaxis_title="Horizontal Position (m)",
|
| 566 |
+
yaxis_title="Vertical Position (m)",
|
| 567 |
+
showlegend=True,
|
| 568 |
+
hovermode='closest',
|
| 569 |
+
template='plotly_white',
|
| 570 |
+
height=600,
|
| 571 |
+
margin=dict(l=50, r=50, t=80, b=50)
|
| 572 |
+
)
|
| 573 |
+
|
| 574 |
+
# Set axis ranges
|
| 575 |
+
fig.update_xaxes(range=[0, None])
|
| 576 |
+
fig.update_yaxes(range=[0, None])
|
| 577 |
+
|
| 578 |
+
return fig, trajectories_data
|
| 579 |
|
| 580 |
# Create cached comparison data
|
| 581 |
+
@st.cache_data
|
| 582 |
def create_comparison_data(speed1, angle1, height1, speed2, angle2, height2, speed3, angle3, height3):
|
| 583 |
trajectories_data = [
|
| 584 |
("Trajectory 1", Motion2D(launch_speed=speed1, launch_angle=angle1, launch_height=height1)),
|
|
|
|
| 601 |
|
| 602 |
return comparison_data
|
| 603 |
|
| 604 |
+
# Display Plotly chart (no flickering, no memory issues)
|
| 605 |
+
fig, _ = create_plotly_comparison(speed1, angle1, height1, speed2, angle2, height2, speed3, angle3, height3)
|
| 606 |
+
st.plotly_chart(fig, use_container_width=True)
|
| 607 |
+
|
| 608 |
+
# Display comparison table
|
| 609 |
+
st.markdown("### π Trajectory Comparison Table")
|
| 610 |
+
comparison_data = create_comparison_data(speed1, angle1, height1, speed2, angle2, height2, speed3, angle3, height3)
|
| 611 |
+
st.table(comparison_data)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 612 |
|
| 613 |
if __name__ == "__main__":
|
| 614 |
main()
|