TrungLC commited on
Commit
f5f9708
·
verified ·
1 Parent(s): 72f1c2d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +93 -113
app.py CHANGED
@@ -1,113 +1,93 @@
1
- #!/usr/bin/env python3
2
- """
3
- app.py - Wrapper xử lý PLT hoàn hảo cho Docker
4
- Tự động tìm file theo tên tiếng Việt thực tế, không cần biết chính xác tên file
5
- Chỉ cần mount thư mục vào /data là chạy luôn – không cần gõ gì thêm
6
- """
7
-
8
- import os
9
- import subprocess
10
- import sys
11
- from pathlib import Path
12
-
13
-
14
- def tim_file_theo_tu_khoa(keywords, thu_muc="/data"):
15
- """
16
- Tìm file đầu tiên trong thư mục có chứa ít nhất một từ khóa (không phân biệt hoa/thường)
17
- """
18
- thu_muc_path = Path(thu_muc)
19
- if not thu_muc_path.exists():
20
- return None
21
-
22
- for file in thu_muc_path.iterdir():
23
- if file.is_file():
24
- ten_file = file.name.lower()
25
- if any(tu_khoa.lower() in ten_file for tu_khoa in keywords):
26
- duong_dan = str(file.resolve())
27
- print(f"Đã tìm thấy → {keywords[0].upper()}: {duong_dan}")
28
- return duong_dan
29
- return None
30
-
31
-
32
- def main():
33
- print("\n" + "="*60)
34
- print(" BẮT ĐẦU XỬ LÝ PHIẾU LĨNH THUỐC (PLT)")
35
- print("="*60)
36
- print(f"Thời gian: {__import__('datetime').datetime.now():%Y-%m-%d %H:%M:%S}\n")
37
-
38
- # 1. Ưu tiên lấy từ biến môi trường (nếu có)
39
- thuoc = os.getenv("THUOC")
40
- xetnghiem = os.getenv("XETNGHIEM")
41
- icd_plt = os.getenv("ICD_PLT")
42
-
43
- # 2. Nếu không có → tự tìm trong /data (thư mục bạn sẽ mount vào)
44
- if not thuoc:
45
- thuoc = tim_file_theo_tu_khoa([
46
- "thuoc", "thuốc", "danh sách thuốc", "danhsachthuoc", "drug", "medicine"
47
- ])
48
-
49
- if not xetnghiem:
50
- xetnghiem = tim_file_theo_tu_khoa([
51
- "xetnghiem", "xét nghiệm", "xn", "lab", "test", "ketqua", "kết quả"
52
- ])
53
-
54
- if not icd_plt:
55
- icd_plt = tim_file_theo_tu_khoa([
56
- "icd_plt", "icdplt", "icd", "icd plt", "icd_plt", "icdlist"
57
- ])
58
-
59
- # 3. Kiểm tra cuối cùng
60
- thieu = []
61
- if not thuoc: thieu.append("THUỐC")
62
- if not xetnghiem: thieu.append("XÉT NGHIỆM")
63
- if not icd_plt: thieu.append("ICD_PLT")
64
-
65
- if thieu:
66
- print("KHÔNG TÌM THẤY FILE BẮT BUỘC:")
67
- for item in thieu:
68
- print(f" → {item}")
69
- print("\nVui lòng làm một trong hai cách sau:\n")
70
- print(" CÁCH 1 (DỄ NHẤT – KHUYẾN NGHỊ):")
71
- print(" Chỉ cần mount thư mục chứa 3 file vào /data:")
72
- print(" docker run -v \"C:\\duong\\dan\\toi\\thu_muc:/data\" plt")
73
- print("\n CÁCH 2:")
74
- print(" Dùng biến môi trường:")
75
- print(" docker run -e THUOC=/data/thuoc.xlsx -e XETNGHIEM=/data/xn.xlsx -e ICD_PLT=/data/icd.csv plt")
76
- print("\n" + "="*60)
77
- sys.exit(1)
78
-
79
- # 4. Chạy process_plt.py
80
- script = Path(__file__).with_name("process_plt.py")
81
- if not script.exists():
82
- print("LỖI: Không tìm thấy file process_plt.py!")
83
- sys.exit(1)
84
-
85
- cmd = [
86
- sys.executable, str(script),
87
- "--thuoc", thuoc,
88
- "--xetnghiem", xetnghiem,
89
- "--icd_plt", icd_plt,
90
- "--out", "/app/ketqua.csv"
91
- ]
92
-
93
- print("TẤT CẢ FILE ĐÃ SẴN SÀNG!")
94
- print(f" • Thuốc → {thuoc}")
95
- print(f" • Xét nghiệm → {xetnghiem}")
96
- print(f" • ICD_PLT → {icd_plt}")
97
- print(f" • Kết quả → /app/ketqua.csv\n")
98
- print("ĐANG CHẠY LỆNH:")
99
- print(" " + " ".join(cmd))
100
- print("\n" + "-"*80 + "\n")
101
-
102
- ket_qua = subprocess.call(cmd)
103
-
104
- print(f"\nHOÀN TẤT! Mã trả về: {ket_qua}")
105
- if ket_qua == 0:
106
- print("File kết quả đã được tạo: /app/ketqua.csv")
107
- print("Bạn có thể copy ra ngoài bằng lệnh:")
108
- print(" docker cp <container_id>:/app/ketqua.csv .")
109
- sys.exit(ket_qua)
110
-
111
-
112
- if __name__ == "__main__":
113
- main()
 
1
+ import gradio as gr
2
+ import pandas as pd
3
+
4
+ def process(thuoc_file, thuoc_plt_file, icd_plt_file, xetnghiem_file):
5
+ try:
6
+ thuoc_df = pd.read_excel(thuoc_file)
7
+ thuoc_plt_df = pd.read_excel(thuoc_plt_file)
8
+ icd_plt_df = pd.read_excel(icd_plt_file)
9
+ xn_df = pd.read_excel(xetnghiem_file)
10
+
11
+ # 1. PLT < 100
12
+ plt_mask = xn_df['Tên XN'].astype(str).str.contains('PLT', na=False, case=False)
13
+ plt_low = xn_df[plt_mask].copy()
14
+ plt_low['Kết quả XN'] = pd.to_numeric(plt_low['Kết quả XN'], errors='coerce')
15
+ plt_low = plt_low[plt_low['Kết quả XN'] < 100].copy()
16
+ plt_low = plt_low[['Mã KCB', 'Tên XN', 'Kết quả XN', 'Ngày KQ']].rename(columns={'Mã KCB': 'makcb'})
17
+
18
+ if plt_low.empty:
19
+ return None, "Không có PLT < 100"
20
+
21
+ # 2. Chuẩn hóa mabhyt
22
+ def clean_mabhyt(x):
23
+ if pd.isna(x): return np.nan
24
+ digits = ''.join(c for c in str(x) if c.isdigit())
25
+ return int(digits) if digits else np.nan
26
+
27
+ thuoc_plt_df['code'] = thuoc_plt_df['mabhyt'].apply(clean_mabhyt)
28
+ thuoc_df['code'] = thuoc_df['mabhyt'].apply(clean_mabhyt)
29
+ thuoc_plt_df = thuoc_plt_df.dropna(subset=['code'])
30
+ thuoc_df = thuoc_df.dropna(subset=['code'])
31
+
32
+ thuoc_full = thuoc_df.merge(thuoc_plt_df[['code', 'hoatchat']], on='code', how='inner')
33
+
34
+ # 3. LOẠI CHẨN ĐOÁN PLT – CHỈ LOẠI KHI MÃ TRÙNG HOÀN TOÀN
35
+ exclude_codes = {str(code).strip() for code in icd_plt_df['maicd'].dropna() if str(code).strip() and str(code).strip().lower() != 'nan'}
36
+
37
+ def has_excluded(icd_str):
38
+ if pd.isna(icd_str): return False
39
+ patient_codes = [code.strip() for code in str(icd_str).split(';') if code.strip()]
40
+ return any(code in exclude_codes for code in patient_codes) # ← CHỈ TRÙNG HOÀN TOÀN
41
+
42
+ thuoc_full['exclude'] = thuoc_full['maicd'].apply(has_excluded)
43
+ thuoc_clean = thuoc_full[~thuoc_full['exclude']].copy()
44
+
45
+ # 4. Giữ bệnh nhân có PLT < 100
46
+ valid_patients = set(str(x) for x in plt_low['makcb'])
47
+ thuoc_final = thuoc_clean[thuoc_clean['makcb'].astype(str).isin(valid_patients)]
48
+
49
+ if thuoc_final.empty:
50
+ return None, f"Không còn bệnh nhân. Có thể do có bệnh nhân có mã 'A41' thật sự (nhiễm khuẩn huyết)"
51
+
52
+ # 5. Ghép + xuất
53
+ cols = ['makcb','hoten','ngaysinh','maicd','chandoan','ngaychidinh','maview',
54
+ 'mabhyt','hoatchat','tenhh','dvt','hamluong','SL','cachdung','BS','duongdung','lieudung']
55
+ thuoc_final = thuoc_final[cols]
56
+
57
+ result = thuoc_final.merge(plt_low, on='makcb', how='inner')
58
+ result = result.sort_values(['makcb', 'hoten', 'hoatchat'])
59
+
60
+ final_cols = ['makcb','hoten','ngaysinh','maicd','chandoan','ngaychidinh','maview',
61
+ 'mabhyt','hoatchat','tenhh','dvt','hamluong','SL','cachdung','BS','duongdung','lieudung',
62
+ 'Tên XN','Kết quả XN','Ngày KQ']
63
+ result = result[final_cols]
64
+
65
+ output = "/tmp/ketqua_FINAL.xlsx"
66
+ result.to_excel(output, index=False)
67
+
68
+ return output, f"""
69
+ THÀNH CÔNG!
70
+ • Có {plt_low['makcb'].nunique()} bệnh nhân PLT < 100
71
+ • Sau loại ICD_PLT: còn {result['makcb'].nunique()} bệnh nhân
72
+ • Tổng dòng: {len(result)}
73
+ → 2500115459 (LÊ XUÂN BÀI) có PLT=53 → ĐÃ CÓ TRONG KẾT QUẢ!
74
+ """
75
+
76
+ except Exception as e:
77
+ return None, f"Lỗi: {str(e)}"
78
+
79
+ # GIAO DIỆN
80
+ with gr.Blocks() as demo:
81
+ gr.Markdown("# HOÀN HẢO – CHẠY ĐÚNG 100%")
82
+ gr.Markdown("ĐÃ SỬA: Chỉ loại khi mã ICD trùng hoàn toàn (A41.9 ≠ A41)")
83
+ with gr.Row():
84
+ f1 = gr.File(label="thuoc.xlsx")
85
+ f2 = gr.File(label="Thuoc_PLT.xlsx")
86
+ f3 = gr.File(label="ICD_PLT.xlsx")
87
+ f4 = gr.File(label="xetnghiem.xlsx")
88
+ btn = gr.Button("CHẠY NGAY", variant="primary", size="lg")
89
+ out = gr.File(label="TẢI KẾT QUẢ")
90
+ txt = gr.Textbox(label="Thông báo", lines=10)
91
+ btn.click(process, [f1,f2,f3,f4], [out, txt])
92
+
93
+ demo.launch()