-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathstreamlit_app.py
More file actions
363 lines (315 loc) Β· 13.1 KB
/
streamlit_app.py
File metadata and controls
363 lines (315 loc) Β· 13.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
#!/usr/bin/env python3
"""
QuantumMeter Pro - Streamlit Version
Advanced Laboratory Software for Quantum Measurement Devices
"""
import streamlit as st
import pandas as pd
import numpy as np
import plotly.graph_objects as go
import plotly.express as px
from datetime import datetime, timedelta
import time
import json
from pathlib import Path
# Page configuration
st.set_page_config(
page_title="QuantumMeter Pro",
page_icon="π¬",
layout="wide",
initial_sidebar_state="expanded"
)
# Custom CSS
st.markdown("""
<style>
.main-header {
font-size: 3rem;
font-weight: bold;
color: #1f77b4;
text-align: center;
margin-bottom: 2rem;
}
.metric-card {
background-color: #f0f2f6;
padding: 1rem;
border-radius: 0.5rem;
border-left: 4px solid #1f77b4;
}
.status-connected {
color: #28a745;
font-weight: bold;
}
.status-disconnected {
color: #dc3545;
font-weight: bold;
}
</style>
""", unsafe_allow_html=True)
# Initialize session state
if 'measurement_data' not in st.session_state:
st.session_state.measurement_data = {
'timestamp': [],
'current': [],
'voltage': [],
'resistance': [],
'temperature': []
}
if 'measuring' not in st.session_state:
st.session_state.measuring = False
if 'device_connected' not in st.session_state:
st.session_state.device_connected = False
def load_sample_data():
"""Load sample quantum measurement data"""
sample_file = Path('data/sample_quantum_data.csv')
if sample_file.exists():
df = pd.read_csv(sample_file)
st.session_state.measurement_data = {
'timestamp': [datetime.fromisoformat(ts) for ts in df['timestamp']],
'current': df['current'].tolist(),
'voltage': df['voltage'].tolist(),
'resistance': df['resistance'].tolist(),
'temperature': df['temperature'].tolist()
}
return True
return False
def simulate_quantum_measurement():
"""Simulate quantum measurement data"""
timestamp = datetime.now()
# Generate realistic quantum measurement data
base_current = 1e-9 # 1 nA base current
noise = np.random.normal(0, base_current * 0.01)
current = base_current + noise
voltage = 1.0 + np.random.normal(0, 0.001)
resistance = voltage / current if current != 0 else 1e12
temperature = 23.0 + np.random.normal(0, 0.1)
return {
'timestamp': timestamp,
'current': current,
'voltage': voltage,
'resistance': resistance,
'temperature': temperature
}
def perform_ai_analysis(data):
"""Perform AI analysis on measurement data"""
if not data['current']:
return None
current_array = np.array(data['current'])
voltage_array = np.array(data['voltage'])
# Statistical analysis
current_stats = {
'mean': np.mean(current_array),
'std': np.std(current_array),
'min': np.min(current_array),
'max': np.max(current_array)
}
voltage_stats = {
'mean': np.mean(voltage_array),
'std': np.std(voltage_array),
'min': np.min(voltage_array),
'max': np.max(voltage_array)
}
# Anomaly detection (3-sigma rule)
current_anomalies = np.sum(np.abs(current_array - current_stats['mean']) > 3 * current_stats['std'])
voltage_anomalies = np.sum(np.abs(voltage_array - voltage_stats['mean']) > 3 * voltage_stats['std'])
# Quality score calculation
current_stability = 1 - (current_stats['std'] / current_stats['mean']) if current_stats['mean'] != 0 else 0
voltage_stability = 1 - (voltage_stats['std'] / voltage_stats['mean']) if voltage_stats['mean'] != 0 else 0
quality_score = (current_stability + voltage_stability) / 2
return {
'current': current_stats,
'voltage': voltage_stats,
'anomalies': {
'current_anomalies': int(current_anomalies),
'voltage_anomalies': int(voltage_anomalies)
},
'quality_score': quality_score
}
# Main application
def main():
# Header
st.markdown('<h1 class="main-header">π¬ QuantumMeter Pro</h1>', unsafe_allow_html=True)
st.markdown("**Advanced Laboratory Software for Quantum Measurement Devices**")
# Sidebar
with st.sidebar:
st.header("π§ Device Control")
# Device connection
if st.button("π Connect Device" if not st.session_state.device_connected else "π Disconnect Device"):
st.session_state.device_connected = not st.session_state.device_connected
if st.session_state.device_connected:
st.success("Device connected successfully!")
else:
st.warning("Device disconnected")
# Measurement control
if st.session_state.device_connected:
if st.button("βΆοΈ Start Measurement" if not st.session_state.measuring else "βΉοΈ Stop Measurement"):
st.session_state.measuring = not st.session_state.measuring
# Data management
st.header("π Data Management")
if st.button("π Load Sample Data"):
if load_sample_data():
st.success("Sample data loaded successfully!")
else:
st.error("Sample data file not found")
if st.button("πΎ Export Data"):
if st.session_state.measurement_data['timestamp']:
df = pd.DataFrame(st.session_state.measurement_data)
csv = df.to_csv(index=False)
st.download_button(
label="π₯ Download CSV",
data=csv,
file_name=f"quantum_measurements_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv",
mime="text/csv"
)
# Device status
st.header("π Device Status")
status_color = "status-connected" if st.session_state.device_connected else "status-disconnected"
status_text = "Connected" if st.session_state.device_connected else "Disconnected"
st.markdown(f'<p class="{status_color}">π {status_text}</p>', unsafe_allow_html=True)
if st.session_state.measuring:
st.markdown('<p class="status-connected">π Measuring</p>', unsafe_allow_html=True)
else:
st.markdown('<p class="status-disconnected">βΈοΈ Stopped</p>', unsafe_allow_html=True)
# Main content area
col1, col2, col3, col4 = st.columns(4)
# Real-time metrics
if st.session_state.measurement_data['timestamp']:
latest_idx = -1
with col1:
st.metric(
"Current",
f"{st.session_state.measurement_data['current'][latest_idx]:.2e} A",
f"{(st.session_state.measurement_data['current'][latest_idx] * 1e9):.2f} nA"
)
with col2:
st.metric(
"Voltage",
f"{st.session_state.measurement_data['voltage'][latest_idx]:.6f} V",
f"{(st.session_state.measurement_data['voltage'][latest_idx] * 1e6):.2f} ΞΌV"
)
with col3:
st.metric(
"Resistance",
f"{st.session_state.measurement_data['resistance'][latest_idx]:.2e} Ξ©",
f"{(st.session_state.measurement_data['resistance'][latest_idx] / 1e6):.2f} MΞ©"
)
with col4:
st.metric(
"Temperature",
f"{st.session_state.measurement_data['temperature'][latest_idx]:.1f} Β°C"
)
# Real-time charts
if st.session_state.measurement_data['timestamp']:
st.header("π Real-time Measurements")
# Create charts
fig_current = go.Figure()
fig_current.add_trace(go.Scatter(
x=st.session_state.measurement_data['timestamp'],
y=st.session_state.measurement_data['current'],
mode='lines+markers',
name='Current (A)',
line=dict(color='#1f77b4', width=2)
))
fig_current.update_layout(
title="Current Measurement",
xaxis_title="Time",
yaxis_title="Current (A)",
height=300
)
fig_voltage = go.Figure()
fig_voltage.add_trace(go.Scatter(
x=st.session_state.measurement_data['timestamp'],
y=st.session_state.measurement_data['voltage'],
mode='lines+markers',
name='Voltage (V)',
line=dict(color='#ff7f0e', width=2)
))
fig_voltage.update_layout(
title="Voltage Measurement",
xaxis_title="Time",
yaxis_title="Voltage (V)",
height=300
)
fig_resistance = go.Figure()
fig_resistance.add_trace(go.Scatter(
x=st.session_state.measurement_data['timestamp'],
y=st.session_state.measurement_data['resistance'],
mode='lines+markers',
name='Resistance (Ξ©)',
line=dict(color='#2ca02c', width=2)
))
fig_resistance.update_layout(
title="Resistance Calculation",
xaxis_title="Time",
yaxis_title="Resistance (Ξ©)",
height=300
)
fig_temperature = go.Figure()
fig_temperature.add_trace(go.Scatter(
x=st.session_state.measurement_data['timestamp'],
y=st.session_state.measurement_data['temperature'],
mode='lines+markers',
name='Temperature (Β°C)',
line=dict(color='#d62728', width=2)
))
fig_temperature.update_layout(
title="Temperature Monitoring",
xaxis_title="Time",
yaxis_title="Temperature (Β°C)",
height=300
)
# Display charts in columns
chart_col1, chart_col2 = st.columns(2)
with chart_col1:
st.plotly_chart(fig_current, use_container_width=True)
st.plotly_chart(fig_resistance, use_container_width=True)
with chart_col2:
st.plotly_chart(fig_voltage, use_container_width=True)
st.plotly_chart(fig_temperature, use_container_width=True)
# AI Analysis
if st.session_state.measurement_data['timestamp']:
st.header("π€ AI Analysis")
analysis = perform_ai_analysis(st.session_state.measurement_data)
if analysis:
col1, col2, col3 = st.columns(3)
with col1:
st.subheader("π Current Analysis")
st.metric("Mean", f"{analysis['current']['mean']:.2e} A")
st.metric("Std Dev", f"{analysis['current']['std']:.2e} A")
st.metric("Stability", f"{(1 - analysis['current']['std']/analysis['current']['mean']) * 100:.2f}%" if analysis['current']['mean'] != 0 else "N/A")
with col2:
st.subheader("π Voltage Analysis")
st.metric("Mean", f"{analysis['voltage']['mean']:.6f} V")
st.metric("Std Dev", f"{analysis['voltage']['std']:.6f} V")
st.metric("Stability", f"{(1 - analysis['voltage']['std']/analysis['voltage']['mean']) * 100:.2f}%" if analysis['voltage']['mean'] != 0 else "N/A")
with col3:
st.subheader("β οΈ Anomaly Detection")
st.metric("Current Anomalies", analysis['anomalies']['current_anomalies'])
st.metric("Voltage Anomalies", analysis['anomalies']['voltage_anomalies'])
st.metric("Quality Score", f"{analysis['quality_score'] * 100:.1f}%")
if analysis['quality_score'] > 0.95:
st.success("β
Excellent Quality")
elif analysis['quality_score'] > 0.9:
st.warning("π‘ Good Quality")
else:
st.error("π΄ Needs Improvement")
# Data table
if st.session_state.measurement_data['timestamp']:
st.header("π Measurement Data")
df = pd.DataFrame(st.session_state.measurement_data)
st.dataframe(df, use_container_width=True)
# Auto-refresh for real-time updates
if st.session_state.measuring and st.session_state.device_connected:
time.sleep(1)
new_data = simulate_quantum_measurement()
st.session_state.measurement_data['timestamp'].append(new_data['timestamp'])
st.session_state.measurement_data['current'].append(new_data['current'])
st.session_state.measurement_data['voltage'].append(new_data['voltage'])
st.session_state.measurement_data['resistance'].append(new_data['resistance'])
st.session_state.measurement_data['temperature'].append(new_data['temperature'])
# Keep only last 100 data points
if len(st.session_state.measurement_data['timestamp']) > 100:
for key in st.session_state.measurement_data:
st.session_state.measurement_data[key] = st.session_state.measurement_data[key][-100:]
st.rerun()
if __name__ == "__main__":
main()