NavyDevilDoc commited on
Commit
b6a881b
Β·
verified Β·
1 Parent(s): 2b3a82c

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. 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 with proper isolation
510
  st.markdown("---")
511
 
512
- # Create comparison plot with hash exclusion for Motion2D objects
513
- @st.cache_data(hash_funcs={Motion2D: lambda x: str(x.__dict__)})
514
- def create_comparison_plot(speed1, angle1, height1, speed2, angle2, height2, speed3, angle3, height3):
515
- # Clear any existing figures first
516
- plt.close('all')
517
-
518
- # Recreate trajectories inside cached function
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, ax = plt.subplots(figsize=(12, 8))
526
 
527
- max_range = 0
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
- # Mark launch and landing points
533
- ax.plot(motion.launch_x, motion.launch_height, 'o', markersize=8, color=color, alpha=0.7)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
534
  if len(data['x']) > 0:
535
- ax.plot(data['x'][-1], data['y'][-1], 's', markersize=8, color=color, alpha=0.7)
536
- max_range = max(max_range, data['x'][-1])
537
-
538
- ax.set_xlabel('Horizontal Position (m)', fontsize=12)
539
- ax.set_ylabel('Vertical Position (m)', fontsize=12)
540
- ax.set_title('Trajectory Comparison', fontsize=16, fontweight='bold')
541
- ax.grid(True, alpha=0.3)
542
- ax.legend(fontsize=12)
543
- ax.set_ylim(bottom=0)
544
- ax.set_xlim(0, max_range * 1.1 if max_range > 0 else 10)
545
-
546
- return fig
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
- # Use containers to isolate the display elements
573
- with st.container():
574
- # Display cached plot
575
- try:
576
- fig = create_comparison_plot(speed1, angle1, height1, speed2, angle2, height2, speed3, angle3, height3)
577
- st.pyplot(fig, clear_figure=True)
578
- plt.close(fig) # Immediately close after display
579
- except Exception as e:
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()