File size: 4,684 Bytes
6f850cd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import gradio as gr
import numpy as np
import pandas as pd
from momentfm import MOMENTPipeline
import matplotlib.pyplot as plt
from io import StringIO

# Initialize the MOMENT model
model = MOMENTPipeline.from_pretrained(
    "AutonLab/MOMENT-1-large",
    model_kwargs={"task_name": "reconstruction"},
)
model.init()

def detect_anomalies(data_input, threshold=0.05):
    """
    Process time-series data and detect anomalies using MOMENT model
    """
    try:
        # Handle different input types
        if isinstance(data_input, str):
            # Try to read as CSV
            try:
                df = pd.read_csv(StringIO(data_input))
            except:
                # Try to read as JSON
                try:
                    df = pd.read_json(StringIO(data_input))
                except:
                    return "Error: Could not parse input data. Please provide valid CSV or JSON."
        elif isinstance(data_input, dict):
            df = pd.DataFrame(data_input)
        else:
            return "Error: Unsupported input format"
        
        # Check for required columns
        if 'timestamp' not in df.columns or 'value' not in df.columns:
            return "Error: Data must contain 'timestamp' and 'value' columns"
        
        # Convert timestamp to datetime if needed
        df['timestamp'] = pd.to_datetime(df['timestamp'])
        df = df.sort_values('timestamp')
        
        # Prepare data for MOMENT model
        time_series = df['value'].values.astype(float)
        
        # Get reconstruction from the model
        reconstruction = model.reconstruct(time_series)
        
        # Calculate reconstruction error
        error = np.abs(time_series - reconstruction)
        
        # Detect anomalies based on threshold
        df['anomaly_score'] = error
        df['is_anomaly'] = error > threshold * np.max(error)
        
        # Create plot
        fig, ax = plt.subplots(figsize=(12, 6))
        ax.plot(df['timestamp'], df['value'], label='Original', color='blue')
        ax.scatter(
            df[df['is_anomaly']]['timestamp'], 
            df[df['is_anomaly']]['value'], 
            color='red', 
            label='Anomaly'
        )
        ax.set_title('Time Series with Anomalies Detected')
        ax.set_xlabel('Timestamp')
        ax.set_ylabel('Value')
        ax.legend()
        ax.grid(True)
        
        # Prepare results
        anomalies = df[df['is_anomaly']]
        stats = {
            "total_points": len(df),
            "anomalies_detected": len(anomalies),
            "anomaly_percentage": f"{100 * len(anomalies)/len(df):.2f}%",
            "max_anomaly_score": np.max(error),
            "threshold_used": threshold
        }
        
        return fig, stats, df.to_dict(orient='records')
    
    except Exception as e:
        return f"Error processing data: {str(e)}"

# Create Gradio interface
with gr.Blocks(title="Equipment Anomaly Detection") as demo:
    gr.Markdown("# 🛠️ Equipment Sensor Anomaly Detection")
    gr.Markdown("""
    **Detect anomalies in equipment sensor data using the MOMENT-1-large model**
    - Upload CSV/JSON data with 'timestamp' and 'value' columns
    - Adjust the sensitivity threshold as needed
    - Get visual and statistical results
    """)
    
    with gr.Row():
        with gr.Column():
            input_data = gr.Textbox(
                label="Paste your time-series data (CSV/JSON)",
                placeholder="timestamp,value\n2023-01-01,1.2\n2023-01-02,1.5...",
                lines=5
            )
            file_upload = gr.File(label="Or upload a file")
            threshold = gr.Slider(
                minimum=0.01,
                maximum=0.2,
                value=0.05,
                step=0.01,
                label="Anomaly Detection Sensitivity (lower = more sensitive)"
            )
            submit_btn = gr.Button("Detect Anomalies", variant="primary")
        
        with gr.Column():
            plot_output = gr.Plot(label="Anomaly Detection Results")
            stats_output = gr.JSON(label="Detection Statistics")
            data_output = gr.JSON(label="Processed Data with Anomaly Scores")
    
    # Handle file upload
    def process_file(file):
        if file:
            with open(file.name, 'r') as f:
                return f.read()
        return ""
    
    file_upload.change(process_file, inputs=file_upload, outputs=input_data)
    
    submit_btn.click(
        detect_anomalies,
        inputs=[input_data, threshold],
        outputs=[plot_output, stats_output, data_output]
    )

if __name__ == "__main__":
    demo.launch(server_name="0.0.0.0", server_port=7860)