Upload 16 files
Browse files- README.md +89 -14
- ai_assistant.py +39 -0
- bacteria.jpeg +0 -0
- best_model_1.pkl +3 -0
- best_model_1.pklZone.Identifier +0 -0
- config.py +10 -0
- implied_susceptibility_rules.csv +101 -0
- label_encoders/anon_id_label_encoder.json +0 -0
- label_encoders/antibiotic_label_encoder.json +1 -0
- label_encoders/culture_description_label_encoder.json +1 -0
- label_encoders/ordering_mode_label_encoder.json +1 -0
- label_encoders/organism_label_encoder.json +1 -0
- label_encoders/susceptibility_label_encoder.json +1 -0
- prediction.py +65 -0
- requirements.txt +6 -0
- utils.py +32 -0
README.md
CHANGED
@@ -1,14 +1,89 @@
|
|
1 |
-
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Microbial Susceptibility Analyzer
|
2 |
+
|
3 |
+
## Overview
|
4 |
+
The Microbial Susceptibility Analyzer is a Streamlit-based web application that combines machine learning and rule-based decision making to predict antibiotic resistance patterns. The application provides:
|
5 |
+
- Susceptibility predictions for organism-antibiotic combinations
|
6 |
+
- Rule-based guidance for treatment decisions
|
7 |
+
- AI-powered explanations and recommendations
|
8 |
+
- Batch prediction capabilities for CSV datasets
|
9 |
+
|
10 |
+
## Installation
|
11 |
+
|
12 |
+
1. Clone the repository:
|
13 |
+
```bash
|
14 |
+
git clone https://github.com/yourusername/microbial-susceptibility-analyzer.git
|
15 |
+
cd microbial-susceptibility-analyzer
|
16 |
+
```
|
17 |
+
|
18 |
+
2. Create a virtual environment:
|
19 |
+
```bash
|
20 |
+
python -m venv venv
|
21 |
+
source venv/bin/activate # On Windows use: venv\Scripts\activate
|
22 |
+
```
|
23 |
+
|
24 |
+
3. Install dependencies:
|
25 |
+
```bash
|
26 |
+
pip install -r requirements.txt
|
27 |
+
```
|
28 |
+
|
29 |
+
4. Set up environment variables:
|
30 |
+
Create a `.streamlit/secrets.toml` file with your API keys:
|
31 |
+
```toml
|
32 |
+
OPENAI_API_KEY = "your_openai_api_key"
|
33 |
+
OPENAI_BASE_URL = "https://api.openai.com/v1"
|
34 |
+
```
|
35 |
+
|
36 |
+
## Usage
|
37 |
+
|
38 |
+
Run the application:
|
39 |
+
```bash
|
40 |
+
streamlit run app.py
|
41 |
+
```
|
42 |
+
|
43 |
+
The application provides several pages:
|
44 |
+
- **Home**: Project overview and introduction
|
45 |
+
- **Susceptibility Analysis**: Single prediction interface
|
46 |
+
- **AI Assistant**: Expert system for detailed explanations
|
47 |
+
- **Data Upload**: Batch prediction for CSV files
|
48 |
+
- **About**: Project information and contact details
|
49 |
+
|
50 |
+
## File Structure
|
51 |
+
|
52 |
+
```
|
53 |
+
microbial-susceptibility-analyzer/
|
54 |
+
├── app.py # Main application file
|
55 |
+
├── prediction.py # Prediction logic
|
56 |
+
├── ai_assistant.py # AI integration
|
57 |
+
├── utils.py # Utility functions
|
58 |
+
├── config.py # Configuration settings
|
59 |
+
├── requirements.txt # Python dependencies
|
60 |
+
├── README.md # This documentation
|
61 |
+
├── label_encoders/ # Label encoding files
|
62 |
+
│ ├── organism_label_encoder.json
|
63 |
+
│ ├── antibiotic_label_encoder.json
|
64 |
+
│ └── ...
|
65 |
+
├── models/ # Trained models
|
66 |
+
│ ├── best_model.pkl
|
67 |
+
│ └── best_model_1.pkl
|
68 |
+
└── data/ # Data files
|
69 |
+
├── implied_susceptibility_rules.csv
|
70 |
+
└── microbiology_cultures_implied_susceptibility.csv
|
71 |
+
```
|
72 |
+
|
73 |
+
## Configuration
|
74 |
+
|
75 |
+
The application requires the following configuration:
|
76 |
+
|
77 |
+
1. **Model Path**: Set in `config.py`
|
78 |
+
2. **Encoder Directory**: Set in `config.py`
|
79 |
+
3. **OpenAI API**: Configure in `.streamlit/secrets.toml`
|
80 |
+
|
81 |
+
## License
|
82 |
+
|
83 |
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
84 |
+
|
85 |
+
## Contact
|
86 |
+
|
87 |
+
For questions or support, contact:
|
88 |
+
Chukwuebuka Anulunko
|
89 |
ai_assistant.py
ADDED
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# ai_assistant.py
|
2 |
+
|
3 |
+
from openai import OpenAI
|
4 |
+
import re
|
5 |
+
|
6 |
+
def initialize_openai_client(api_key, base_url):
|
7 |
+
"""Initialize the OpenAI client."""
|
8 |
+
return OpenAI(api_key=api_key, base_url=base_url)
|
9 |
+
|
10 |
+
def generate_system_message(current_organism, current_antibiotic, current_was_positive):
|
11 |
+
"""Generate a dynamic system message for the AI Assistant."""
|
12 |
+
system_message = """
|
13 |
+
You are a clinical microbiology AI assistant. Analyze susceptibility results considering:
|
14 |
+
1) Model predictions 2) CLSI/EUCAST guidelines 3) Local resistance patterns.
|
15 |
+
Provide: Interpretation, therapy options, resistance mechanisms, and infection control measures.
|
16 |
+
"""
|
17 |
+
|
18 |
+
if all([current_organism, current_antibiotic, current_was_positive is not None]):
|
19 |
+
system_message += f"""
|
20 |
+
CONTEXTUAL NOTES:
|
21 |
+
- Current organism: {current_organism}
|
22 |
+
- Current antibiotic: {current_antibiotic}
|
23 |
+
- Culture positivity: {'Positive' if current_was_positive else 'Negative'}
|
24 |
+
"""
|
25 |
+
|
26 |
+
return system_message
|
27 |
+
|
28 |
+
# In ai_assistant.py
|
29 |
+
|
30 |
+
def get_ai_response(client, prompt):
|
31 |
+
"""Get a response from the AI Assistant."""
|
32 |
+
response = client.chat.completions.create(
|
33 |
+
model="deepseek-chat",
|
34 |
+
messages=[
|
35 |
+
{"role": "system", "content": "You are a clinical microbiology AI assistant."},
|
36 |
+
{"role": "user", "content": prompt}
|
37 |
+
]
|
38 |
+
).choices[0].message.content
|
39 |
+
return response
|
bacteria.jpeg
ADDED
![]() |
best_model_1.pkl
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:02eeb4beb89219d8a0afdf20a5a2cc9c1ea6e77937214568cd4287f8c815eee4
|
3 |
+
size 15174394
|
best_model_1.pklZone.Identifier
ADDED
File without changes
|
config.py
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# config.py
|
2 |
+
|
3 |
+
|
4 |
+
# File paths
|
5 |
+
MODEL_PATH = 'best_model_1.pkl'
|
6 |
+
ENCODER_DIR = 'label_encoders'
|
7 |
+
|
8 |
+
# OpenAI API key (stored in Streamlit secrets)
|
9 |
+
OPENAI_API_KEY =st.secrets["DEEPSEEK_API_KEY"]
|
10 |
+
OPENAI_BASE_URL = "https://api.deepseek.com"
|
implied_susceptibility_rules.csv
ADDED
@@ -0,0 +1,101 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
organism,antibiotic,implied_susceptibility,rationale
|
2 |
+
ACINETOBACTER,Aztreonam,Resistant,
|
3 |
+
ACINETOBACTER,Cefazolin,Resistant,
|
4 |
+
ACINETOBACTER,Minocycline,Resistant,
|
5 |
+
ACINETOBACTER,Tetracycline,Resistant,
|
6 |
+
ACINETOBACTER,Doripenem,Same as Meropenem if reported,
|
7 |
+
ACINETOBACTER,Meropenem,Susceptible if susceptible to Imipenem,
|
8 |
+
CITROBACTER,Ampicillin,Resistant,
|
9 |
+
CITROBACTER,Cefazolin,Resistant,
|
10 |
+
CITROBACTER,Cefotetan,Resistant,
|
11 |
+
CITROBACTER,Cefoxitin,Resistant,
|
12 |
+
CITROBACTER,Cefepime,Susceptible if susceptible to Ceftriaxone or Cefotaxime,
|
13 |
+
CITROBACTER,Ceftazidime,Susceptible if susceptible to Ceftriaxone or Cefotaxime,
|
14 |
+
ACINETOBACTER,Ceftriaxone,Same as Cefotaxime if reported,
|
15 |
+
ACINETOBACTER,Cefotaxime,Same as Ceftriaxone if reported,
|
16 |
+
ACINETOBACTER,Ertapenem,Susceptible if susceptible to Ceftriaxone or Cefotaxime,
|
17 |
+
ACINETOBACTER,Imipenem,Susceptible if susceptible to Ceftriaxone or Cefotaxime,
|
18 |
+
ACINETOBACTER,Meropenem,Susceptible if susceptible to Imipenem, Ceftriaxone, or Cefotaxime,
|
19 |
+
Enterobacter,Ampicillin,Resistant,
|
20 |
+
Enterobacter,Cefazolin,Resistant,
|
21 |
+
Enterobacter,Cefepime,Susceptible if susceptible to Ceftriaxone or Cefotaxime,
|
22 |
+
Enterobacter,Ceftazidime,Susceptible if susceptible to Ceftriaxone or Cefotaxime,
|
23 |
+
Enterobacter,Ceftriaxone,Same as Cefotaxime if reported,
|
24 |
+
Enterobacter,Cefotaxime,Same as Ceftriaxone if reported,
|
25 |
+
Enterobacter,Doxycycline,Susceptible if susceptible to Tetracycline, otherwise Resistant,
|
26 |
+
Enterobacter,Doripenem,Same as Meropenem if reported,
|
27 |
+
Enterobacter,Ertapenem,Susceptible if susceptible to Ceftriaxone or Cefotaxime,
|
28 |
+
Enterobacter,Imipenem,Susceptible if susceptible to Ceftriaxone or Cefotaxime,
|
29 |
+
Enterobacter,Meropenem,Susceptible if susceptible to Imipenem, Ceftriaxone, or Cefotaxime,
|
30 |
+
ESCHERICHIA COLI,Cefepime,Susceptible if susceptible to Ceftriaxone, Cefotaxime, or Cefazolin,
|
31 |
+
ESCHERICHIA COLI,Ceftazidime,Susceptible if susceptible to Ceftriaxone, Cefotaxime, or Cefazolin,
|
32 |
+
ESCHERICHIA COLI,Ceftriaxone,Same as Cefotaxime if reported,
|
33 |
+
ESCHERICHIA COLI,Cefotetan,Susceptible if susceptible to Cefazolin,
|
34 |
+
ESCHERICHIA COLI,Cefoxitin,Susceptible if susceptible to Cefazolin,
|
35 |
+
ESCHERICHIA COLI,Cefpodoxime,Same as Ceftriaxone if reported; otherwise, Susceptible if susceptible to Cefazolin,
|
36 |
+
ESCHERICHIA COLI,Cefuroxime,Susceptible if susceptible to Cefazolin,
|
37 |
+
ESCHERICHIA COLI,Doxycycline,Susceptible if susceptible to Tetracycline, otherwise Resistant,
|
38 |
+
KLEBSIELLA,Ampicillin,Resistant,
|
39 |
+
Proteus species,Tetracycline,Resistant,
|
40 |
+
Proteus species,Tigecycline,Resistant,
|
41 |
+
Proteus species,Colistin,Resistant,
|
42 |
+
Pseudomonas aeruginosa,Ampicillin,Resistant,
|
43 |
+
Pseudomonas aeruginosa,Ceftriaxone,Resistant,
|
44 |
+
Pseudomonas aeruginosa,Cefazolin,Resistant,
|
45 |
+
Pseudomonas aeruginosa,Ertapenem,Resistant,
|
46 |
+
Pseudomonas aeruginosa,Tetracycline,Resistant,
|
47 |
+
Pseudomonas aeruginosa,Tigecycline,Resistant,
|
48 |
+
Serratia,Ampicillin,Resistant,
|
49 |
+
Serratia,Cefazolin,Resistant,
|
50 |
+
Serratia,Tetracycline,Resistant
|
51 |
+
organism,antibiotic,implied_susceptibility,rationale
|
52 |
+
ACINETOBACTER,Aztreonam,Resistant,
|
53 |
+
ACINETOBACTER,Cefazolin,Resistant,
|
54 |
+
ACINETOBACTER,Minocycline,Resistant,
|
55 |
+
ACINETOBACTER,Tetracycline,Resistant,
|
56 |
+
ACINETOBACTER,Doripenem,Same as Meropenem if reported,
|
57 |
+
ACINETOBACTER,Meropenem,Susceptible if susceptible to Imipenem,
|
58 |
+
CITROBACTER,Ampicillin,Resistant,
|
59 |
+
CITROBACTER,Cefazolin,Resistant,
|
60 |
+
CITROBACTER,Cefotetan,Resistant,
|
61 |
+
CITROBACTER,Cefoxitin,Resistant,
|
62 |
+
CITROBACTER,Cefepime,Susceptible if susceptible to Ceftriaxone or Cefotaxime,
|
63 |
+
CITROBACTER,Ceftazidime,Susceptible if susceptible to Ceftriaxone or Cefotaxime,
|
64 |
+
ACINETOBACTER,Ceftriaxone,Same as Cefotaxime if reported,
|
65 |
+
ACINETOBACTER,Cefotaxime,Same as Ceftriaxone if reported,
|
66 |
+
ACINETOBACTER,Ertapenem,Susceptible if susceptible to Ceftriaxone or Cefotaxime,
|
67 |
+
ACINETOBACTER,Imipenem,Susceptible if susceptible to Ceftriaxone or Cefotaxime,
|
68 |
+
ACINETOBACTER,Meropenem,Susceptible if susceptible to Imipenem, Ceftriaxone, or Cefotaxime,
|
69 |
+
Enterobacter,Ampicillin,Resistant,
|
70 |
+
Enterobacter,Cefazolin,Resistant,
|
71 |
+
Enterobacter,Cefepime,Susceptible if susceptible to Ceftriaxone or Cefotaxime,
|
72 |
+
Enterobacter,Ceftazidime,Susceptible if susceptible to Ceftriaxone or Cefotaxime,
|
73 |
+
Enterobacter,Ceftriaxone,Same as Cefotaxime if reported,
|
74 |
+
Enterobacter,Cefotaxime,Same as Ceftriaxone if reported,
|
75 |
+
Enterobacter,Doxycycline,Susceptible if susceptible to Tetracycline, otherwise Resistant,
|
76 |
+
Enterobacter,Doripenem,Same as Meropenem if reported,
|
77 |
+
Enterobacter,Ertapenem,Susceptible if susceptible to Ceftriaxone or Cefotaxime,
|
78 |
+
Enterobacter,Imipenem,Susceptible if susceptible to Ceftriaxone or Cefotaxime,
|
79 |
+
Enterobacter,Meropenem,Susceptible if susceptible to Imipenem, Ceftriaxone, or Cefotaxime,
|
80 |
+
ESCHERICHIA COLI,Cefepime,Susceptible if susceptible to Ceftriaxone, Cefotaxime, or Cefazolin,
|
81 |
+
ESCHERICHIA COLI,Ceftazidime,Susceptible if susceptible to Ceftriaxone, Cefotaxime, or Cefazolin,
|
82 |
+
ESCHERICHIA COLI,Ceftriaxone,Same as Cefotaxime if reported,
|
83 |
+
ESCHERICHIA COLI,Cefotetan,Susceptible if susceptible to Cefazolin,
|
84 |
+
ESCHERICHIA COLI,Cefoxitin,Susceptible if susceptible to Cefazolin,
|
85 |
+
ESCHERICHIA COLI,Cefpodoxime,Same as Ceftriaxone if reported; otherwise, Susceptible if susceptible to Cefazolin,
|
86 |
+
ESCHERICHIA COLI,Cefuroxime,Susceptible if susceptible to Cefazolin,
|
87 |
+
ESCHERICHIA COLI,Doxycycline,Susceptible if susceptible to Tetracycline, otherwise Resistant,
|
88 |
+
KLEBSIELLA,Ampicillin,Resistant,
|
89 |
+
Proteus species,Tetracycline,Resistant,
|
90 |
+
Proteus species,Tigecycline,Resistant,
|
91 |
+
Proteus species,Colistin,Resistant,
|
92 |
+
Pseudomonas aeruginosa,Ampicillin,Resistant,
|
93 |
+
Pseudomonas aeruginosa,Ceftriaxone,Resistant,
|
94 |
+
Pseudomonas aeruginosa,Cefazolin,Resistant,
|
95 |
+
Pseudomonas aeruginosa,Ertapenem,Resistant,
|
96 |
+
Pseudomonas aeruginosa,Tetracycline,Resistant,
|
97 |
+
Pseudomonas aeruginosa,Tigecycline,Resistant,
|
98 |
+
Serratia,Ampicillin,Resistant,
|
99 |
+
Serratia,Cefazolin,Resistant,
|
100 |
+
Serratia,Cefazolin,Resistant
|
101 |
+
Serratia,Tetracycline,Resistant
|
label_encoders/anon_id_label_encoder.json
ADDED
The diff for this file is too large to render.
See raw diff
|
|
label_encoders/antibiotic_label_encoder.json
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
{"Amikacin": 0, "Amoxicillin/Clavulanic Acid": 1, "Ampicillin": 2, "Ampicillin/Sulbactam": 3, "Aztreonam": 4, "Cefazolin": 5, "Cefepime": 6, "Cefiderocol": 7, "Cefotaxime": 8, "Cefotetan": 9, "Cefoxitin": 10, "Cefpodoxime": 11, "Ceftaroline": 12, "Ceftazidime": 13, "Ceftazidime/Avibactam": 14, "Ceftolozane/Tazobactam": 15, "Ceftriaxone": 16, "Cefuroxime": 17, "Cephalexin/Cephalothin": 18, "Chloramphenicol": 19, "Ciprofloxacin": 20, "Clarithromycin": 21, "Clindamycin": 22, "Colistin": 23, "Daptomycin": 24, "Doripenem": 25, "Doxycycline": 26, "Ertapenem": 27, "Erythromycin": 28, "Fosfomycin": 29, "Gentamicin": 30, "Imipenem": 31, "Imipenem/Ebactam": 32, "Levofloxacin": 33, "Linezolid": 34, "Meropenem": 35, "Meropenem/Vaborbactam": 36, "Metronidazole": 37, "Minocycline": 38, "Moxifloxacin": 39, "Nitrofurantoin": 40, "Null": 41, "Oxacillin": 42, "Penicillin": 43, "Piperacillin": 44, "Piperacillin/Tazobactam": 45, "Quinupristin/Dalfopristin": 46, "Streptomycin": 47, "Tetracycline": 48, "Ticacarcillin/Clavulanic Acid": 49, "Ticarcillin": 50, "Tigecycline": 51, "Tobramycin": 52, "Trimethoprim/Sulfamethoxazole": 53, "Vancomycin": 54}
|
label_encoders/culture_description_label_encoder.json
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
{"BLOOD": 0, "RESPIRATORY": 1, "URINE": 2}
|
label_encoders/ordering_mode_label_encoder.json
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
{"Inpatient": 0, "Null": 1, "Outpatient": 2}
|
label_encoders/organism_label_encoder.json
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
{"ABIOTROPHIA SPECIES (OR GRANULICATELLA SPECIES)": 0, "ACHROMOBACTER SPECIES": 1, "ACHROMOBACTER XYLOSOXIDANS": 2, "ACID FAST BACILLI": 3, "ACID FAST BACILLI DETECTED IN LIQUID MEDIUM": 4, "ACINETOBACTER BAUMANNII": 5, "ACINETOBACTER BAUMANNII COMPLEX": 6, "ACINETOBACTER HAEMOLYTICUS": 7, "ACINETOBACTER LWOFFI": 8, "ACINETOBACTER SPECIES": 9, "ACTINOMYCES SPECIES": 10, "AEROCOCCUS SANGUINICOLA": 11, "AEROCOCCUS SPECIES": 12, "AEROCOCCUS URINAE": 13, "AEROMONAS CAVIAE": 14, "AEROMONAS HYDROPHILA GROUP": 15, "AEROMONAS SPECIES": 16, "AEROMONAS VERONII": 17, "ALCALIGENES FAECALIS": 18, "ALCALIGENES SPECIES": 19, "ANAEROBIC GRAM NEGATIVE RODS": 20, "ANAEROBIC GRAM POSITIVE COCCI": 21, "ANAEROBIC GRAM POSITIVE RODS": 22, "ARCANOBACTERIUM HAEMOLYTICUM": 23, "BACILLUS SPECIES": 24, "BACTEROIDES CACCAE": 25, "BACTEROIDES FRAGILIS": 26, "BACTEROIDES OVATUS": 27, "BACTEROIDES SPECIES": 28, "BACTEROIDES SPECIES NOT FRAGILIS": 29, "BACTEROIDES THETAIOTAOMICRON": 30, "BACTEROIDES UNIFORMIS": 31, "BACTEROIDES UREOLYTICUS": 32, "BACTEROIDES VULGATUS": 33, "BETA STREPTOCOCCUS GROUP C": 34, "BETA STREPTOCOCCUS GROUP G": 35, "BETA STREPTOCOCCUS SPECIES": 36, "BORDETELLA BRONCHISEPTICA": 37, "BREVIBACTERIUM SPECIES": 38, "BREVUNDIMONAS": 39, "BURKHOLDERIA CENOCEPACIA": 40, "BURKHOLDERIA CEPACIA": 41, "BURKHOLDERIA CEPACIA COMPLEX": 42, "BURKHOLDERIA CEPACIA COMPLEX GENOMOVAR I": 43, "BURKHOLDERIA GLADIOLI": 44, "BURKHOLDERIA MULTIVORANS": 45, "BURKHOLDERIA VIETNAMIENSIS": 46, "CAMPYLOBACTER SPECIES": 47, "CHROMOGENIC AFB, NOT M.TUBERCULOSIS": 48, "CHRYSEOBACTERIUM INDOLOGENES": 49, "CHRYSEOBACTERIUM SPECIES": 50, "CHRYSEOMONAS LUTEOLA": 51, "CITROBACTER AMALONATICUS COMPLEX": 52, "CITROBACTER BRAAKII": 53, "CITROBACTER FREUNDII": 54, "CITROBACTER FREUNDII COMPLEX": 55, "CITROBACTER FREUNDII COMPLEX (CARBAPENEM RESISTANT)": 56, "CITROBACTER KOSERI": 57, "CITROBACTER KOSERI (CARBAPENEM RESISTANT)": 58, "CITROBACTER SPECIES": 59, "CITROBACTER YOUNGAE": 60, "CLOSTRIDIUM CLOSTRIDIOFORME": 61, "CLOSTRIDIUM INNOCUUM": 62, "CLOSTRIDIUM PARAPUTRIFICUM": 63, "CLOSTRIDIUM PERFRINGENS": 64, "CLOSTRIDIUM RAMOSUM": 65, "CLOSTRIDIUM SEPTICUM": 66, "CLOSTRIDIUM SORDELLII": 67, "CLOSTRIDIUM SPECIES": 68, "CLOSTRIDIUM SPECIES, NOT PERFRINGENS": 69, "CLOSTRIDIUM TERTIUM": 70, "COAG NEGATIVE STAPHYLOCOCCUS": 71, "COMAMONAS ACIDOVORANS": 72, "CORYNEBAC. STRIATUM/AMYCOLATUM": 73, "CORYNEBACTERIUM ACCOLENS": 74, "CORYNEBACTERIUM AMYCOLATUM": 75, "CORYNEBACTERIUM DIPTHERIAE": 76, "CORYNEBACTERIUM GROUP F-1": 77, "CORYNEBACTERIUM JEIKEIUM": 78, "CORYNEBACTERIUM MACGINLEYI": 79, "CORYNEBACTERIUM PROPINQUUM": 80, "CORYNEBACTERIUM PSEUDODIPHTHERITICUM": 81, "CORYNEBACTERIUM SPECIES": 82, "CORYNEBACTERIUM SPECIES, NOT C. UREALYTICUM": 83, "CORYNEBACTERIUM STRIATUM": 84, "CORYNEBACTERIUM UREALYTICUM": 85, "CRONOBACTER SAKAZAKII": 86, "CULTURE POSITIVE GRAM NEGATIVE COCCI": 87, "CULTURE POSITIVE GRAM POSITIVE COCCI": 88, "DERMABACTER HOMINIS": 89, "DIPHTHEROIDS - CORYNEBACTERIUM SPECIES": 90, "EGGERTHELLA LENTA": 91, "ELIZABETHKINGIA MENINGOSEPTICA": 92, "ELIZABETHKINGIA SPECIES": 93, "ENTERIC GRAM NEGATIVE RODS": 94, "ENTEROBACTER AMNIGENUS 1": 95, "ENTEROBACTER ASBURIAE": 96, "ENTEROBACTER CANCEROGENUS": 97, "ENTEROBACTER CLOACAE": 98, "ENTEROBACTER CLOACAE COMPLEX": 99, "ENTEROBACTER CLOACAE COMPLEX (CARBAPENEM RESISTANT)": 100, "ENTEROBACTER GERGOVIAE": 101, "ENTEROBACTER SPECIES": 102, "ENTEROBACTER TAYLORAE": 103, "ENTEROCOCCUS AVIUM": 104, "ENTEROCOCCUS CASSELIFLAVUS": 105, "ENTEROCOCCUS DURANS": 106, "ENTEROCOCCUS DURANS/HIRAE": 107, "ENTEROCOCCUS FAECALIS": 108, "ENTEROCOCCUS FAECALIS - VANCO RESISTANT": 109, "ENTEROCOCCUS FAECIUM": 110, "ENTEROCOCCUS FAECIUM - VANCO RESISTANT": 111, "ENTEROCOCCUS GALLINARUM": 112, "ENTEROCOCCUS RAFFINOSUS": 113, "ENTEROCOCCUS SPECIES": 114, "ESCHERICHIA COLI": 115, "ESCHERICHIA COLI (CARBAPENEM RESISTANT)": 116, "ESCHERICHIA FERGUSONII": 117, "ESCHERICHIA HERMANII": 118, "ESCHERICHIA SPECIES": 119, "ESCHERICHIA VULNERIS": 120, "EUBACTERIUM LENTUM": 121, "EWINGELLA AMERICANA": 122, "FLAVOBACTERIUM SPECIES": 123, "FUSOBACTERIUM NECROPHORUM": 124, "FUSOBACTERIUM NUCLEATUM": 125, "FUSOBACTERIUM SPECIES": 126, "GORDONIA SPECIES": 127, "GRAM NEGATIVE RODS": 128, "GRAM NEGATIVE RODS - NONFERM, UNIDENTIFIED": 129, "GRAM POSITIVE RODS": 130, "HAEMOPHILUS ACTINOMYCETEMCOMITANS": 131, "HAFNIA": 132, "HAFNIA ALVEI": 133, "HAFNIA ALVEI (CARBAPENEM RESISTANT)": 134, "KLEBSIELLA AEROGENES": 135, "KLEBSIELLA AEROGENES (CARBAPENEM RESISTANT)": 136, "KLEBSIELLA OXYTOCA": 137, "KLEBSIELLA OZAENAE": 138, "KLEBSIELLA PNEUMONIAE": 139, "KLEBSIELLA PNEUMONIAE (CARBAPENEM RESISTANT)": 140, "KLEBSIELLA PNEUMONIAE SSP. OZAENAE": 141, "KLEBSIELLA SPECIES": 142, "KLUYVERA ASCORBATA": 143, "KLUYVERA CRYOCRESCENS": 144, "KLUYVERA SPECIES": 145, "LACTOBACILLUS CASEI": 146, "LACTOBACILLUS RHAMNOSUS": 147, "LACTOBACILLUS SPECIES": 148, "LACTOCOCCUS SPECIES": 149, "LACTOSE FERMENTING GRAM NEGATIVE RODS": 150, "LECLERCIA ADECARBOXYLATA": 151, "LEUCONOSTOC SPECIES": 152, "LISTERIA MONOCYTOGENES": 153, "LISTERIA SPECIES": 154, "MICROBACTERIUM SPECIES": 155, "MICROCOCCUS SPECIES": 156, "MIXED GENITAL FLORA": 157, "MORAXELLA NON-LIQUEFACIENS": 158, "MORAXELLA OSLOENSIS": 159, "MORAXELLA SPECIES": 160, "MORGANELLA MORGANII": 161, "MUCOID PSEUDOMONAS AERUGINOSA": 162, "MYCOBACTERIUM ABSCESSUS": 163, "MYCOBACTERIUM ABSCESSUS GROUP": 164, "MYCOBACTERIUM AVIUM COMPLEX": 165, "MYCOBACTERIUM AVIUM COMPLEX BY DNA PROBE": 166, "MYCOBACTERIUM CHELONAE": 167, "MYCOBACTERIUM FORTUITUM": 168, "MYCOBACTERIUM FORTUITUM SPECIES GROUP": 169, "MYCOBACTERIUM IMMUNOGENUM": 170, "MYCOBACTERIUM NEOAURUM": 171, "MYCOBACTERIUM SPECIES": 172, "MYCOBACTERIUM SPECIES - RAPID GROWER": 173, "MYCOBACTERIUM TUBERCULOSIS COMPLEX BY DNA PROBE": 174, "MYCOBACTERIUM XENOPI": 175, "MYROIDES SPECIES": 176, "NOCARDIA ASTEROIDES": 177, "NOCARDIA CYRIACIGEORGICA": 178, "NOCARDIA FARCINICA": 179, "NOCARDIA NOVA": 180, "NOCARDIA NOVA COMPLEX": 181, "NOCARDIA SPECIES": 182, "NOCARDIA TRANSVALENSIS": 183, "NOCARDIA TRANSVALENSIS COMPLEX": 184, "NON FERMENTING GRAM NEGATIVE RODS": 185, "NON LACTOSE FERMENTING GRAM NEGATIVE RODS": 186, "NON SPORE-FORMING ANAEROBIC GRAM POSITIVE RODS": 187, "NON-FERMENTING GRAM NEGATIVE RODS - NOT P.AERUGINOSA": 188, "NONFERMENTING GRAM NEGATIVE RODS - UNIDENTIFIED": 189, "NORCARDIA WALLACEI": 190, "Null": 191, "OCHROBACTRUM": 192, "OCHROBACTRUM ANTHROPI": 193, "OLIGELLA URETHRALIS": 194, "PAENIBACILLUS SPECIES": 195, "PANTOEA AGGLOMERANS": 196, "PANTOEA SPECIES": 197, "PARABACTEROIDES DISTASONIS": 198, "PARABACTEROIDES SPECIES": 199, "PASTEURELLA MULTOCIDA": 200, "PEDIOCOCCUS SP.": 201, "PEPTOSTREPTOCOCCUS SPECIES": 202, "PREVOTELLA SPECIES": 203, "PROTEUS MIRABILIS": 204, "PROTEUS SPECIES": 205, "PROTEUS VULGARIS GROUP": 206, "PROVIDENCIA RETTGERI": 207, "PROVIDENCIA SPECIES": 208, "PROVIDENCIA STUARTII": 209, "PSEUDOMONAS AERUGINOSA": 210, "PSEUDOMONAS AERUGINOSA (NON-MUCOID CF)": 211, "PSEUDOMONAS FLUORESCENS": 212, "PSEUDOMONAS FLUORESCENS GROUP": 213, "PSEUDOMONAS MENDOCINA": 214, "PSEUDOMONAS ORYZIHABITANS": 215, "PSEUDOMONAS PUTIDA": 216, "PSEUDOMONAS PUTIDA GROUP": 217, "PSEUDOMONAS SPECIES": 218, "PSEUDOMONAS SPECIES - FLUORESCENS/PUTIDA GROUP": 219, "PSEUDOMONAS SPECIES - NOT P.AERUGINOSA": 220, "PSEUDOMONAS STUTZERI": 221, "PSEUDOMONAS STUTZERI GROUP": 222, "RAHNELLA": 223, "RALSTONIA MANNITOLILYTICA": 224, "RALSTONIA SPECIES": 225, "RAOULTELLA": 226, "RAOULTELLA ORNITHINOLYTICA": 227, "RAOULTELLA PLANTICOLA": 228, "RHIZOBIUM RADIOBACTER": 229, "SALMONELLA ENTERICA": 230, "SALMONELLA SPECIES": 231, "SALMONELLA TYPHI": 232, "SCHISTOSOMA HAEMATOBIUM OVA": 233, "SERRATIA LIQUEFACIENS": 234, "SERRATIA MARCESCENS": 235, "SERRATIA MARCESCENS (CARBAPENEM RESISTANT)": 236, "SERRATIA ODORIFERA": 237, "SERRATIA PLYMUTHICA": 238, "SERRATIA RUBIDAEA": 239, "SERRATIA SPECIES": 240, "SHEWANELLA PUTREFACIENS": 241, "SHIGELLA SPECIES": 242, "SPHINGOBACTERIUM MULTIVORUM": 243, "SPHINGOBACTERIUM SPIRITIVORUM": 244, "SPHINGOMONAS": 245, "SPHINGOMONAS PAUCIMOBILIS/PARAPAUCIMOBILIS": 246, "STAPH AUREUS {MRSA}": 247, "STAPH AUREUS(COLONY VARIANT - SMALL COLONY OR OTHER MORPHOTYPE)": 248, "STAPH NEG NOT LUGDUNENSIS": 249, "STAPHYLOCOCCUS AUREUS": 250, "STAPHYLOCOCCUS COHNII": 251, "STAPHYLOCOCCUS EPIDERMIDIS": 252, "STAPHYLOCOCCUS HAEMOLYTICUS": 253, "STAPHYLOCOCCUS LUGDUNENSIS": 254, "STAPHYLOCOCCUS SAPROPHYTICUS": 255, "STAPHYLOCOCCUS SPECIES": 256, "STAPHYLOCOCCUS SPECIES - COAG NEGATIVE, NOT STAPH SAPROPHYTICUS": 257, "STAPHYLOCOCCUS SPECIES -NOT STAPH. AUREUS": 258, "STAPHYLOCOCCUS SPECIES, COAG PENDING": 259, "STENOTROPHOMONAS MALTOPHILIA": 260, "STREP. GRP D NOT ENTEROCOCCI": 261, "STREPTOCOCCUS AGALACTIAE (GROUP B)": 262, "STREPTOCOCCUS AGALACTIAE {GROUP B}": 263, "STREPTOCOCCUS ANGINOSUS": 264, "STREPTOCOCCUS ANGINOSUS GROUP": 265, "STREPTOCOCCUS BOVIS": 266, "STREPTOCOCCUS BOVIS GP.": 267, "STREPTOCOCCUS CONSTELLATUS": 268, "STREPTOCOCCUS DYSGALACTIAE": 269, "STREPTOCOCCUS DYSGALACTIAE SUBSP. EQUISIMILIS (GROUP C/G STR]": 270, "STREPTOCOCCUS GALLOLYTICUS": 271, "STREPTOCOCCUS GALLOLYTICUS, SUBSP. GALLOLYTICUS": 272, "STREPTOCOCCUS GALLOLYTICUS, SUBSP. PASTEURIANUS": 273, "STREPTOCOCCUS GORDONII": 274, "STREPTOCOCCUS INTERMEDIUS": 275, "STREPTOCOCCUS MITIS": 276, "STREPTOCOCCUS MITIS GROUP": 277, "STREPTOCOCCUS MITIS/STREPTOCOCCUS ORALIS": 278, "STREPTOCOCCUS MUTANS": 279, "STREPTOCOCCUS MUTANS GROUP": 280, "STREPTOCOCCUS ORALIS": 281, "STREPTOCOCCUS PARASANGUINIS": 282, "STREPTOCOCCUS PNEUMONIAE": 283, "STREPTOCOCCUS PYOGENES (GROUP A)": 284, "STREPTOCOCCUS PYOGENES {GROUP A}": 285, "STREPTOCOCCUS SALIVARIUS": 286, "STREPTOCOCCUS SALIVARIUS GROUP": 287, "STREPTOCOCCUS SANGUINIS": 288, "STREPTOCOCCUS SANGUIS": 289, "STREPTOCOCCUS SPECIES": 290, "STREPTOCOCCUS SPECIES - ALPHA HEMOLYTIC": 291, "STREPTOCOCCUS SPECIES - ALPHA HEMOLYTIC, NOT S.PNEUMO": 292, "TSUKAMURELLA PULMONIS": 293, "TSUKAMURELLA SPECIES": 294, "VEILLONELLA SPECIES": 295, "VIRIDANS GROUP STREPTOCOCCI": 296, "VIRIDANS GROUP STREPTOCOCCI NOT S. PNEUMONIAE": 297, "YERSINIA ENTEROCOLITICA": 298, "ZZAEROMONAS CAVIAE COMPLEX": 299, "ZZAEROMONAS HYDROPHILA COMPLEX": 300, "ZZAEROMONAS VERONII COMPLEX": 301, "ZZZBACTEROIDES DISTASONIS": 302, "ZZZBACTEROIDES FRAGILIS GROUP": 303, "ZZZBACTEROIDES NOT B. FRAGILIS GRP": 304, "ZZZCITROBACTER AMALONATICUS": 305, "ZZZCITROBACTER FARMERI": 306, "ZZZCLOSTRIDIUM SPECIES": 307, "ZZZENTEROBACTER AEROGENES": 308, "ZZZMYCOBACTERIUM MUCOGENICUM": 309, "ZZZPROPIONIBACTERIUM ACNES": 310, "ZZZPROTEUS PENNERI": 311, "ZZZPROTEUS VULGARIS": 312, "ZZZSTREPTOCOCCUS GALLOLYTICUS SUBSP. GALLOLYTICUS": 313, "ZZZSTREPTOCOCCUS GALLOLYTICUS SUBSP. PASTEURIANUS": 314}
|
label_encoders/susceptibility_label_encoder.json
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
{"Inconclusive": 0, "Intermediate": 1, "Null": 2, "Resistant": 3, "Susceptible": 4, "Synergism": 5}
|
prediction.py
ADDED
@@ -0,0 +1,65 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# prediction.py
|
2 |
+
|
3 |
+
import pandas as pd
|
4 |
+
from utils import extract_genus, load_rules
|
5 |
+
import re
|
6 |
+
|
7 |
+
rules = load_rules()
|
8 |
+
|
9 |
+
def encode_input(input_data, encoders):
|
10 |
+
"""Encode input data using label encoders."""
|
11 |
+
encoded_data = {}
|
12 |
+
for col, value in input_data.items():
|
13 |
+
if col in encoders:
|
14 |
+
try:
|
15 |
+
encoded_data[col] = encoders[col][value]
|
16 |
+
except KeyError:
|
17 |
+
return f"Error: '{value}' is not a valid option for '{col}'"
|
18 |
+
else:
|
19 |
+
encoded_data[col] = value # Numeric values pass through
|
20 |
+
return encoded_data
|
21 |
+
|
22 |
+
def decode_output(encoded_value, encoder_name, encoders):
|
23 |
+
"""Decode encoded values back to original labels."""
|
24 |
+
if encoder_name in encoders:
|
25 |
+
reverse_mapping = {v: k for k, v in encoders[encoder_name].items()}
|
26 |
+
return reverse_mapping.get(encoded_value, "Unknown")
|
27 |
+
return "Unknown"
|
28 |
+
|
29 |
+
def predict_susceptibility(input_data, model, encoders):
|
30 |
+
"""Predict susceptibility using the model and rules."""
|
31 |
+
try:
|
32 |
+
organism = input_data["organism"]
|
33 |
+
antibiotic = input_data["antibiotic"]
|
34 |
+
genus = extract_genus(organism)
|
35 |
+
|
36 |
+
# Check if any rule matches using regex
|
37 |
+
matching_rule = next((rules[key] for key in rules if re.match(fr"^{key[0]}", genus) and key[1] == antibiotic), None)
|
38 |
+
|
39 |
+
rule_output = matching_rule if matching_rule else "No specific rule found"
|
40 |
+
|
41 |
+
# Model prediction
|
42 |
+
encoded_data = encode_input(input_data, encoders)
|
43 |
+
if isinstance(encoded_data, str):
|
44 |
+
return encoded_data
|
45 |
+
|
46 |
+
encoded_df = pd.DataFrame([encoded_data])
|
47 |
+
model_prediction = model.predict(encoded_df)[0]
|
48 |
+
model_output = decode_output(model_prediction, "susceptibility", encoders)
|
49 |
+
|
50 |
+
# Apply rule override if needed
|
51 |
+
if rule_output != "No specific rule found" and rule_output != model_output:
|
52 |
+
final_output = rule_output
|
53 |
+
reason = "Rule-based correction applied."
|
54 |
+
else:
|
55 |
+
final_output = model_output
|
56 |
+
reason = "Model prediction used."
|
57 |
+
|
58 |
+
return {
|
59 |
+
"Final Output": final_output,
|
60 |
+
"Rule Guidance": rule_output,
|
61 |
+
"Model Prediction": model_output,
|
62 |
+
"Decision Reason": reason
|
63 |
+
}
|
64 |
+
except Exception as e:
|
65 |
+
return {"Error": str(e)}
|
requirements.txt
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
streamlit
|
2 |
+
scikit-learn==1.2.2
|
3 |
+
pandas
|
4 |
+
numpy
|
5 |
+
joblib
|
6 |
+
regex
|
utils.py
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# utils.py
|
2 |
+
|
3 |
+
import joblib
|
4 |
+
import json
|
5 |
+
import os
|
6 |
+
import re
|
7 |
+
|
8 |
+
def load_model(model_path):
|
9 |
+
"""Load the trained model."""
|
10 |
+
return joblib.load(model_path)
|
11 |
+
|
12 |
+
def load_label_encoders(encoder_dir):
|
13 |
+
"""Load label encoders from JSON files."""
|
14 |
+
encoders = {}
|
15 |
+
for filename in os.listdir(encoder_dir):
|
16 |
+
if filename.endswith('_label_encoder.json'):
|
17 |
+
column = filename.replace('_label_encoder.json', '')
|
18 |
+
with open(os.path.join(encoder_dir, filename), 'r') as file:
|
19 |
+
encoders[column] = json.load(file)
|
20 |
+
return encoders
|
21 |
+
|
22 |
+
def load_rules():
|
23 |
+
"""Load rule-based susceptibility rules."""
|
24 |
+
return {
|
25 |
+
("ACINETOBACTER", "Aztreonam"): "Resistant",
|
26 |
+
("ACINETOBACTER", "Cefazolin"): "Resistant",
|
27 |
+
# Add all other rules here...
|
28 |
+
}
|
29 |
+
|
30 |
+
def extract_genus(organism_name):
|
31 |
+
"""Extract the genus from the organism name."""
|
32 |
+
return organism_name.split()[0].upper()
|