Emmanuel Frimpong Asante commited on
Commit
edbf3ae
·
1 Parent(s): b0de8e6

update space

Browse files
.idea/.gitignore DELETED
@@ -1,8 +0,0 @@
1
- # Default ignored files
2
- /shelf/
3
- /workspace.xml
4
- # Editor-based HTTP Client requests
5
- /httpRequests/
6
- # Datasource local storage ignored files
7
- /dataSources/
8
- /dataSources.local.xml
 
 
 
 
 
 
 
 
 
.idea/Generative_AI_with_poultry_disease_detection_system_v2.iml DELETED
@@ -1,11 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <module type="PYTHON_MODULE" version="4">
3
- <component name="NewModuleRootManager">
4
- <content url="file://$MODULE_DIR$">
5
- <excludeFolder url="file://$MODULE_DIR$/.venv" />
6
- </content>
7
- <orderEntry type="jdk" jdkName="Python 3.12 (Generative_AI_with_poultry_disease_detection_system_v2)" jdkType="Python SDK" />
8
- <orderEntry type="sourceFolder" forTests="false" />
9
- <orderEntry type="library" name="jquery-3.6.0" level="application" />
10
- </component>
11
- </module>
 
 
 
 
 
 
 
 
 
 
 
 
.idea/git_toolbox_blame.xml DELETED
@@ -1,6 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="GitToolBoxBlameSettings">
4
- <option name="version" value="2" />
5
- </component>
6
- </project>
 
 
 
 
 
 
 
.idea/git_toolbox_prj.xml DELETED
@@ -1,15 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="GitToolBoxProjectSettings">
4
- <option name="commitMessageIssueKeyValidationOverride">
5
- <BoolValueOverride>
6
- <option name="enabled" value="true" />
7
- </BoolValueOverride>
8
- </option>
9
- <option name="commitMessageValidationEnabledOverride">
10
- <BoolValueOverride>
11
- <option name="enabled" value="true" />
12
- </BoolValueOverride>
13
- </option>
14
- </component>
15
- </project>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
.idea/inspectionProfiles/profiles_settings.xml DELETED
@@ -1,6 +0,0 @@
1
- <component name="InspectionProjectProfileManager">
2
- <settings>
3
- <option name="USE_PROJECT_PROFILE" value="false" />
4
- <version value="1.0" />
5
- </settings>
6
- </component>
 
 
 
 
 
 
 
.idea/jsLibraryMappings.xml DELETED
@@ -1,6 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="JavaScriptLibraryMappings">
4
- <file url="file://$PROJECT_DIR$" libraries="{jquery-3.6.0}" />
5
- </component>
6
- </project>
 
 
 
 
 
 
 
.idea/misc.xml DELETED
@@ -1,7 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="Black">
4
- <option name="sdkName" value="Python 3.12 (Generative_AI_with_poultry)" />
5
- </component>
6
- <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.12 (Generative_AI_with_poultry_disease_detection_system_v2)" project-jdk-type="Python SDK" />
7
- </project>
 
 
 
 
 
 
 
 
.idea/modules.xml DELETED
@@ -1,8 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="ProjectModuleManager">
4
- <modules>
5
- <module fileurl="file://$PROJECT_DIR$/.idea/Generative_AI_with_poultry_disease_detection_system_v2.iml" filepath="$PROJECT_DIR$/.idea/Generative_AI_with_poultry_disease_detection_system_v2.iml" />
6
- </modules>
7
- </component>
8
- </project>
 
 
 
 
 
 
 
 
 
.idea/vcs.xml DELETED
@@ -1,6 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="VcsDirectoryMappings">
4
- <mapping directory="" vcs="Git" />
5
- </component>
6
- </project>
 
 
 
 
 
 
 
app.py CHANGED
@@ -3,7 +3,6 @@
3
  import os
4
  import time
5
  import logging
6
- from datetime import datetime
7
  from fastapi import FastAPI, Request, HTTPException, BackgroundTasks
8
  from fastapi.templating import Jinja2Templates
9
  from fastapi.responses import HTMLResponse
@@ -11,13 +10,22 @@ from fastapi.staticfiles import StaticFiles
11
  import tensorflow as tf
12
  from routes.authentication import auth_router
13
  from routes.disease_detection import disease_router
14
- from services.health_monitoring_service import evaluate_health_data
 
 
15
 
16
  # Setup logging
17
  logging.basicConfig(level=logging.INFO)
18
  logger = logging.getLogger(__name__)
19
 
20
- # Check GPU availability
 
 
 
 
 
 
 
21
  gpu_devices = tf.config.list_physical_devices('GPU')
22
  if gpu_devices:
23
  logger.info(f"GPUs available: {len(gpu_devices)}")
@@ -32,14 +40,15 @@ templates = Jinja2Templates(directory="templates")
32
  static_dir = "static"
33
  if os.path.isdir(static_dir):
34
  app.mount("/static", StaticFiles(directory=static_dir), name="static")
35
- logger.info(f"Mounted static directory at /static")
36
  else:
37
  logger.error("Static directory not found.")
38
  raise HTTPException(status_code=500, detail="Static directory not found.")
39
 
40
- # Include routers for authentication and disease detection
41
  app.include_router(auth_router, prefix="/auth", tags=["Authentication"])
42
  app.include_router(disease_router, prefix="/disease", tags=["Disease Detection"])
 
43
 
44
  @app.get("/", response_class=HTMLResponse)
45
  async def landing_page(request: Request):
@@ -47,7 +56,7 @@ async def landing_page(request: Request):
47
  logger.info("Landing page accessed")
48
  return templates.TemplateResponse("landing.html", {"request": request})
49
 
50
- # Example health metrics for periodic monitoring
51
  health_metrics = {
52
  "weight_loss_percentage": 6,
53
  "mortality_rate": 1,
@@ -55,15 +64,18 @@ health_metrics = {
55
  }
56
 
57
  def monitor_health():
58
- """Periodically evaluate health data and log notifications if thresholds are crossed."""
59
  while True:
 
60
  notifications = evaluate_health_data(health_metrics)
61
  if notifications["notifications"]:
62
  logger.info(f"Health Notifications: {notifications['notifications']}")
 
 
63
  time.sleep(3600) # Run every hour
64
 
65
  @app.on_event("startup")
66
  async def startup_event():
67
- """Start background health monitoring on startup."""
68
  logger.info("Starting background health monitoring.")
69
  BackgroundTasks().add_task(monitor_health)
 
3
  import os
4
  import time
5
  import logging
 
6
  from fastapi import FastAPI, Request, HTTPException, BackgroundTasks
7
  from fastapi.templating import Jinja2Templates
8
  from fastapi.responses import HTMLResponse
 
10
  import tensorflow as tf
11
  from routes.authentication import auth_router
12
  from routes.disease_detection import disease_router
13
+ from routes.health_dashboard import dashboard_router
14
+ from services.health_monitoring_service import evaluate_health_data, get_health_alerts, send_alerts
15
+ from huggingface_hub import login
16
 
17
  # Setup logging
18
  logging.basicConfig(level=logging.INFO)
19
  logger = logging.getLogger(__name__)
20
 
21
+ # Load Hugging Face Token
22
+ HF_TOKEN = os.getenv('HF_Token')
23
+ if HF_TOKEN:
24
+ login(token=HF_TOKEN, add_to_git_credential=True)
25
+ else:
26
+ logger.warning("Hugging Face token not found in environment variables.")
27
+
28
+ # Check GPU availability for TensorFlow
29
  gpu_devices = tf.config.list_physical_devices('GPU')
30
  if gpu_devices:
31
  logger.info(f"GPUs available: {len(gpu_devices)}")
 
40
  static_dir = "static"
41
  if os.path.isdir(static_dir):
42
  app.mount("/static", StaticFiles(directory=static_dir), name="static")
43
+ logger.info("Mounted static directory at /static")
44
  else:
45
  logger.error("Static directory not found.")
46
  raise HTTPException(status_code=500, detail="Static directory not found.")
47
 
48
+ # Include routers for authentication, disease detection, and health dashboard
49
  app.include_router(auth_router, prefix="/auth", tags=["Authentication"])
50
  app.include_router(disease_router, prefix="/disease", tags=["Disease Detection"])
51
+ app.include_router(dashboard_router, prefix="/dashboard", tags=["Dashboard"])
52
 
53
  @app.get("/", response_class=HTMLResponse)
54
  async def landing_page(request: Request):
 
56
  logger.info("Landing page accessed")
57
  return templates.TemplateResponse("landing.html", {"request": request})
58
 
59
+ # health metrics for periodic monitoring
60
  health_metrics = {
61
  "weight_loss_percentage": 6,
62
  "mortality_rate": 1,
 
64
  }
65
 
66
  def monitor_health():
67
+ """Evaluate health data and log notifications if thresholds are crossed."""
68
  while True:
69
+ # Evaluate health metrics and send alerts
70
  notifications = evaluate_health_data(health_metrics)
71
  if notifications["notifications"]:
72
  logger.info(f"Health Notifications: {notifications['notifications']}")
73
+ # Optionally, send alerts to the farmer
74
+ send_alerts(notifications["notifications"], os.getenv("FARMER_EMAIL"))
75
  time.sleep(3600) # Run every hour
76
 
77
  @app.on_event("startup")
78
  async def startup_event():
79
+ """Initialize background health monitoring on startup."""
80
  logger.info("Starting background health monitoring.")
81
  BackgroundTasks().add_task(monitor_health)
requirements.txt CHANGED
@@ -10,4 +10,5 @@ jinja2
10
  python-multipart
11
  numpy
12
  pillow
13
- tensorflow[and-cuda]~=2.9
 
 
10
  python-multipart
11
  numpy
12
  pillow
13
+ tensorflow[and-cuda]~=2.9
14
+ huggingface_hub
routes/disease_detection.py CHANGED
@@ -3,16 +3,11 @@
3
  from fastapi import APIRouter, UploadFile, File, HTTPException
4
  from fastapi.responses import JSONResponse
5
  from PIL import Image
6
- import io
7
  import numpy as np
8
- from services.image_preprocessing import preprocess_image
9
- from services.disease_detection_service import load_disease_model
10
- from services.health_monitoring_service import get_treatment_recommendation
11
-
12
 
13
  disease_router = APIRouter()
14
- model = load_disease_model()
15
-
16
 
17
 
18
  @disease_router.post("/detect_disease", response_class=JSONResponse)
@@ -21,36 +16,34 @@ async def detect_disease(file: UploadFile = File(...)):
21
  Detect disease from uploaded poultry fecal image and provide treatment suggestions.
22
 
23
  Parameters:
24
- file (UploadFile): Uploaded image file to analyze.
25
 
26
  Returns:
27
- JSONResponse: Prediction result with disease notification and treatment suggestion.
28
  """
29
  if file.content_type not in ["image/jpeg", "image/png"]:
30
  raise HTTPException(status_code=400, detail="Invalid file type. Please upload a JPEG or PNG image.")
31
 
32
- # Load image and preprocess
33
- image_data = await file.read()
34
- image = Image.open(io.BytesIO(image_data))
35
- processed_image = preprocess_image(image)
36
-
37
- # Predict using the loaded model
38
- prediction = model.predict(processed_image)
39
- predicted_class = np.argmax(prediction, axis=1).item()
40
-
41
- # Map prediction to disease label (adjust labels as per model output)
42
- label_map = {0: "Healthy", 1: "Infected", 2: "Coccidiosis", 3: "Avian Influenza"}
43
- disease = label_map.get(predicted_class, "Unknown")
44
- confidence = prediction[0][predicted_class] * 100
45
-
46
- # Get treatment recommendation and notifications
47
- treatment_info = get_treatment_recommendation(disease)
48
-
49
- result = {
50
- "disease": disease,
51
  "confidence": f"{confidence:.2f}%",
52
- "notification": treatment_info["notification"],
53
- "suggestion": treatment_info["suggestion"]
54
- }
55
-
56
- return JSONResponse(content=result)
 
3
  from fastapi import APIRouter, UploadFile, File, HTTPException
4
  from fastapi.responses import JSONResponse
5
  from PIL import Image
 
6
  import numpy as np
7
+ import io
8
+ from services.disease_detection_service import bot
 
 
9
 
10
  disease_router = APIRouter()
 
 
11
 
12
 
13
  @disease_router.post("/detect_disease", response_class=JSONResponse)
 
16
  Detect disease from uploaded poultry fecal image and provide treatment suggestions.
17
 
18
  Parameters:
19
+ file (UploadFile): Image file to analyze.
20
 
21
  Returns:
22
+ JSONResponse: Prediction results including disease, status, confidence, recommendation, and details.
23
  """
24
  if file.content_type not in ["image/jpeg", "image/png"]:
25
  raise HTTPException(status_code=400, detail="Invalid file type. Please upload a JPEG or PNG image.")
26
 
27
+ try:
28
+ # Read and convert image to numpy array
29
+ image_data = await file.read()
30
+ image = Image.open(io.BytesIO(image_data)).convert("RGB")
31
+ image_np = np.array(image)
32
+ except Exception as e:
33
+ raise HTTPException(status_code=500, detail=f"Error loading image: {e}")
34
+
35
+ # Use bot to diagnose disease and generate a response
36
+ detailed_response, disease_name, status, recommendation, confidence = bot.diagnose_and_respond(image_np)
37
+
38
+ # Check if disease was detected successfully
39
+ if disease_name is None:
40
+ return JSONResponse(content={"error": "Unable to detect disease. Please try again."}, status_code=500)
41
+
42
+ # Return JSON response with prediction details
43
+ return JSONResponse(content={
44
+ "disease": disease_name,
45
+ "status": status,
46
  "confidence": f"{confidence:.2f}%",
47
+ "recommendation": recommendation,
48
+ "details": detailed_response
49
+ })
 
 
routes/health_dashboard.py ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # routes/health_dashboard.py
2
+
3
+ from fastapi import APIRouter, Request
4
+ from fastapi.templating import Jinja2Templates
5
+ from datetime import datetime
6
+
7
+ from starlette.responses import HTMLResponse
8
+
9
+ dashboard_router = APIRouter()
10
+ templates = Jinja2Templates(directory="templates")
11
+
12
+ # Simulate a database or storage for alerts
13
+ ALERT_HISTORY = []
14
+
15
+ @dashboard_router.get("/dashboard", response_class=HTMLResponse)
16
+ async def health_dashboard(request: Request):
17
+ """Render the health dashboard with current and historical alerts."""
18
+ # For demonstration purposes, we're displaying recent alerts.
19
+ # In a real implementation, fetch this data from a database.
20
+ context = {
21
+ "request": request,
22
+ "alerts": ALERT_HISTORY,
23
+ "last_updated": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
24
+ }
25
+ return templates.TemplateResponse("dashboard.html", context)
services/disease_detection_service.py CHANGED
@@ -1,35 +1,135 @@
1
  # services/disease_detection_service.py
2
 
 
 
3
  import tensorflow as tf
4
- from tensorflow.keras.models import load_model
 
5
  import numpy as np
6
- from PIL import Image
7
- import os
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
 
9
- # Enable memory growth for GPUs
10
  gpus = tf.config.list_physical_devices('GPU')
11
  if gpus:
12
- try:
13
- for gpu in gpus:
14
- tf.config.experimental.set_memory_growth(gpu, True)
15
- print("Memory growth enabled for GPU.")
16
- except RuntimeError as e:
17
- print(f"Error setting memory growth: {e}")
18
-
19
-
20
- MODEL_PATH = "models/Final_Chicken_disease_model.h5"
21
- model = None
22
-
23
- def load_disease_model():
24
- """Load the trained disease detection model with GPU support if available."""
25
- global model
26
- if model is None:
27
- # Use GPU if available
28
- if tf.config.list_physical_devices('GPU'):
29
- print("GPU is available. Using GPU for model inference.")
30
- with tf.device('/GPU:0'):
31
- model = load_model(MODEL_PATH, custom_objects={'BatchNormalization': tf.keras.layers.BatchNormalization})
32
- else:
33
- print("GPU not available. Using CPU for model inference.")
34
- model = load_model(MODEL_PATH, custom_objects={'BatchNormalization': tf.keras.layers.BatchNormalization})
35
- return model
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  # services/disease_detection_service.py
2
 
3
+ import os
4
+ import logging
5
  import tensorflow as tf
6
+ from keras.models import load_model
7
+ import cv2
8
  import numpy as np
9
+ from huggingface_hub import login
10
+ from pymongo import MongoClient
11
+ from transformers import AutoModelForCausalLM, AutoTokenizer
12
+
13
+ # Logging setup
14
+ logging.basicConfig(level=logging.INFO)
15
+ logger = logging.getLogger(__name__)
16
+
17
+ # Load environment variables
18
+ MONGO_URI = os.getenv("MONGO_URI")
19
+ HF_TOKEN = os.getenv('HF_Token')
20
+ db_client = MongoClient(MONGO_URI)
21
+ db = db_client.poultry_farm # MongoDB for record-keeping
22
+
23
+ # Hugging Face login for Llama 3.2
24
+ if HF_TOKEN:
25
+ login(token=HF_TOKEN, add_to_git_credential=True)
26
+ else:
27
+ logger.warning("Hugging Face token not found in environment variables.")
28
 
29
+ # Mixed precision and GPU configuration
30
  gpus = tf.config.list_physical_devices('GPU')
31
  if gpus:
32
+ for gpu in gpus:
33
+ tf.config.experimental.set_memory_growth(gpu, True)
34
+ from tensorflow.keras import mixed_precision
35
+ policy = mixed_precision.Policy('mixed_float16')
36
+ mixed_precision.set_global_policy(policy)
37
+ logger.info("Using mixed precision with GPU.")
38
+ else:
39
+ logger.info("Using CPU without mixed precision.")
40
+
41
+ # Load the disease detection model
42
+ try:
43
+ device_name = '/GPU:0' if gpus else '/CPU:0'
44
+ with tf.device(device_name):
45
+ disease_model = load_model('models/Final_Chicken_disease_model.h5', compile=True)
46
+ logger.info(f"Disease detection model loaded on {device_name}.")
47
+ except Exception as e:
48
+ logger.error(f"Error loading disease model: {e}")
49
+
50
+ # Llama 3.2 setup
51
+ model_name = "meta-llama/Llama-3.2-1B"
52
+ tokenizer = AutoTokenizer.from_pretrained(model_name)
53
+ llama_model = AutoModelForCausalLM.from_pretrained(model_name)
54
+
55
+ # Set a padding token if it doesn’t already exist
56
+ if tokenizer.pad_token is None:
57
+ tokenizer.add_special_tokens({'pad_token': '[PAD]'})
58
+ llama_model.resize_token_embeddings(len(tokenizer))
59
+
60
+ # Disease mapping and treatment guidelines
61
+ name_disease = {0: 'Coccidiosis', 1: 'Healthy', 2: 'New Castle Disease', 3: 'Salmonella'}
62
+ status_map = {0: 'Critical', 1: 'No issue', 2: 'Critical', 3: 'Critical'}
63
+ recommendations = {
64
+ 0: 'Administer anti-coccidial medication, maintain hygiene, and ensure proper litter management.',
65
+ 1: 'No treatment necessary; maintain regular monitoring and hygiene.',
66
+ 2: 'Isolate affected birds and seek veterinary consultation for targeted treatment.',
67
+ 3: 'Administer antibiotics as prescribed by a veterinarian and ensure biosecurity.'
68
+ }
69
+
70
+ class PoultryFarmBot:
71
+ def __init__(self, db):
72
+ self.db = db
73
+
74
+ def preprocess_image(self, image):
75
+ """Preprocess image for model input."""
76
+ try:
77
+ image = cv2.resize(image, (224, 224))
78
+ image = np.expand_dims(image, axis=0) / 255.0 # Normalize and add batch dimension
79
+ logger.info("Image preprocessed successfully.")
80
+ return image
81
+ except Exception as e:
82
+ logger.error(f"Error in image preprocessing: {e}")
83
+ return None
84
+
85
+ def predict_disease(self, image):
86
+ """Predict the disease from a preprocessed image and return detailed information."""
87
+ preprocessed_image = self.preprocess_image(image)
88
+ if preprocessed_image is None:
89
+ return "Image preprocessing failed.", None, None, None
90
+
91
+ try:
92
+ prediction = disease_model.predict(preprocessed_image)
93
+ predicted_class = np.argmax(prediction, axis=1).item()
94
+ disease_name = name_disease.get(predicted_class, "Unknown disease")
95
+ disease_status = status_map.get(predicted_class, "Unknown status")
96
+ recommendation = recommendations.get(predicted_class, "No recommendation available")
97
+ confidence = prediction[0][predicted_class] * 100
98
+ logger.info(f"Predicted: {disease_name} with {confidence:.2f}% confidence.")
99
+
100
+ # Generate detailed response using Llama 3.2
101
+ detailed_response = self.generate_detailed_response(disease_name, disease_status, recommendation)
102
+ return detailed_response, disease_name, disease_status, recommendation, confidence
103
+ except Exception as e:
104
+ logger.error(f"Prediction error: {e}")
105
+ return "Prediction failed.", None, None, None, None
106
+
107
+ def generate_detailed_response(self, disease_name, status, recommendation):
108
+ """Generate a detailed response using Llama 3.2 model for additional disease insights."""
109
+ prompt = (
110
+ f"The disease detected is {disease_name}, classified as {status}. "
111
+ f"Recommended action: {recommendation}. "
112
+ f"Here is more information about {disease_name}, including its causes, symptoms, and treatments "
113
+ "for effective management on a poultry farm."
114
+ )
115
+ response = self.llama_response(prompt)
116
+ return response.replace(prompt, "").strip()
117
+
118
+ def llama_response(self, prompt):
119
+ """Generate a response from the Llama 3.2 model based on a given prompt."""
120
+ try:
121
+ inputs = tokenizer(prompt, return_tensors="pt", max_length=150, truncation=True, padding=True)
122
+ outputs = llama_model.generate(inputs["input_ids"], max_length=150, do_sample=True, temperature=0.7)
123
+ return tokenizer.decode(outputs[0], skip_special_tokens=True)
124
+ except Exception as e:
125
+ logger.error(f"Llama model response error: {e}")
126
+ return "Error generating detailed response."
127
+
128
+ def diagnose_and_respond(self, image):
129
+ """Diagnose the disease and respond with detailed information and recommendations."""
130
+ if image is None or image.size == 0:
131
+ return "Please provide a valid poultry fecal image.", None, None, None, None
132
+ return self.predict_disease(image)
133
+
134
+ # Initialize the bot instance
135
+ bot = PoultryFarmBot(db)
services/health_monitoring_service.py CHANGED
@@ -2,38 +2,36 @@
2
 
3
  from datetime import datetime, timedelta
4
  from typing import Dict, List
5
-
6
  from services.email_notification_service import send_email
7
 
8
  # Dictionary to map diseases to suggested treatments
9
  TREATMENT_GUIDELINES = {
10
  "Healthy": {
11
  "notification": "The flock is healthy.",
12
- "suggestion": "Continue regular health checks and a balanced diet."
13
- },
14
- "Infected": {
15
- "notification": "Disease detected in poultry.",
16
- "suggestion": "Isolate affected birds and administer prescribed antibiotics. Consult a veterinarian for further assistance."
17
  },
18
  "Coccidiosis": {
19
  "notification": "Coccidiosis symptoms detected.",
20
- "suggestion": "Administer amprolium or sulfa drugs as recommended. Ensure clean water and reduce stress."
21
  },
22
- "Avian Influenza": {
23
- "notification": "Avian Influenza suspected.",
24
- "suggestion": "Report to the relevant authorities immediately. Quarantine the flock and halt bird movements."
 
 
 
 
25
  }
26
  }
27
 
28
- # Notification rules for various conditions
29
  HEALTH_THRESHOLDS = {
30
  "weight_loss_percentage": 5, # Alert if weight loss > 5% in a week
31
- "mortality_rate": 2, # Alert if mortality rate > 2% in a week
32
  "reduced_feed_intake_percentage": 10 # Alert if feed intake drops > 10%
33
  }
34
 
35
-
36
- def get_health_alerts(health_metrics: dict) -> Dict[str, str]:
37
  """
38
  Check health metrics and return alerts if thresholds are crossed.
39
 
@@ -41,7 +39,7 @@ def get_health_alerts(health_metrics: dict) -> Dict[str, str]:
41
  health_metrics (dict): Health metrics like weight loss, mortality rate, and feed intake.
42
 
43
  Returns:
44
- dict: Notifications and suggestions if any health issues are detected.
45
  """
46
  alerts = []
47
  if health_metrics.get("weight_loss_percentage", 0) > HEALTH_THRESHOLDS["weight_loss_percentage"]:
@@ -55,16 +53,13 @@ def get_health_alerts(health_metrics: dict) -> Dict[str, str]:
55
 
56
  return alerts
57
 
58
-
59
- def send_alerts(alerts: list, farmer_email: str):
60
  """Send alert notifications to the farmer's email."""
61
  if alerts:
62
  message = "\n".join(alerts)
63
  subject = "Poultry Health Alert"
64
  send_email(farmer_email, subject, message)
65
 
66
-
67
-
68
  def get_treatment_recommendation(disease: str) -> Dict[str, str]:
69
  """Get notification and treatment suggestion based on disease detected."""
70
  return TREATMENT_GUIDELINES.get(disease, {
@@ -72,8 +67,7 @@ def get_treatment_recommendation(disease: str) -> Dict[str, str]:
72
  "suggestion": "Consult a veterinarian for diagnosis and treatment."
73
  })
74
 
75
-
76
- def evaluate_health_data(health_metrics: dict) -> dict[str, list[str]]:
77
  """
78
  Evaluate health data and trigger alerts if thresholds are crossed.
79
 
@@ -81,7 +75,7 @@ def evaluate_health_data(health_metrics: dict) -> dict[str, list[str]]:
81
  health_metrics (dict): Health metrics like weight loss, mortality rate, and feed intake.
82
 
83
  Returns:
84
- dict: Notifications and suggestions if any health issues are detected.
85
  """
86
  notifications = []
87
 
@@ -89,8 +83,7 @@ def evaluate_health_data(health_metrics: dict) -> dict[str, list[str]]:
89
  notifications.append("Significant weight loss detected. Monitor feed quality and check for underlying issues.")
90
 
91
  if health_metrics.get("mortality_rate", 0) > HEALTH_THRESHOLDS["mortality_rate"]:
92
- notifications.append(
93
- "Increased mortality rate. Review flock conditions and investigate potential health issues.")
94
 
95
  if health_metrics.get("reduced_feed_intake_percentage", 0) > HEALTH_THRESHOLDS["reduced_feed_intake_percentage"]:
96
  notifications.append("Feed intake has dropped. Check for signs of illness or environmental stress.")
 
2
 
3
  from datetime import datetime, timedelta
4
  from typing import Dict, List
 
5
  from services.email_notification_service import send_email
6
 
7
  # Dictionary to map diseases to suggested treatments
8
  TREATMENT_GUIDELINES = {
9
  "Healthy": {
10
  "notification": "The flock is healthy.",
11
+ "suggestion": "No treatment necessary; maintain regular monitoring and hygiene."
 
 
 
 
12
  },
13
  "Coccidiosis": {
14
  "notification": "Coccidiosis symptoms detected.",
15
+ "suggestion": "Administer anti-coccidial medication, maintain hygiene, and ensure proper litter management."
16
  },
17
+ "New Castle Disease": {
18
+ "notification": "New Castle Disease suspected.",
19
+ "suggestion": "Isolate affected birds and seek veterinary consultation for targeted treatment."
20
+ },
21
+ "Salmonella": {
22
+ "notification": "Salmonella infection detected.",
23
+ "suggestion": "Administer antibiotics as prescribed by a veterinarian and ensure biosecurity."
24
  }
25
  }
26
 
27
+ # Notification thresholds for health metrics
28
  HEALTH_THRESHOLDS = {
29
  "weight_loss_percentage": 5, # Alert if weight loss > 5% in a week
30
+ "mortality_rate": 2, # Alert if mortality rate > 2% in a week
31
  "reduced_feed_intake_percentage": 10 # Alert if feed intake drops > 10%
32
  }
33
 
34
+ def get_health_alerts(health_metrics: dict) -> List[str]:
 
35
  """
36
  Check health metrics and return alerts if thresholds are crossed.
37
 
 
39
  health_metrics (dict): Health metrics like weight loss, mortality rate, and feed intake.
40
 
41
  Returns:
42
+ list: Notifications and suggestions if any health issues are detected.
43
  """
44
  alerts = []
45
  if health_metrics.get("weight_loss_percentage", 0) > HEALTH_THRESHOLDS["weight_loss_percentage"]:
 
53
 
54
  return alerts
55
 
56
+ def send_alerts(alerts: List[str], farmer_email: str):
 
57
  """Send alert notifications to the farmer's email."""
58
  if alerts:
59
  message = "\n".join(alerts)
60
  subject = "Poultry Health Alert"
61
  send_email(farmer_email, subject, message)
62
 
 
 
63
  def get_treatment_recommendation(disease: str) -> Dict[str, str]:
64
  """Get notification and treatment suggestion based on disease detected."""
65
  return TREATMENT_GUIDELINES.get(disease, {
 
67
  "suggestion": "Consult a veterinarian for diagnosis and treatment."
68
  })
69
 
70
+ def evaluate_health_data(health_metrics: dict) -> Dict[str, List[str]]:
 
71
  """
72
  Evaluate health data and trigger alerts if thresholds are crossed.
73
 
 
75
  health_metrics (dict): Health metrics like weight loss, mortality rate, and feed intake.
76
 
77
  Returns:
78
+ dict: Notifications if any health issues are detected.
79
  """
80
  notifications = []
81
 
 
83
  notifications.append("Significant weight loss detected. Monitor feed quality and check for underlying issues.")
84
 
85
  if health_metrics.get("mortality_rate", 0) > HEALTH_THRESHOLDS["mortality_rate"]:
86
+ notifications.append("Increased mortality rate. Review flock conditions and investigate potential health issues.")
 
87
 
88
  if health_metrics.get("reduced_feed_intake_percentage", 0) > HEALTH_THRESHOLDS["reduced_feed_intake_percentage"]:
89
  notifications.append("Feed intake has dropped. Check for signs of illness or environmental stress.")
services/image_preprocessing.py CHANGED
@@ -2,6 +2,11 @@
2
 
3
  from PIL import Image
4
  import numpy as np
 
 
 
 
 
5
 
6
 
7
  def preprocess_image(image: Image.Image, target_size=(224, 224)):
@@ -15,8 +20,24 @@ def preprocess_image(image: Image.Image, target_size=(224, 224)):
15
  Returns:
16
  np.ndarray: Preprocessed image ready for model input.
17
  """
18
- image = image.convert("RGB") # Ensure 3 color channels
19
- image = image.resize(target_size) # Resize image
20
- image_array = np.array(image) / 255.0 # Normalize to [0, 1]
21
- image_array = np.expand_dims(image_array, axis=0) # Add batch dimension
22
- return image_array
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
 
3
  from PIL import Image
4
  import numpy as np
5
+ import logging
6
+
7
+ # Setup logging
8
+ logging.basicConfig(level=logging.INFO)
9
+ logger = logging.getLogger(__name__)
10
 
11
 
12
  def preprocess_image(image: Image.Image, target_size=(224, 224)):
 
20
  Returns:
21
  np.ndarray: Preprocessed image ready for model input.
22
  """
23
+ try:
24
+ # Ensure the image has 3 color channels (RGB)
25
+ image = image.convert("RGB")
26
+ logger.info("Image converted to RGB.")
27
+
28
+ # Resize image to the target size
29
+ image = image.resize(target_size)
30
+ logger.info(f"Image resized to {target_size}.")
31
+
32
+ # Normalize the image pixels to [0, 1] range
33
+ image_array = np.array(image) / 255.0
34
+ logger.info("Image normalized to [0, 1] range.")
35
+
36
+ # Add a batch dimension to the image array
37
+ image_array = np.expand_dims(image_array, axis=0)
38
+ logger.info("Batch dimension added to image array.")
39
+
40
+ return image_array
41
+ except Exception as e:
42
+ logger.error(f"Error preprocessing image: {e}")
43
+ return None
templates/dashboard.html ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!-- templates/dashboard.html -->
2
+
3
+ <!DOCTYPE html>
4
+ <html lang="en">
5
+ <head>
6
+ <meta charset="UTF-8">
7
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
8
+ <title>Poultry Health Dashboard</title>
9
+ </head>
10
+ <body>
11
+ <h1>Poultry Health Dashboard</h1>
12
+ <p>Last Updated: {{ last_updated }}</p>
13
+
14
+ <h2>Recent Alerts</h2>
15
+ <ul>
16
+ {% for alert in alerts %}
17
+ <li>{{ alert }}</li>
18
+ {% endfor %}
19
+ </ul>
20
+ </body>
21
+ </html>