|
|
import gradio as gr |
|
|
import matplotlib.pyplot as plt |
|
|
import pandas as pd |
|
|
import io |
|
|
import tempfile |
|
|
import os |
|
|
|
|
|
|
|
|
|
|
|
def parse_accel_hex(tokens): |
|
|
if len(tokens) < 6: |
|
|
return None, None, None |
|
|
acc_x = int(tokens[0], 16) << 8 | int(tokens[1], 16) |
|
|
acc_y = int(tokens[2], 16) << 8 | int(tokens[3], 16) |
|
|
acc_z = int(tokens[4], 16) << 8 | int(tokens[5], 16) |
|
|
def to_int16(val): |
|
|
return val - 0x10000 if val & 0x8000 else val |
|
|
return to_int16(acc_x), to_int16(acc_y), to_int16(acc_z) |
|
|
|
|
|
def process_file(file_obj, acc_sensitivity): |
|
|
|
|
|
if hasattr(file_obj, 'read'): |
|
|
|
|
|
file_obj.seek(0) |
|
|
lines = file_obj.read().decode('utf-8').splitlines() |
|
|
else: |
|
|
|
|
|
with open(str(file_obj), 'r', encoding='utf-8') as f: |
|
|
lines = f.read().splitlines() |
|
|
output = io.StringIO() |
|
|
output.write('Timestamp,AccelX,AccelY,AccelZ\n') |
|
|
data = [] |
|
|
for line in lines: |
|
|
if 'INFO' not in line: |
|
|
continue |
|
|
parts = line.split() |
|
|
if not parts: |
|
|
continue |
|
|
timestamp = parts[0] |
|
|
idx = line.find('value (0x):') |
|
|
if idx == -1: |
|
|
continue |
|
|
hex_str = line[idx + len('value (0x):'):].strip() |
|
|
tokens = [tok for tok in hex_str.split('-') if tok] |
|
|
acc_x, acc_y, acc_z = parse_accel_hex(tokens) |
|
|
if acc_x is None: |
|
|
continue |
|
|
f_acc_x = acc_x / acc_sensitivity |
|
|
f_acc_y = acc_y / acc_sensitivity |
|
|
f_acc_z = acc_z / acc_sensitivity |
|
|
output.write(f"{timestamp},{f_acc_x:.4f},{f_acc_y:.4f},{f_acc_z:.4f}\n") |
|
|
data.append((timestamp, f_acc_x, f_acc_y, f_acc_z)) |
|
|
|
|
|
|
|
|
if data: |
|
|
data.pop(0) |
|
|
|
|
|
output.seek(0) |
|
|
return output, data |
|
|
|
|
|
def gradio_interface(file, acc_sensitivity): |
|
|
if file is None: |
|
|
return None, None, None |
|
|
csv_io, data = process_file(file, acc_sensitivity) |
|
|
|
|
|
with tempfile.NamedTemporaryFile(delete=False, suffix='.csv', mode='w', encoding='utf-8') as tmp: |
|
|
tmp.write(csv_io.getvalue()) |
|
|
tmp_path = tmp.name |
|
|
|
|
|
if not data: |
|
|
return tmp_path, None, "No valid data." |
|
|
df = pd.DataFrame(data, columns=['Timestamp', 'AccelX', 'AccelY', 'AccelZ']) |
|
|
|
|
|
df['Timestamp'] = pd.to_datetime(df['Timestamp'], errors='coerce') |
|
|
fig, ax = plt.subplots(figsize=(10,6)) |
|
|
ax.plot(df['Timestamp'], df['AccelX'], label='Ax') |
|
|
ax.plot(df['Timestamp'], df['AccelY'], label='Ay') |
|
|
ax.plot(df['Timestamp'], df['AccelZ'], label='Az') |
|
|
ax.set_xlabel('Time') |
|
|
ax.set_ylabel('Acceleration (g)') |
|
|
ax.set_title('Accelerometer Data') |
|
|
ax.legend() |
|
|
fig.autofmt_xdate() |
|
|
plt.tight_layout() |
|
|
return tmp_path, fig, None |
|
|
|
|
|
demo = gr.Blocks() |
|
|
with demo: |
|
|
gr.Markdown(""" |
|
|
<img src="https://custom-images.strikinglycdn.com/res/hrscywv4p/image/upload/c_limit,fl_lossy,h_300,w_300,f_auto,q_auto/4493206/132971_72411.png" width="100" /> |
|
|
|
|
|
# 加速度資料轉換與視覺化 |
|
|
上傳原始檔案(如 data.txt),調整 ACC_SENSITIVITY,下載轉換後的 csv,並預覽加速度圖表。 |
|
|
""") |
|
|
|
|
|
with gr.Row(): |
|
|
file_input = gr.File(label="上傳原始檔案(txt)") |
|
|
acc_input = gr.Number(value=4096.0, label="ACC_SENSITIVITY (例如 4096.0)") |
|
|
with gr.Row(): |
|
|
csv_output = gr.File(label="下載轉換後的 CSV") |
|
|
plot_output = gr.Plot(label="加速度圖表") |
|
|
msg_output = gr.Textbox(label="訊息", interactive=False) |
|
|
btn = gr.Button("執行轉換與繪圖") |
|
|
btn.click(fn=gradio_interface, inputs=[file_input, acc_input], outputs=[csv_output, plot_output, msg_output]) |
|
|
|
|
|
demo.launch() |
|
|
|