Create app.py
Browse files
app.py
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import gradio as gr
|
| 2 |
+
import matplotlib.pyplot as plt
|
| 3 |
+
import pandas as pd
|
| 4 |
+
import io
|
| 5 |
+
import tempfile
|
| 6 |
+
import os
|
| 7 |
+
|
| 8 |
+
# 直接複製 main.py 的處理邏輯
|
| 9 |
+
|
| 10 |
+
def parse_accel_hex(tokens):
|
| 11 |
+
if len(tokens) < 6:
|
| 12 |
+
return None, None, None
|
| 13 |
+
acc_x = int(tokens[0], 16) << 8 | int(tokens[1], 16)
|
| 14 |
+
acc_y = int(tokens[2], 16) << 8 | int(tokens[3], 16)
|
| 15 |
+
acc_z = int(tokens[4], 16) << 8 | int(tokens[5], 16)
|
| 16 |
+
def to_int16(val):
|
| 17 |
+
return val - 0x10000 if val & 0x8000 else val
|
| 18 |
+
return to_int16(acc_x), to_int16(acc_y), to_int16(acc_z)
|
| 19 |
+
|
| 20 |
+
def process_file(file_obj, acc_sensitivity):
|
| 21 |
+
# 支援 gradio 3.x/4.x: file_obj 可能是檔案物件或路徑字串或 NamedString
|
| 22 |
+
if hasattr(file_obj, 'read'):
|
| 23 |
+
# 檔案物件
|
| 24 |
+
file_obj.seek(0)
|
| 25 |
+
lines = file_obj.read().decode('utf-8').splitlines()
|
| 26 |
+
else:
|
| 27 |
+
# 路徑字串或 NamedString
|
| 28 |
+
with open(str(file_obj), 'r', encoding='utf-8') as f:
|
| 29 |
+
lines = f.read().splitlines()
|
| 30 |
+
output = io.StringIO()
|
| 31 |
+
output.write('Timestamp,AccelX,AccelY,AccelZ\n')
|
| 32 |
+
data = []
|
| 33 |
+
for line in lines:
|
| 34 |
+
if 'INFO' not in line:
|
| 35 |
+
continue
|
| 36 |
+
parts = line.split()
|
| 37 |
+
if not parts:
|
| 38 |
+
continue
|
| 39 |
+
timestamp = parts[0]
|
| 40 |
+
idx = line.find('value (0x):')
|
| 41 |
+
if idx == -1:
|
| 42 |
+
continue
|
| 43 |
+
hex_str = line[idx + len('value (0x):'):].strip()
|
| 44 |
+
tokens = [tok for tok in hex_str.split('-') if tok]
|
| 45 |
+
acc_x, acc_y, acc_z = parse_accel_hex(tokens)
|
| 46 |
+
if acc_x is None:
|
| 47 |
+
continue
|
| 48 |
+
f_acc_x = acc_x / acc_sensitivity
|
| 49 |
+
f_acc_y = acc_y / acc_sensitivity
|
| 50 |
+
f_acc_z = acc_z / acc_sensitivity
|
| 51 |
+
output.write(f"{timestamp},{f_acc_x:.4f},{f_acc_y:.4f},{f_acc_z:.4f}\n")
|
| 52 |
+
data.append((timestamp, f_acc_x, f_acc_y, f_acc_z))
|
| 53 |
+
output.seek(0)
|
| 54 |
+
return output, data
|
| 55 |
+
|
| 56 |
+
def gradio_interface(file, acc_sensitivity):
|
| 57 |
+
if file is None:
|
| 58 |
+
return None, None, None
|
| 59 |
+
csv_io, data = process_file(file, acc_sensitivity)
|
| 60 |
+
# 下載用:寫入臨時檔案,回傳路徑
|
| 61 |
+
with tempfile.NamedTemporaryFile(delete=False, suffix='.csv', mode='w', encoding='utf-8') as tmp:
|
| 62 |
+
tmp.write(csv_io.getvalue())
|
| 63 |
+
tmp_path = tmp.name
|
| 64 |
+
# 視覺化
|
| 65 |
+
if not data:
|
| 66 |
+
return tmp_path, None, "No valid data."
|
| 67 |
+
df = pd.DataFrame(data, columns=['Timestamp', 'AccelX', 'AccelY', 'AccelZ'])
|
| 68 |
+
# 將 Timestamp 轉為 datetime
|
| 69 |
+
df['Timestamp'] = pd.to_datetime(df['Timestamp'], errors='coerce')
|
| 70 |
+
fig, ax = plt.subplots(figsize=(10,6))
|
| 71 |
+
ax.plot(df['Timestamp'], df['AccelX'], label='Ax')
|
| 72 |
+
ax.plot(df['Timestamp'], df['AccelY'], label='Ay')
|
| 73 |
+
ax.plot(df['Timestamp'], df['AccelZ'], label='Az')
|
| 74 |
+
ax.set_xlabel('Time')
|
| 75 |
+
ax.set_ylabel('Acceleration (g)')
|
| 76 |
+
ax.set_title('Accelerometer Data')
|
| 77 |
+
ax.legend()
|
| 78 |
+
fig.autofmt_xdate()
|
| 79 |
+
plt.tight_layout()
|
| 80 |
+
return tmp_path, fig, None
|
| 81 |
+
|
| 82 |
+
demo = gr.Blocks()
|
| 83 |
+
with demo:
|
| 84 |
+
gr.Markdown("""
|
| 85 |
+
# 加速度資料轉換與視覺化
|
| 86 |
+
上傳原始檔案(如 data2.txt),調整 ACC_SENSITIVITY,下載轉換後的 csv,並預覽加速度圖表。
|
| 87 |
+
""")
|
| 88 |
+
with gr.Row():
|
| 89 |
+
file_input = gr.File(label="上傳原始檔案(txt)")
|
| 90 |
+
acc_input = gr.Number(value=4096.0, label="ACC_SENSITIVITY (例如 4096.0)")
|
| 91 |
+
with gr.Row():
|
| 92 |
+
csv_output = gr.File(label="下載轉換後的 CSV")
|
| 93 |
+
plot_output = gr.Plot(label="加速度圖表")
|
| 94 |
+
msg_output = gr.Textbox(label="訊息", interactive=False)
|
| 95 |
+
btn = gr.Button("執行轉換與繪圖")
|
| 96 |
+
btn.click(fn=gradio_interface, inputs=[file_input, acc_input], outputs=[csv_output, plot_output, msg_output])
|
| 97 |
+
|
| 98 |
+
demo.launch()
|