Skip to content

Commit

Permalink
Merge pull request #108 from aseemanand/uday_010825
Browse files Browse the repository at this point in the history
Added additional API endpoints in api_catch.py
  • Loading branch information
jpamarthi authored Jan 8, 2025
2 parents d2a4ab2 + 99ba924 commit 012c50f
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 2 deletions.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "pycatcher"
version = "0.0.63"
version = "0.0.64"
description = "This package identifies outlier(s) for a given time-series dataset in simple steps. It supports day, week, month and quarter level time-series data."
authors = ["Aseem Anand <[email protected]>"]
maintainers = ["Jagadish Pamarthi <[email protected]>"]
Expand Down
67 changes: 66 additions & 1 deletion src/pycatcher/api_catch.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import pandas as pd
from src.pycatcher.catch import find_outliers_iqr
from src.pycatcher.catch import (find_outliers_iqr, detect_outliers_stl, detect_outliers_today_classic)

# Define the FastAPI app
app = FastAPI(
Expand Down Expand Up @@ -48,5 +48,70 @@ async def find_outliers_api(inputs: InputModel):

return OutputModel(outliers=outliers_list)

except Exception as e:
raise HTTPException(status_code=500, detail=str(e))


@app.post("/detect_outliers_stl", response_model=OutputModel, summary="Detect outliers using STL")
async def detect_outliers_stl_api(inputs: InputModel):
"""
API endpoint to detect outliers using the STL method.
"""
try:
# Convert input data into a pandas DataFrame
df = pd.DataFrame(data=inputs.data, columns=inputs.columns)

# Ensure the first column is in datetime format
if not pd.api.types.is_datetime64_any_dtype(df.iloc[:, 0]):
try:
df.iloc[:, 0] = pd.to_datetime(df.iloc[:, 0])
except Exception as e:
raise HTTPException(status_code=400, detail=f"Error converting first column to datetime: {e}")

# Call the `detect_outliers_stl` function
if not callable(detect_outliers_stl):
raise HTTPException(status_code=500, detail="`detect_outliers_stl` is not defined or not callable")

# Call the function and get the result
outliers = detect_outliers_stl(df)

# Check if the result is a DataFrame
if isinstance(outliers, pd.DataFrame):
outliers_list = outliers.reset_index().to_dict(orient="records")
else:
raise HTTPException(status_code=400, detail="No outliers detected or an error occurred.")

return OutputModel(outliers=outliers_list)

except Exception as e:
raise HTTPException(status_code=500, detail=str(e))


@app.post("/detect_outliers_today_classic", response_model=OutputModel, summary="Detect today's outliers using "
"Classic method")
async def detect_outliers_today_classic_api(inputs: InputModel):
"""
API endpoint to detect today's outliers using the Classic method.
"""
try:
df = pd.DataFrame(data=inputs.data, columns=inputs.columns)

if not pd.api.types.is_datetime64_any_dtype(df.iloc[:, 0]):
try:
df.iloc[:, 0] = pd.to_datetime(df.iloc[:, 0])
except Exception as e:
raise HTTPException(status_code=400, detail=f"Error converting first column to datetime: {e}")

outliers = detect_outliers_today_classic(df)

if isinstance(outliers, pd.DataFrame):
outliers_list = outliers.reset_index().to_dict(orient="records")
elif isinstance(outliers, str): # Handle the "No Outliers Today!" case
outliers_list = [{"message": outliers}]
else:
raise HTTPException(status_code=400, detail="Unexpected output from the function.")

return OutputModel(outliers=outliers_list)

except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
60 changes: 60 additions & 0 deletions tests/test_api_catch.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
from src.pycatcher.api_catch import app
import pandas as pd

# Create a TestClient instance for the FastAPI app
client = TestClient(app)

def test_find_outliers_api():
# Create a TestClient instance for the FastAPI app
client = TestClient(app)
Expand Down Expand Up @@ -40,4 +43,61 @@ def test_find_outliers_api():
f"Expected outliers {expected_outliers}, but got {response_data['outliers']}"
)

def test_detect_outliers_stl_api():
# Prepare test data
data = {
'ID': [1, 2, 3, 4, 5],
'Value': [10, 12, 14, 100, 15]
}
df = pd.DataFrame(data)
payload = {
"data": df.values.tolist(),
"columns": df.columns.tolist()
}

response = client.post("/detect_outliers_stl", json=payload)

# Expected output
expected_outliers = [
{'ID': '1970-01-01T00:00:00', 'Value': 100.0, 'index': 3}
]

assert response.status_code == 200
response_data = response.json()
assert "outliers" in response_data

# Validate the outliers detected
assert response_data["outliers"] == expected_outliers, (
f"Expected outliers {expected_outliers}, but got {response_data['outliers']}"
)

def test_detect_outliers_today_classic_api():
# Prepare test data
data = {
'ID': [1, 2, 3, 4, 5],
'Value': [10, 12, 14, 100, 15]
}

df = pd.DataFrame(data)
payload = {
"data": df.values.tolist(),
"columns": df.columns.tolist()
}

response = client.post("/detect_outliers_today_classic", json=payload)

# Expected output
expected_outliers = [
{'message': 'No Outliers Today!'}
]

assert response.status_code == 200
response_data = response.json()
assert "outliers" in response_data

# Validate the outliers detected
assert response_data["outliers"] == expected_outliers, (
f"Expected outliers {expected_outliers}, but got {response_data['outliers']}"
)

print("Test passed: The API detected outliers correctly.")

0 comments on commit 012c50f

Please sign in to comment.