euler314 commited on
Commit
aeff02a
·
verified ·
1 Parent(s): f90829b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +387 -275
app.py CHANGED
@@ -8,20 +8,62 @@ from PIL import Image
8
  import time
9
  import io
10
 
11
- # Set page config
12
  st.set_page_config(
13
- page_title="Eigenvalue Analysis",
14
  page_icon="📊",
15
- layout="wide"
 
16
  )
17
 
18
- # Title and description
19
- st.title("Eigenvalue Analysis Visualization")
20
  st.markdown("""
21
- This application visualizes eigenvalue analysis for matrices with specific properties.
22
- Adjust the parameters below to generate a plot showing the relationship between empirical
23
- and theoretical eigenvalues.
24
- """)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
 
26
  # Create output directory in the current working directory
27
  current_dir = os.getcwd()
@@ -32,287 +74,357 @@ os.makedirs(output_dir, exist_ok=True)
32
  cpp_file = os.path.join(current_dir, "app.cpp")
33
  executable = os.path.join(current_dir, "eigen_analysis")
34
 
35
- # Check if cpp file exists
36
- if not os.path.exists(cpp_file):
37
- st.error(f"C++ source file not found at: {cpp_file}")
38
- st.stop()
39
 
40
- # Compile the C++ code with the right OpenCV libraries
41
- try:
42
- st.info("Compiling C++ code...")
43
- compile_commands = [
44
- f"g++ -o {executable} {cpp_file} `pkg-config --cflags --libs opencv4` -std=c++11",
45
- f"g++ -o {executable} {cpp_file} `pkg-config --cflags --libs opencv` -std=c++11",
46
- f"g++ -o {executable} {cpp_file} -I/usr/include/opencv4 -lopencv_core -lopencv_imgproc -std=c++11"
47
- ]
48
-
49
- compiled = False
50
- for cmd in compile_commands:
51
- compile_result = subprocess.run(
52
- cmd,
53
- shell=True,
54
- capture_output=True,
55
- text=True
56
- )
57
-
58
- if compile_result.returncode == 0:
59
- compiled = True
60
- break
61
 
62
- if not compiled:
63
- st.error("All compilation attempts failed. Please check the system requirements.")
 
64
  st.stop()
65
 
66
- # Make sure the executable is executable
67
- os.chmod(executable, 0o755)
68
- st.success("C++ code compiled successfully")
69
-
70
- except Exception as e:
71
- st.error(f"Error during compilation: {str(e)}")
72
- st.stop()
73
-
74
- # Input parameters sidebar
75
- st.sidebar.header("Parameters")
76
-
77
- # Parameter inputs with defaults and validation
78
- n = st.sidebar.number_input("Sample size (n)", min_value=5, max_value=100000, value=100, step=5, help="Number of samples")
79
- p = st.sidebar.number_input("Dimension (p)", min_value=5, max_value=1000000, value=50, step=5, help="Dimensionality")
80
- a = st.sidebar.number_input("Value for a", min_value=1.1, max_value=10.0, value=2.0, step=0.1, help="Parameter a > 1")
81
-
82
- # Automatically calculate y = p/n (as requested)
83
- y = p/n
84
- st.sidebar.text(f"Value for y = p/n: {y:.4f}")
85
-
86
- # Add fineness control
87
- st.sidebar.subheader("Calculation Controls")
88
- fineness = st.sidebar.slider(
89
- "Beta points",
90
- min_value=20,
91
- max_value=500,
92
- value=100,
93
- step=10,
94
- help="Number of points to calculate along the β axis (0 to 1)"
95
- )
96
-
97
- # Add controls for theoretical calculation precision
98
- theory_grid_points = st.sidebar.slider(
99
- "Theoretical grid points",
100
- min_value=100,
101
- max_value=1000,
102
- value=200,
103
- step=50,
104
- help="Number of points in initial grid search for theoretical calculations"
105
- )
106
-
107
- theory_tolerance = st.sidebar.number_input(
108
- "Theoretical tolerance",
109
- min_value=1e-12,
110
- max_value=1e-6,
111
- value=1e-10,
112
- format="%.1e",
113
- help="Convergence tolerance for golden section search"
114
- )
115
-
116
- # Generate button
117
- if st.sidebar.button("Generate Plot", type="primary"):
118
- # Show progress
119
- progress_bar = st.progress(0)
120
- status_text = st.empty()
121
-
122
- try:
123
- # Run the C++ executable with the parameters in JSON output mode
124
- data_file = os.path.join(output_dir, "eigenvalue_data.json")
125
-
126
- # Delete previous output if exists
127
- if os.path.exists(data_file):
128
- os.remove(data_file)
129
-
130
- # Execute the C++ program
131
- cmd = [
132
- executable,
133
- str(n),
134
- str(p),
135
- str(a),
136
- str(y),
137
- str(fineness),
138
- str(theory_grid_points),
139
- str(theory_tolerance),
140
- data_file
141
- ]
142
-
143
- process = subprocess.Popen(
144
- cmd,
145
- stdout=subprocess.PIPE,
146
- stderr=subprocess.PIPE,
147
- text=True
148
- )
149
-
150
- # Show output in a status area
151
- status_text.text("Starting calculations...")
152
-
153
- last_progress = 0
154
- while process.poll() is None:
155
- output = process.stdout.readline()
156
- if output:
157
- if output.startswith("PROGRESS:"):
158
- try:
159
- # Update progress bar
160
- progress_value = float(output.split(":")[1].strip())
161
- progress_bar.progress(progress_value)
162
- last_progress = progress_value
163
- status_text.text(f"Calculating... {int(progress_value * 100)}% complete")
164
- except:
165
- pass
166
- else:
167
- status_text.text(output.strip())
168
- time.sleep(0.1)
169
-
170
- return_code = process.poll()
171
-
172
- if return_code != 0:
173
- error = process.stderr.read()
174
- st.error(f"Error executing the analysis: {error}")
175
- else:
176
- progress_bar.progress(1.0)
177
- status_text.text("Calculations complete! Generating plot...")
178
-
179
- # Load the results from the JSON file
180
- with open(data_file, 'r') as f:
181
- data = json.load(f)
182
-
183
- # Create a better plot with matplotlib
184
- beta_values = np.array(data['beta_values'])
185
- max_eigenvalues = np.array(data['max_eigenvalues'])
186
- min_eigenvalues = np.array(data['min_eigenvalues'])
187
- theoretical_max = np.array(data['theoretical_max'])
188
- theoretical_min = np.array(data['theoretical_min'])
189
-
190
- # Create the plot
191
- fig, ax = plt.subplots(figsize=(12, 9), dpi=100)
192
-
193
- # Set the background color
194
- fig.patch.set_facecolor('#f5f5f5')
195
- ax.set_facecolor('#f0f0f0')
196
-
197
- # Plot the data
198
- ax.plot(beta_values, max_eigenvalues, 'r-', linewidth=2,
199
- label='Empirical Max Eigenvalue', marker='o', markevery=len(beta_values)//20)
200
- ax.plot(beta_values, min_eigenvalues, 'b-', linewidth=2,
201
- label='Empirical Min Eigenvalue', marker='o', markevery=len(beta_values)//20)
202
- ax.plot(beta_values, theoretical_max, 'g-', linewidth=2,
203
- label='Theoretical Max Function', marker='D', markevery=len(beta_values)//20)
204
- ax.plot(beta_values, theoretical_min, 'm-', linewidth=2,
205
- label='Theoretical Min Function', marker='D', markevery=len(beta_values)//20)
206
-
207
- # Add grid
208
- ax.grid(True, linestyle='--', alpha=0.7)
209
 
210
- # Set labels and title
211
- ax.set_xlabel('β', fontsize=14)
212
- ax.set_ylabel('Eigenvalues', fontsize=14)
213
- ax.set_title(f'Eigenvalue Analysis: n={n}, p={p}, a={a}, y={y:.4f}', fontsize=16)
214
-
215
- # Add legend
216
- ax.legend(loc='best', fontsize=12, framealpha=0.9)
217
-
218
- # Add formulas as text
219
- formula_text1 = r"Max Function: $\max_{k \in (0,\infty)} \frac{y\beta(a-1)k + (ak+1)((y-1)k-1)}{(ak+1)(k^2+k)}$"
220
- formula_text2 = r"Min Function: $\min_{t \in (-1/a,0)} \frac{y\beta(a-1)t + (at+1)((y-1)t-1)}{(at+1)(t^2+t)}$"
221
-
222
- plt.figtext(0.02, 0.02, formula_text1, fontsize=10, color='green')
223
- plt.figtext(0.55, 0.02, formula_text2, fontsize=10, color='purple')
224
-
225
- # Adjust layout
226
- plt.tight_layout(rect=[0, 0.05, 1, 0.95])
227
-
228
- # Save the plot to a buffer
229
- buf = io.BytesIO()
230
- plt.savefig(buf, format='png', dpi=100)
231
- buf.seek(0)
232
-
233
- # Save to file
234
- output_file = os.path.join(output_dir, "eigenvalue_analysis.png")
235
- plt.savefig(output_file, format='png', dpi=100)
236
- plt.close()
237
-
238
- # Display the image in Streamlit
239
- status_text.success("Analysis completed successfully!")
240
- st.image(buf, use_column_width=True)
241
-
242
- # Provide download button
243
- with open(output_file, "rb") as file:
244
- btn = st.download_button(
245
- label="Download Plot",
246
- data=file,
247
- file_name=f"eigenvalue_analysis_n{n}_p{p}_a{a}_y{y:.4f}.png",
248
- mime="image/png"
249
  )
 
 
 
 
250
 
251
- # Add some statistics
252
- st.subheader("Statistical Summary")
253
- col1, col2 = st.columns(2)
254
 
255
- with col1:
256
- st.write("### Maximum Eigenvalues")
257
- st.write(f"Empirical Max: {max(max_eigenvalues):.6f}")
258
- st.write(f"Theoretical Max: {max(theoretical_max):.6f}")
259
- st.write(f"Difference: {abs(max(max_eigenvalues) - max(theoretical_max)):.6f}")
260
-
261
- with col2:
262
- st.write("### Minimum Eigenvalues")
263
- st.write(f"Empirical Min: {min(min_eigenvalues):.6f}")
264
- st.write(f"Theoretical Min: {min(theoretical_min):.6f}")
265
- st.write(f"Difference: {abs(min(min_eigenvalues) - min(theoretical_min)):.6f}")
266
-
267
- # Display calculation settings
268
- with st.expander("Calculation Settings"):
269
- st.write(f"Beta points: {fineness}")
270
- st.write(f"Theoretical grid points: {theory_grid_points}")
271
- st.write(f"Theoretical tolerance: {theory_tolerance:.1e}")
272
-
273
- except Exception as e:
274
- st.error(f"An error occurred: {str(e)}")
275
-
276
- # Show example plot on startup or previous results
277
- example_file = os.path.join(output_dir, "eigenvalue_analysis.png")
278
- if os.path.exists(example_file):
279
- # Show the most recent plot by default
280
- st.subheader("Current Plot")
281
- img = Image.open(example_file)
282
- st.image(img, use_column_width=True)
283
- else:
284
- st.info("👈 Set parameters and click 'Generate Plot' to create a visualization.")
285
-
286
- # Add information about the analysis
287
- with st.expander("About Eigenvalue Analysis"):
288
- st.markdown("""
289
- ## Theory
290
 
291
- This application visualizes the relationship between empirical and theoretical eigenvalues for matrices with specific properties.
 
 
 
 
292
 
293
- The analysis examines:
 
 
294
 
295
- - **Empirical Max/Min Eigenvalues**: The maximum and minimum eigenvalues calculated from the generated matrices
296
- - **Theoretical Max/Min Functions**: The theoretical bounds derived from mathematical analysis
 
 
 
 
 
 
 
297
 
298
- ### Key Parameters
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
299
 
300
- - **n**: Sample size
301
- - **p**: Dimension
302
- - **a**: Value > 1 that affects the distribution of eigenvalues
303
- - **y**: Value calculated as p/n that affects scaling
304
 
305
- ### Calculation Controls
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
306
 
307
- - **Beta points**: Number of points calculated along the β range (0 to 1)
308
- - **Theoretical grid points**: Number of points in initial grid search for finding theoretical max/min
309
- - **Theoretical tolerance**: Convergence tolerance for golden section search algorithm
310
 
311
- ### Mathematical Formulas
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
312
 
313
- Max Function:
314
- max{k (0,∞)} [yβ(a-1)k + (ak+1)((y-1)k-1)]/[(ak+1)(k²+k)]
 
 
 
 
 
 
 
 
315
 
316
- Min Function:
317
- min{t ∈ (-1/a,0)} [yβ(a-1)t + (at+1)((y-1)t-1)]/[(at+1)(t²+t)]
318
- """)
 
8
  import time
9
  import io
10
 
11
+ # Set page config with wider layout
12
  st.set_page_config(
13
+ page_title="Eigenvalue Analysis Dashboard",
14
  page_icon="📊",
15
+ layout="wide",
16
+ initial_sidebar_state="expanded"
17
  )
18
 
19
+ # Apply custom CSS for a dashboard-like appearance
 
20
  st.markdown("""
21
+ <style>
22
+ .main-header {
23
+ font-size: 2.5rem;
24
+ color: #1E88E5;
25
+ text-align: center;
26
+ margin-bottom: 1rem;
27
+ padding-bottom: 1rem;
28
+ border-bottom: 2px solid #f0f0f0;
29
+ }
30
+ .dashboard-container {
31
+ background-color: #f9f9f9;
32
+ padding: 1.5rem;
33
+ border-radius: 10px;
34
+ box-shadow: 0 2px 5px rgba(0,0,0,0.1);
35
+ margin-bottom: 1.5rem;
36
+ }
37
+ .panel-header {
38
+ font-size: 1.3rem;
39
+ font-weight: bold;
40
+ margin-bottom: 1rem;
41
+ color: #424242;
42
+ border-left: 4px solid #1E88E5;
43
+ padding-left: 10px;
44
+ }
45
+ .stats-card {
46
+ background-color: white;
47
+ padding: 1rem;
48
+ border-radius: 8px;
49
+ box-shadow: 0 1px 3px rgba(0,0,0,0.1);
50
+ text-align: center;
51
+ }
52
+ .stats-value {
53
+ font-size: 1.8rem;
54
+ font-weight: bold;
55
+ color: #1E88E5;
56
+ }
57
+ .stats-label {
58
+ font-size: 0.9rem;
59
+ color: #616161;
60
+ margin-top: 0.3rem;
61
+ }
62
+ </style>
63
+ """, unsafe_allow_html=True)
64
+
65
+ # Dashboard Header
66
+ st.markdown('<h1 class="main-header">Eigenvalue Analysis Dashboard</h1>', unsafe_allow_html=True)
67
 
68
  # Create output directory in the current working directory
69
  current_dir = os.getcwd()
 
74
  cpp_file = os.path.join(current_dir, "app.cpp")
75
  executable = os.path.join(current_dir, "eigen_analysis")
76
 
77
+ # Two-column layout for the dashboard
78
+ left_column, right_column = st.columns([1, 3])
 
 
79
 
80
+ with left_column:
81
+ st.markdown('<div class="dashboard-container">', unsafe_allow_html=True)
82
+ st.markdown('<div class="panel-header">Control Panel</div>', unsafe_allow_html=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83
 
84
+ # Check if cpp file exists and compile if necessary
85
+ if not os.path.exists(cpp_file):
86
+ st.error(f"C++ source file not found at: {cpp_file}")
87
  st.stop()
88
 
89
+ # Compile the C++ code with the right OpenCV libraries
90
+ if not os.path.exists(executable) or st.button("Recompile C++ Code"):
91
+ with st.spinner("Compiling C++ code..."):
92
+ compile_commands = [
93
+ f"g++ -o {executable} {cpp_file} `pkg-config --cflags --libs opencv4` -std=c++11",
94
+ f"g++ -o {executable} {cpp_file} `pkg-config --cflags --libs opencv` -std=c++11",
95
+ f"g++ -o {executable} {cpp_file} -I/usr/include/opencv4 -lopencv_core -lopencv_imgproc -std=c++11"
96
+ ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97
 
98
+ compiled = False
99
+ for cmd in compile_commands:
100
+ compile_result = subprocess.run(
101
+ cmd,
102
+ shell=True,
103
+ capture_output=True,
104
+ text=True
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
105
  )
106
+
107
+ if compile_result.returncode == 0:
108
+ compiled = True
109
+ break
110
 
111
+ if not compiled:
112
+ st.error("All compilation attempts failed. Please check the system requirements.")
113
+ st.stop()
114
 
115
+ # Make sure the executable is executable
116
+ os.chmod(executable, 0o755)
117
+ st.success("C++ code compiled successfully")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
118
 
119
+ # Parameter inputs with defaults and validation
120
+ st.markdown("### Matrix Parameters")
121
+ n = st.number_input("Sample size (n)", min_value=5, max_value=1000, value=100, step=5, help="Number of samples")
122
+ p = st.number_input("Dimension (p)", min_value=5, max_value=1000, value=50, step=5, help="Dimensionality")
123
+ a = st.number_input("Value for a", min_value=1.1, max_value=10.0, value=2.0, step=0.1, help="Parameter a > 1")
124
 
125
+ # Automatically calculate y = p/n (as requested)
126
+ y = p/n
127
+ st.info(f"Value for y = p/n: {y:.4f}")
128
 
129
+ st.markdown("### Calculation Controls")
130
+ fineness = st.slider(
131
+ "Beta points",
132
+ min_value=20,
133
+ max_value=500,
134
+ value=100,
135
+ step=10,
136
+ help="Number of points to calculate along the β axis (0 to 1)"
137
+ )
138
 
139
+ with st.expander("Advanced Settings"):
140
+ # Add controls for theoretical calculation precision
141
+ theory_grid_points = st.slider(
142
+ "Theoretical grid points",
143
+ min_value=100,
144
+ max_value=1000,
145
+ value=200,
146
+ step=50,
147
+ help="Number of points in initial grid search for theoretical calculations"
148
+ )
149
+
150
+ theory_tolerance = st.number_input(
151
+ "Theoretical tolerance",
152
+ min_value=1e-12,
153
+ max_value=1e-6,
154
+ value=1e-10,
155
+ format="%.1e",
156
+ help="Convergence tolerance for golden section search"
157
+ )
158
 
159
+ # Generate button
160
+ generate_button = st.button("Generate Analysis", type="primary", use_container_width=True)
161
+ st.markdown('</div>', unsafe_allow_html=True)
 
162
 
163
+ # About section
164
+ with st.expander("About Eigenvalue Analysis"):
165
+ st.markdown("""
166
+ ## Theory
167
+
168
+ This application visualizes the relationship between empirical and theoretical eigenvalues for matrices with specific properties.
169
+
170
+ The analysis examines:
171
+
172
+ - **Empirical Max/Min Eigenvalues**: The maximum and minimum eigenvalues calculated from the generated matrices
173
+ - **Theoretical Max/Min Functions**: The theoretical bounds derived from mathematical analysis
174
+
175
+ ### Key Parameters
176
+
177
+ - **n**: Sample size
178
+ - **p**: Dimension
179
+ - **a**: Value > 1 that affects the distribution of eigenvalues
180
+ - **y**: Value calculated as p/n that affects scaling
181
+
182
+ ### Calculation Controls
183
+
184
+ - **Beta points**: Number of points calculated along the β range (0 to 1)
185
+ - **Theoretical grid points**: Number of points in initial grid search for finding theoretical max/min
186
+ - **Theoretical tolerance**: Convergence tolerance for golden section search algorithm
187
+
188
+ ### Mathematical Formulas
189
+
190
+ Max Function:
191
+ max{k ∈ (0,∞)} [yβ(a-1)k + (ak+1)((y-1)k-1)]/[(ak+1)(k²+k)]
192
+
193
+ Min Function:
194
+ min{t ∈ (-1/a,0)} [yβ(a-1)t + (at+1)((y-1)t-1)]/[(at+1)(t²+t)]
195
+ """)
196
+
197
+ with right_column:
198
+ # Main visualization area
199
+ st.markdown('<div class="dashboard-container">', unsafe_allow_html=True)
200
+ st.markdown('<div class="panel-header">Eigenvalue Analysis Visualization</div>', unsafe_allow_html=True)
201
 
202
+ # Container for the analysis results
203
+ results_container = st.container()
 
204
 
205
+ # Process when generate button is clicked
206
+ if generate_button:
207
+ with results_container:
208
+ # Show progress
209
+ progress_container = st.container()
210
+ with progress_container:
211
+ progress_bar = st.progress(0)
212
+ status_text = st.empty()
213
+
214
+ try:
215
+ # Run the C++ executable with the parameters in JSON output mode
216
+ data_file = os.path.join(output_dir, "eigenvalue_data.json")
217
+
218
+ # Delete previous output if exists
219
+ if os.path.exists(data_file):
220
+ os.remove(data_file)
221
+
222
+ # Execute the C++ program
223
+ cmd = [
224
+ executable,
225
+ str(n),
226
+ str(p),
227
+ str(a),
228
+ str(y),
229
+ str(fineness),
230
+ str(theory_grid_points),
231
+ str(theory_tolerance),
232
+ data_file
233
+ ]
234
+
235
+ process = subprocess.Popen(
236
+ cmd,
237
+ stdout=subprocess.PIPE,
238
+ stderr=subprocess.PIPE,
239
+ text=True
240
+ )
241
+
242
+ # Show output in a status area
243
+ status_text.text("Starting calculations...")
244
+
245
+ last_progress = 0
246
+ while process.poll() is None:
247
+ output = process.stdout.readline()
248
+ if output:
249
+ if output.startswith("PROGRESS:"):
250
+ try:
251
+ # Update progress bar
252
+ progress_value = float(output.split(":")[1].strip())
253
+ progress_bar.progress(progress_value)
254
+ last_progress = progress_value
255
+ status_text.text(f"Calculating... {int(progress_value * 100)}% complete")
256
+ except:
257
+ pass
258
+ else:
259
+ status_text.text(output.strip())
260
+ time.sleep(0.1)
261
+
262
+ return_code = process.poll()
263
+
264
+ if return_code != 0:
265
+ error = process.stderr.read()
266
+ st.error(f"Error executing the analysis: {error}")
267
+ else:
268
+ progress_bar.progress(1.0)
269
+ status_text.text("Calculations complete! Generating visualization...")
270
+
271
+ # Load the results from the JSON file
272
+ with open(data_file, 'r') as f:
273
+ data = json.load(f)
274
+
275
+ # Extract data
276
+ beta_values = np.array(data['beta_values'])
277
+ max_eigenvalues = np.array(data['max_eigenvalues'])
278
+ min_eigenvalues = np.array(data['min_eigenvalues'])
279
+ theoretical_max = np.array(data['theoretical_max'])
280
+ theoretical_min = np.array(data['theoretical_min'])
281
+
282
+ # Create the plot
283
+ fig, ax = plt.subplots(figsize=(12, 8), dpi=100)
284
+
285
+ # Set the background color
286
+ fig.patch.set_facecolor('#f9f9f9')
287
+ ax.set_facecolor('#f0f0f0')
288
+
289
+ # Plot the data with improved styling
290
+ ax.plot(beta_values, max_eigenvalues, 'r-', linewidth=2.5,
291
+ label='Empirical Max Eigenvalue', marker='o', markevery=len(beta_values)//20, markersize=6)
292
+ ax.plot(beta_values, min_eigenvalues, 'b-', linewidth=2.5,
293
+ label='Empirical Min Eigenvalue', marker='o', markevery=len(beta_values)//20, markersize=6)
294
+ ax.plot(beta_values, theoretical_max, 'g-', linewidth=2.5,
295
+ label='Theoretical Max Function', marker='D', markevery=len(beta_values)//20, markersize=6)
296
+ ax.plot(beta_values, theoretical_min, 'm-', linewidth=2.5,
297
+ label='Theoretical Min Function', marker='D', markevery=len(beta_values)//20, markersize=6)
298
+
299
+ # Add grid
300
+ ax.grid(True, linestyle='--', alpha=0.7)
301
+
302
+ # Set labels and title with better formatting
303
+ ax.set_xlabel('β Parameter', fontsize=14, fontweight='bold')
304
+ ax.set_ylabel('Eigenvalues', fontsize=14, fontweight='bold')
305
+ ax.set_title(f'Eigenvalue Analysis: n={n}, p={p}, a={a}, y={y:.4f}',
306
+ fontsize=16, fontweight='bold', pad=15)
307
+
308
+ # Add legend with improved styling
309
+ legend = ax.legend(loc='best', fontsize=12, framealpha=0.9,
310
+ fancybox=True, shadow=True, borderpad=1)
311
+
312
+ # Add formulas as text with better styling
313
+ formula_text1 = r"Max Function: $\max_{k \in (0,\infty)} \frac{y\beta(a-1)k + (ak+1)((y-1)k-1)}{(ak+1)(k^2+k)}$"
314
+ formula_text2 = r"Min Function: $\min_{t \in (-1/a,0)} \frac{y\beta(a-1)t + (at+1)((y-1)t-1)}{(at+1)(t^2+t)}$"
315
+
316
+ plt.figtext(0.02, 0.02, formula_text1, fontsize=10, color='green',
317
+ bbox=dict(facecolor='white', alpha=0.8, edgecolor='green', boxstyle='round,pad=0.5'))
318
+ plt.figtext(0.55, 0.02, formula_text2, fontsize=10, color='purple',
319
+ bbox=dict(facecolor='white', alpha=0.8, edgecolor='purple', boxstyle='round,pad=0.5'))
320
+
321
+ # Adjust layout
322
+ plt.tight_layout(rect=[0, 0.05, 1, 0.95])
323
+
324
+ # Save the plot to a buffer
325
+ buf = io.BytesIO()
326
+ plt.savefig(buf, format='png', dpi=100)
327
+ buf.seek(0)
328
+
329
+ # Save to file
330
+ output_file = os.path.join(output_dir, "eigenvalue_analysis.png")
331
+ plt.savefig(output_file, format='png', dpi=100)
332
+ plt.close()
333
+
334
+ # Clear progress container
335
+ progress_container.empty()
336
+
337
+ # Display the image in Streamlit (with fixed deprecated parameter)
338
+ st.image(buf, use_container_width=True)
339
+
340
+ # Provide download button
341
+ col1, col2, col3 = st.columns([1, 2, 1])
342
+ with col2:
343
+ with open(output_file, "rb") as file:
344
+ btn = st.download_button(
345
+ label="Download Plot",
346
+ data=file,
347
+ file_name=f"eigenvalue_analysis_n{n}_p{p}_a{a}_y{y:.4f}.png",
348
+ mime="image/png",
349
+ use_container_width=True
350
+ )
351
+
352
+ # Add statistics section with cards
353
+ st.markdown("### Results Summary")
354
+
355
+ # Calculate key statistics
356
+ emp_max = max(max_eigenvalues)
357
+ emp_min = min(min_eigenvalues)
358
+ theo_max = max(theoretical_max)
359
+ theo_min = min(theoretical_min)
360
+ max_diff = abs(emp_max - theo_max)
361
+ min_diff = abs(emp_min - theo_min)
362
+
363
+ # Display statistics in a card layout
364
+ col1, col2, col3, col4 = st.columns(4)
365
+
366
+ with col1:
367
+ st.markdown('<div class="stats-card">', unsafe_allow_html=True)
368
+ st.markdown(f'<div class="stats-value">{emp_max:.4f}</div>', unsafe_allow_html=True)
369
+ st.markdown('<div class="stats-label">Empirical Maximum</div>', unsafe_allow_html=True)
370
+ st.markdown('</div>', unsafe_allow_html=True)
371
+
372
+ with col2:
373
+ st.markdown('<div class="stats-card">', unsafe_allow_html=True)
374
+ st.markdown(f'<div class="stats-value">{emp_min:.4f}</div>', unsafe_allow_html=True)
375
+ st.markdown('<div class="stats-label">Empirical Minimum</div>', unsafe_allow_html=True)
376
+ st.markdown('</div>', unsafe_allow_html=True)
377
+
378
+ with col3:
379
+ st.markdown('<div class="stats-card">', unsafe_allow_html=True)
380
+ st.markdown(f'<div class="stats-value">{theo_max:.4f}</div>', unsafe_allow_html=True)
381
+ st.markdown('<div class="stats-label">Theoretical Maximum</div>', unsafe_allow_html=True)
382
+ st.markdown('</div>', unsafe_allow_html=True)
383
+
384
+ with col4:
385
+ st.markdown('<div class="stats-card">', unsafe_allow_html=True)
386
+ st.markdown(f'<div class="stats-value">{theo_min:.4f}</div>', unsafe_allow_html=True)
387
+ st.markdown('<div class="stats-label">Theoretical Minimum</div>', unsafe_allow_html=True)
388
+ st.markdown('</div>', unsafe_allow_html=True)
389
+
390
+ st.markdown("<br>", unsafe_allow_html=True)
391
+
392
+ col1, col2 = st.columns(2)
393
+ with col1:
394
+ st.markdown('<div class="stats-card">', unsafe_allow_html=True)
395
+ st.markdown(f'<div class="stats-value">{max_diff:.4f}</div>', unsafe_allow_html=True)
396
+ st.markdown('<div class="stats-label">Max Difference</div>', unsafe_allow_html=True)
397
+ st.markdown('</div>', unsafe_allow_html=True)
398
+
399
+ with col2:
400
+ st.markdown('<div class="stats-card">', unsafe_allow_html=True)
401
+ st.markdown(f'<div class="stats-value">{min_diff:.4f}</div>', unsafe_allow_html=True)
402
+ st.markdown('<div class="stats-label">Min Difference</div>', unsafe_allow_html=True)
403
+ st.markdown('</div>', unsafe_allow_html=True)
404
+
405
+ # Add calculation settings
406
+ with st.expander("Calculation Details"):
407
+ st.markdown(f"""
408
+ - **Matrix Dimensions**: {n} × {p}
409
+ - **Parameter a**: {a}
410
+ - **Parameter y (p/n)**: {y:.4f}
411
+ - **Beta points**: {fineness}
412
+ - **Theoretical grid points**: {theory_grid_points}
413
+ - **Theoretical tolerance**: {theory_tolerance:.1e}
414
+ """)
415
+
416
+ except Exception as e:
417
+ st.error(f"An error occurred: {str(e)}")
418
 
419
+ else:
420
+ # Check for existing results
421
+ example_file = os.path.join(output_dir, "eigenvalue_analysis.png")
422
+ if os.path.exists(example_file):
423
+ # Show the most recent plot by default
424
+ st.image(example_file, use_container_width=True)
425
+ st.info("This is the most recent analysis result. Adjust parameters and click 'Generate Analysis' to create a new visualization.")
426
+ else:
427
+ # Show placeholder
428
+ st.info("👈 Set parameters and click 'Generate Analysis' to create a visualization.")
429
 
430
+ st.markdown('</div>', unsafe_allow_html=True)