|
import pandas as pd |
|
import numpy as np |
|
from momentfm import MOMENTPipeline |
|
from io import StringIO |
|
import gradio as gr |
|
|
|
|
|
model = MOMENTPipeline.from_pretrained( |
|
"AutonLab/MOMENT-1-large", |
|
model_kwargs={"task_name": "reconstruction"}, |
|
) |
|
model.init() |
|
|
|
def generate_analysis_report(data_input, sensitivity=3.0): |
|
"""Generate comprehensive textual analysis report""" |
|
try: |
|
|
|
df = pd.read_csv(StringIO(data_input)) |
|
|
|
if 'timestamp' not in df.columns or 'value' not in df.columns: |
|
return "Error: CSV must contain 'timestamp' and 'value' columns" |
|
|
|
df['timestamp'] = pd.to_datetime(df['timestamp'], errors='coerce') |
|
df['value'] = pd.to_numeric(df['value'], errors='coerce') |
|
|
|
if df.isnull().values.any(): |
|
return "Error: Invalid data in timestamp or value columns" |
|
|
|
df = df.sort_values('timestamp').dropna() |
|
|
|
|
|
values = df['value'].values.astype(np.float32) |
|
values_3d = values.reshape(1, -1, 1) |
|
|
|
|
|
reconstructed = model.reconstruct(X=values_3d) |
|
|
|
|
|
errors = np.abs(values - reconstructed[0,:,0]) |
|
median = np.median(errors) |
|
mad = np.median(np.abs(errors - median)) |
|
threshold = median + sensitivity * (1.4826 * mad) |
|
|
|
|
|
anomalies = df.copy() |
|
anomalies['anomaly_score'] = errors |
|
anomalies = anomalies[errors > threshold].sort_values('anomaly_score', ascending=False) |
|
|
|
|
|
report = f""" |
|
EQUIPMENT ANALYSIS REPORT |
|
======================== |
|
Generated: {pd.Timestamp.now().strftime('%Y-%m-%d %H:%M:%S')} |
|
Sensitivity: {sensitivity} (z-score) |
|
|
|
DATA SUMMARY |
|
------------ |
|
Time period: {df['timestamp'].min()} to {df['timestamp'].max()} |
|
Data points: {len(df)} |
|
Value range: {df['value'].min():.2f} to {df['value'].max():.2f} |
|
Median value: {df['value'].median():.2f} |
|
|
|
ANOMALY FINDINGS |
|
---------------- |
|
Detection threshold: {threshold:.2f} |
|
Anomalies found: {len(anomalies)} ({len(anomalies)/len(df):.1%}) |
|
Most severe: {errors.max():.2f} at {df.loc[errors.argmax(), 'timestamp']} |
|
|
|
TOP ANOMALIES |
|
------------- |
|
{anomalies[['timestamp', 'value', 'anomaly_score']].head(10).to_string(index=False, float_format='%.2f')} |
|
|
|
RECOMMENDATIONS |
|
--------------- |
|
1. Investigate top 3 anomalies for potential equipment issues |
|
2. Check maintenance records around {anomalies['timestamp'].iloc[0].strftime('%Y-%m-%d %H:%M')} |
|
3. Consider recalibration if anomalies persist |
|
4. Review sensor health if anomalies cluster in time |
|
""" |
|
return report.strip() |
|
|
|
except Exception as e: |
|
return f"ANALYSIS FAILED: {str(e)}" |
|
|
|
|
|
with gr.Blocks(title="Equipment Analysis Reporter") as demo: |
|
gr.Markdown("## π Equipment Health Analysis Report") |
|
|
|
with gr.Row(): |
|
with gr.Column(): |
|
data_input = gr.Textbox( |
|
label="Paste CSV Data (timestamp,value)", |
|
value="""timestamp,value |
|
2025-04-01 00:00:00,100 |
|
2025-04-01 01:00:00,102 |
|
2025-04-01 02:00:00,98 |
|
2025-04-01 03:00:00,105 |
|
2025-04-01 04:00:00,103 |
|
2025-04-01 05:00:00,107 |
|
2025-04-01 06:00:00,200 |
|
2025-04-01 07:00:00,108 |
|
2025-04-01 08:00:00,110 |
|
2025-04-01 09:00:00,98 |
|
2025-04-01 10:00:00,99 |
|
2025-04-01 11:00:00,102 |
|
2025-04-01 12:00:00,101""", |
|
lines=10 |
|
) |
|
sensitivity = gr.Slider(1.0, 5.0, value=3.0, step=0.1, label="Detection Sensitivity") |
|
submit_btn = gr.Button("Generate Report", variant="primary") |
|
|
|
with gr.Column(): |
|
report_output = gr.Textbox( |
|
label="Analysis Report", |
|
lines=20, |
|
interactive=False |
|
) |
|
|
|
submit_btn.click( |
|
generate_analysis_report, |
|
inputs=[data_input, sensitivity], |
|
outputs=report_output |
|
) |
|
|
|
if __name__ == "__main__": |
|
demo.launch(server_name="0.0.0.0", server_port=7860) |
|
|