| import sqlite3 |
| import os |
| from src.config import DATA_DIR |
|
|
| DB_PATH = os.path.join(DATA_DIR, "brainscan.db") |
|
|
| def get_db_connection(): |
| """Membuka koneksi ke database SQLite dan mengembalikan objek koneksi""" |
| conn = sqlite3.connect(DB_PATH) |
| conn.row_factory = sqlite3.Row |
| return conn |
|
|
| def init_db(): |
| """Menginisialisasi tabel-tabel di database jika belum ada""" |
| |
| os.makedirs(os.path.dirname(DB_PATH), exist_ok=True) |
| |
| conn = get_db_connection() |
| cursor = conn.cursor() |
| |
| |
| cursor.execute(""" |
| CREATE TABLE IF NOT EXISTS patients ( |
| nik TEXT PRIMARY KEY, |
| name TEXT NOT NULL, |
| age INTEGER, |
| birth_date TEXT, |
| gender TEXT, |
| address TEXT, |
| phone TEXT, |
| created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP |
| ) |
| """) |
| |
| |
| cursor.execute(""" |
| CREATE TABLE IF NOT EXISTS scans ( |
| id INTEGER PRIMARY KEY AUTOINCREMENT, |
| patient_nik TEXT NOT NULL, |
| filename TEXT, |
| modality TEXT, |
| predicted_class TEXT NOT NULL, |
| confidence REAL NOT NULL, |
| radiology_report TEXT, |
| original_image_b64 TEXT, |
| heatmap_image_b64 TEXT, |
| created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
| FOREIGN KEY (patient_nik) REFERENCES patients(nik) ON DELETE CASCADE |
| ) |
| """) |
| |
| |
| cursor.execute(""" |
| CREATE TABLE IF NOT EXISTS dataset_distribution ( |
| kelas TEXT PRIMARY KEY, |
| sebelum_balancing INTEGER, |
| setelah_balancing INTEGER |
| ) |
| """) |
|
|
| |
| cursor.execute(""" |
| CREATE TABLE IF NOT EXISTS training_history ( |
| epoch INTEGER PRIMARY KEY, |
| train_loss REAL, |
| val_loss REAL, |
| train_acc REAL, |
| val_acc REAL, |
| train_f1 REAL, |
| val_f1 REAL, |
| epoch_time_seconds REAL |
| ) |
| """) |
|
|
| |
| cursor.execute(""" |
| CREATE TABLE IF NOT EXISTS test_evaluation_results ( |
| actual_class TEXT, |
| predicted_class TEXT, |
| count INTEGER, |
| PRIMARY KEY (actual_class, predicted_class) |
| ) |
| """) |
| |
| conn.commit() |
| conn.close() |
| print(f"Database berhasil diinisialisasi di: {DB_PATH}") |
|
|
| def save_dataset_distribution_to_db(df): |
| """Menyimpan data distribusi dataset ke database""" |
| conn = get_db_connection() |
| cursor = conn.cursor() |
| cursor.execute("DELETE FROM dataset_distribution") |
| for _, row in df.iterrows(): |
| cursor.execute(""" |
| INSERT INTO dataset_distribution (kelas, sebelum_balancing, setelah_balancing) |
| VALUES (?, ?, ?) |
| """, (row["Kelas"], int(row["Sebelum_Balancing"]), int(row["Setelah_Balancing"]))) |
| conn.commit() |
| conn.close() |
|
|
| def save_training_history_to_db(df): |
| """Menyimpan data histori training ke database""" |
| conn = get_db_connection() |
| cursor = conn.cursor() |
| cursor.execute("DELETE FROM training_history") |
| for _, row in df.iterrows(): |
| cursor.execute(""" |
| INSERT INTO training_history (epoch, train_loss, val_loss, train_acc, val_acc, train_f1, val_f1, epoch_time_seconds) |
| VALUES (?, ?, ?, ?, ?, ?, ?, ?) |
| """, (int(row["Epoch"]), float(row["Train_Loss"]), float(row["Val_Loss"]), float(row["Train_Acc"]), float(row["Val_Acc"]), float(row["Train_F1"]), float(row["Val_F1"]), float(row["Epoch_Time_Seconds"]))) |
| conn.commit() |
| conn.close() |
|
|
| def save_test_evaluation_to_db(cm, classes): |
| """Menyimpan data confusion matrix ke database""" |
| conn = get_db_connection() |
| cursor = conn.cursor() |
| cursor.execute("DELETE FROM test_evaluation_results") |
| for i, act_cls in enumerate(classes): |
| for j, pred_cls in enumerate(classes): |
| cursor.execute(""" |
| INSERT INTO test_evaluation_results (actual_class, predicted_class, count) |
| VALUES (?, ?, ?) |
| """, (act_cls, pred_cls, int(cm[i, j]))) |
| conn.commit() |
| conn.close() |
|
|
| def upsert_patient(nik, name, age=None, birth_date=None, gender=None, address=None, phone=None): |
| """Menyisipkan atau memperbarui data pasien berdasarkan NIK""" |
| conn = get_db_connection() |
| cursor = conn.cursor() |
| cursor.execute(""" |
| INSERT INTO patients (nik, name, age, birth_date, gender, address, phone) |
| VALUES (?, ?, ?, ?, ?, ?, ?) |
| ON CONFLICT(nik) DO UPDATE SET |
| name = excluded.name, |
| age = excluded.age, |
| birth_date = excluded.birth_date, |
| gender = excluded.gender, |
| address = excluded.address, |
| phone = excluded.phone |
| """, (nik, name, age, birth_date, gender, address, phone)) |
| conn.commit() |
| conn.close() |
|
|
| def get_patient(nik): |
| """Mengambil informasi pasien berdasarkan NIK""" |
| conn = get_db_connection() |
| cursor = conn.cursor() |
| cursor.execute("SELECT * FROM patients WHERE nik = ?", (nik,)) |
| row = cursor.fetchone() |
| conn.close() |
| if row: |
| return dict(row) |
| return None |
|
|
| def add_scan_record(patient_nik, filename, modality, predicted_class, confidence, report_text, original_b64=None, heatmap_b64=None): |
| """Menyimpan data riwayat pemeriksaan scan otak""" |
| conn = get_db_connection() |
| cursor = conn.cursor() |
| cursor.execute(""" |
| INSERT INTO scans (patient_nik, filename, modality, predicted_class, confidence, radiology_report, original_image_b64, heatmap_image_b64) |
| VALUES (?, ?, ?, ?, ?, ?, ?, ?) |
| """, (patient_nik, filename, modality, predicted_class, confidence, report_text, original_b64, heatmap_b64)) |
| conn.commit() |
| conn.close() |
|
|
| def get_patient_history(nik): |
| """Mengambil riwayat scan dari pasien tertentu berdasarkan NIK""" |
| conn = get_db_connection() |
| cursor = conn.cursor() |
| cursor.execute(""" |
| SELECT s.*, p.name, p.age, p.gender, p.birth_date, p.address, p.phone |
| FROM scans s |
| JOIN patients p ON s.patient_nik = p.nik |
| WHERE s.patient_nik = ? |
| ORDER BY s.created_at DESC |
| """, (nik,)) |
| rows = cursor.fetchall() |
| conn.close() |
| return [dict(row) for row in rows] |
|
|
| |
| init_db() |
|
|