File size: 12,549 Bytes
7de8b6b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
"""
Hospital Resource Optimizer
Optimizes staff allocation, bed management, and emergency preparedness
"""

import pandas as pd
import numpy as np
from datetime import datetime, timedelta
import config

class HospitalResourceOptimizer:
    """Optimize hospital resources based on predictions"""
    
    def __init__(self):
        self.icu_capacity = config.ICU_CAPACITY
        self.critical_threshold = config.CRITICAL_THRESHOLD
        self.staff_ratio = config.STAFF_PER_10_PATIENTS
        
    def calculate_staff_requirements(self, predicted_admissions, predicted_icu, predicted_workload):
        """
        Calculate optimal staff allocation
        
        Args:
            predicted_admissions: Array of predicted emergency admissions
            predicted_icu: Array of predicted ICU demand
            predicted_workload: Array of predicted staff workload
            
        Returns:
            Dictionary with staff recommendations
        """
        # Base staff from emergency admissions
        base_staff = np.ceil(predicted_admissions * self.staff_ratio / 10)
        
        # Additional staff for ICU (ICU needs 2x staff ratio)
        icu_staff = np.ceil(predicted_icu * self.staff_ratio / 5)
        
        # Workload-based adjustment (already calculated by predictor)
        workload_staff = predicted_workload
        
        # Take maximum to be safe
        total_staff = np.maximum(base_staff, workload_staff)
        total_staff += icu_staff * 0.5  # ICU staff partially overlaps
        
        # Round up and ensure minimum
        total_staff = np.ceil(total_staff).astype(int)
        total_staff = np.maximum(total_staff, 5)  # Minimum 5 staff always
        
        # Categorize by shift (assuming 8-hour shifts)
        shifts = []
        for i in range(0, len(total_staff), 8):
            shift_staff = total_staff[i:i+8].mean()
            shifts.append({
                'shift_start_hour': i,
                'required_staff': int(np.ceil(shift_staff)),
                'peak_hour_staff': int(total_staff[i:i+8].max()),
                'min_hour_staff': int(total_staff[i:i+8].min())
            })
        
        return {
            'hourly_staff': total_staff,
            'shifts': shifts,
            'total_staff_24h': int(total_staff[:24].sum()),
            'peak_staff': int(total_staff.max()),
            'avg_staff': float(total_staff.mean())
        }
    
    def assess_bed_capacity(self, predicted_admissions, predicted_icu, current_occupancy=50):
        """
        Assess bed capacity and recommend actions
        
        Args:
            predicted_admissions: Array of predicted admissions
            predicted_icu: Array of predicted ICU demand
            current_occupancy: Current bed occupancy
            
        Returns:
            Dictionary with bed management recommendations
        """
        # Estimate bed turnover (assume 24-hour average stay)
        hourly_turnover = current_occupancy / 24
        
        # Projected occupancy
        net_admissions = predicted_admissions - hourly_turnover
        projected_occupancy = current_occupancy + np.cumsum(net_admissions)
        
        # ICU capacity check
        icu_utilization = predicted_icu / self.icu_capacity
        
        # Identify critical periods
        critical_hours = np.where(icu_utilization > self.critical_threshold)[0]
        
        recommendations = {
            'projected_occupancy': projected_occupancy,
            'icu_utilization': icu_utilization,
            'critical_hours': critical_hours.tolist(),
            'max_icu_utilization': float(icu_utilization.max()),
            'avg_icu_utilization': float(icu_utilization.mean())
        }
        
        # Generate alerts
        alerts = []
        if len(critical_hours) > 0:
            alerts.append({
                'severity': 'HIGH',
                'message': f'ICU capacity will exceed {self.critical_threshold*100:.0f}% in {len(critical_hours)} hours',
                'action': 'Prepare overflow ICU beds, contact additional ICU staff'
            })
        
        if icu_utilization.max() > 0.95:
            alerts.append({
                'severity': 'CRITICAL',
                'message': 'ICU capacity near maximum',
                'action': 'Activate emergency protocols, consider patient transfers'
            })
        
        if predicted_admissions.sum() > predicted_admissions.mean() * 48 * 1.5:
            alerts.append({
                'severity': 'MEDIUM',
                'message': 'Unusually high admission volume predicted',
                'action': 'Increase emergency department staff, prepare additional beds'
            })
        
        recommendations['alerts'] = alerts
        return recommendations
    
    def create_emergency_preparedness_plan(self, staff_req, bed_assess):
        """
        Create comprehensive emergency preparedness plan
        
        Args:
            staff_req: Staff requirements dictionary
            bed_assess: Bed assessment dictionary
            
        Returns:
            Formatted preparedness plan
        """
        plan = {
            'timestamp': datetime.now().isoformat(),
            'planning_horizon': '48 hours',
            'status': 'NORMAL',
            'recommendations': []
        }
        
        # Determine status
        if bed_assess['max_icu_utilization'] > 0.95:
            plan['status'] = 'CRITICAL'
        elif bed_assess['max_icu_utilization'] > self.critical_threshold or len(bed_assess['alerts']) > 0:
            plan['status'] = 'ELEVATED'
        
        # Staff recommendations
        plan['recommendations'].append({
            'category': 'Staffing',
            'priority': 'HIGH',
            'details': [
                f"Peak staff requirement: {staff_req['peak_staff']} personnel",
                f"Average staff needed: {staff_req['avg_staff']:.1f} personnel per hour",
                f"Total staff-hours (24h): {staff_req['total_staff_24h']} hours",
                f"Recommended shift configuration: {len(staff_req['shifts'])} shifts of 8 hours"
            ]
        })
        
        # Bed management
        plan['recommendations'].append({
            'category': 'Bed Management',
            'priority': 'HIGH' if bed_assess['max_icu_utilization'] > self.critical_threshold else 'MEDIUM',
            'details': [
                f"Expected peak ICU utilization: {bed_assess['max_icu_utilization']*100:.1f}%",
                f"Average ICU utilization: {bed_assess['avg_icu_utilization']*100:.1f}%",
                f"Critical periods: {len(bed_assess['critical_hours'])} hours above threshold"
            ]
        })
        
        # Add alerts
        if bed_assess['alerts']:
            plan['recommendations'].append({
                'category': 'Alerts',
                'priority': 'URGENT',
                'details': [alert['message'] + ' → ' + alert['action'] for alert in bed_assess['alerts']]
            })
        
        # Resource mobilization
        if plan['status'] != 'NORMAL':
            plan['recommendations'].append({
                'category': 'Resource Mobilization',
                'priority': 'HIGH',
                'details': [
                    'Contact on-call staff for potential overtime',
                    'Review supply inventory (PPE, medications, equipment)',
                    'Coordinate with neighboring hospitals for transfer capacity',
                    'Activate incident command if status escalates to CRITICAL'
                ]
            })
        
        return plan
    
    def optimize(self, predicted_admissions, predicted_icu, predicted_workload, current_occupancy=50):
        """
        Main optimization function - coordinates all optimization tasks
        
        Returns:
            Complete optimization results and recommendations
        """
        # Calculate staff requirements
        staff_req = self.calculate_staff_requirements(
            predicted_admissions, 
            predicted_icu, 
            predicted_workload
        )
        
        # Assess bed capacity
        bed_assess = self.assess_bed_capacity(
            predicted_admissions,
            predicted_icu,
            current_occupancy
        )
        
        # Create preparedness plan
        preparedness_plan = self.create_emergency_preparedness_plan(
            staff_req,
            bed_assess
        )
        
        return {
            'staff_requirements': staff_req,
            'bed_assessment': bed_assess,
            'preparedness_plan': preparedness_plan
        }

def demo():
    """Demo the optimizer with sample predictions"""
    print("=== Hospital Resource Optimizer Demo ===\n")
    
    # Load sample predictions (or create synthetic ones)
    # Simulate 48 hours of predictions
    np.random.seed(42)
    
    hours = 48
    predicted_admissions = np.random.poisson(2.5, hours)  # ~2-3 per hour
    predicted_icu = np.random.poisson(0.4, hours)  # ~15% need ICU
    predicted_workload = predicted_admissions * 1.2 + np.random.randint(0, 3, hours)
    
    # Add a surge event at hour 30-36
    predicted_admissions[30:36] *= 2
    predicted_icu[30:36] = np.clip(predicted_icu[30:36] * 2, 0, config.ICU_CAPACITY)
    
    print(f"Simulating predictions for next {hours} hours")
    print(f"Expected admissions: {predicted_admissions.sum()}")
    print(f"Expected ICU demand: {predicted_icu.sum()}")
    print(f"Peak hour admissions: {predicted_admissions.max()}\n")
    
    # Optimize
    optimizer = HospitalResourceOptimizer()
    results = optimizer.optimize(
        predicted_admissions,
        predicted_icu,
        predicted_workload,
        current_occupancy=60
    )
    
    # Display results
    print("=== OPTIMIZATION RESULTS ===\n")
    
    print(f"Status: {results['preparedness_plan']['status']}")
    print(f"\n--- Staff Requirements ---")
    print(f"Peak staff needed: {results['staff_requirements']['peak_staff']} personnel")
    print(f"Average staff per hour: {results['staff_requirements']['avg_staff']:.1f}")
    print(f"Total staff-hours (24h): {results['staff_requirements']['total_staff_24h']}")
    
    print(f"\n--- Shift Recommendations ---")
    for shift in results['staff_requirements']['shifts'][:3]:  # First 3 shifts
        print(f"  Hour {shift['shift_start_hour']:02d}-{shift['shift_start_hour']+7:02d}: "
              f"{shift['required_staff']} staff (peak: {shift['peak_hour_staff']})")
    
    print(f"\n--- Bed Management ---")
    print(f"Max ICU utilization: {results['bed_assessment']['max_icu_utilization']*100:.1f}%")
    print(f"Avg ICU utilization: {results['bed_assessment']['avg_icu_utilization']*100:.1f}%")
    print(f"Critical hours: {len(results['bed_assessment']['critical_hours'])}")
    
    if results['bed_assessment']['alerts']:
        print(f"\n--- ALERTS ---")
        for alert in results['bed_assessment']['alerts']:
            print(f"  [{alert['severity']}] {alert['message']}")
            print(f"    → {alert['action']}")
    
    print(f"\n--- Recommendations ---")
    for rec in results['preparedness_plan']['recommendations']:
        print(f"\n{rec['category']} (Priority: {rec['priority']})")
        for detail in rec['details']:
            print(f"  • {detail}")
    
    # Save results
    import json
    with open('optimization_results.json', 'w') as f:
        # Convert numpy types to native Python types for JSON
        results_json = {
            'staff_requirements': {
                'peak_staff': int(results['staff_requirements']['peak_staff']),
                'avg_staff': float(results['staff_requirements']['avg_staff']),
                'total_staff_24h': int(results['staff_requirements']['total_staff_24h']),
                'shifts': results['staff_requirements']['shifts']
            },
            'bed_assessment': {
                'max_icu_utilization': float(results['bed_assessment']['max_icu_utilization']),
                'avg_icu_utilization': float(results['bed_assessment']['avg_icu_utilization']),
                'critical_hours_count': len(results['bed_assessment']['critical_hours']),
                'alerts': results['bed_assessment']['alerts']
            },
            'preparedness_plan': results['preparedness_plan']
        }
        json.dump(results_json, f, indent=2)
    
    print("\n\nResults saved to optimization_results.json")
    
    return results

if __name__ == "__main__":
    demo()