Lacak Data Melalui Analisis Lengkap

Di bawah ini adalah simulasi percakapan antar komponen sistem saat analisis nyata berlangsung. Tekan Lanjut untuk menelusuri setiap pesan, atau Putar Semua untuk melihat semuanya mengalir masuk. Perhatikan bagaimana setiap komponen mengubah data sebelum meneruskannya.

US
Pengguna

Mengunggah plantation_borneo.geojson ke /api/analysis/upload

FP
FileProcessor

Berhasil membaca 3 fitur. Satu poligon berpotongan sendiri — diperbaiki otomatis. Luas: 247,3 ha.

DB
Database (PostGIS)

Menyimpan 3 plot dengan geometri PostGIS. ID Unggahan: a7f3b...

FA
ForestAnalyzer

Memulai analisis. Koordinat terdeteksi di Indonesia (ID) — risiko TINGGI sesuai Pasal 29. +20 poin.

GL
Layanan GLAD

Hansen GFC via GEE: kehilangan tutupan pohon 3,2 ha pada 2022. Peringatan pasca-batas waktu!

RD
Layanan RADD

Radar Sentinel-1 mengonfirmasi perubahan di area yang sama. 2,8 ha. Kepercayaan tinggi.

FA
ForestAnalyzer

Skor risiko: 82/100. Kehilangan hutan: 3,1%. Keputusan: TIDAK_PATUH

RG
ReportGenerator

PDF dibuat: 8 halaman dengan citra satelit, peta NDVI, tabel peringatan. Mengirim email ke pengguna.

0/8
i
Perhatikan serah terima datanya

Setiap komponen menerima data terstruktur, menambahkan konteksnya sendiri, dan meneruskan hasil yang diperkaya ke hilir. Pengguna mengirim file; ReportGenerator menerima AnalysisResult yang berisi semua informasi yang dikumpulkan sepanjang perjalanan.

Pengambilan Bersamaan dengan asyncio.gather

Kueri GLAD dan RADD bersifat independen — tidak ada yang membutuhkan hasil dari yang lain. Analyzer menjalankan keduanya secara bersamaan menggunakan async/await dan konkurensi:

Python
glad_task = self._fetch_glad_alerts(geometry, plot_id)
radd_task = self._fetch_radd_alerts(geometry, plot_id)

glad_alerts, radd_data = await asyncio.gather(
    glad_task, radd_task, return_exceptions=True
)
Penjelasan
Baris 1: Buat tugas yang akan mengkueri layanan GLAD (data optik Landsat) untuk peringatan deforestasi dalam geometri ini.
Baris 2: Buat tugas kedua yang akan mengkueri layanan RADD (data radar Sentinel-1) untuk area yang sama.
Baris 4-6: Jalankan kedua tugas secara bersamaan. Tunggu hingga keduanya selesai. Jika salah satu gagal, tangkap errornya alih-alih mematikan tugas yang lain (return_exceptions=True). Keluarkan dua hasil ke glad_alerts dan radd_data.

Tugas Aliran Data

Cara menambahkan langkah baru ke pipeline analisis

Misalnya Anda ingin menambahkan pemeriksaan biodiversitas di samping kueri GLAD dan RADD yang sudah ada.

  1. Buka backend/services/forest_analyzer_with_alerts.py dan temukan metode analyze_plot().
  2. Buat metode async baru (misalnya, _fetch_biodiversity_risk(geometry, plot_id)) yang memanggil sumber data Anda dan mengembalikan objek hasil.
  3. Tambahkan tugas baru Anda ke panggilan asyncio.gather bersama tugas GLAD dan RADD agar berjalan secara bersamaan.
  4. Keluarkan hasil baru dan tambahkan ke dict details yang dilampirkan pada AnalysisResult.
  5. Jika data baru tersebut harus memengaruhi skor risiko, perbarui logika penilaian di metode yang sama.

Cara melacak data melalui sistem

Saat melakukan debugging, ikuti rantai ini untuk menelusuri bagaimana sebuah data bergerak:

  1. Endpoint API — Temukan rute di backend/api/. Di sinilah permintaan HTTP tiba dan parameter divalidasi.
  2. Metode service — Endpoint memanggil metode di backend/services/. Di sinilah logika bisnis berada.
  3. Model data — Service membuat atau memperbarui dataclass dari backend/models/.
  4. Tabel database — Model disimpan melalui SQL di backend/utils/database.py.
  5. Respons — Hasilnya mengalir kembali ke atas: baris database → model → service → respons JSON API. Setiap lapisan menambahkan konteks.

Cara menambahkan model data baru

  1. Buat dataclass baru di file yang sesuai di bawah backend/models/ (misalnya, models/alerts.py untuk data terkait peringatan).
  2. Tambahkan metode to_dict() agar model dapat diserialisasi ke JSON untuk respons API.
  3. Gunakan model di lapisan service Anda — impor dan kembalikan instance dari metode service.
  4. Buat tabel database yang sesuai di backend/utils/database.py di dalam fungsi ensure_tables_exist(), menggunakan SQL CREATE TABLE IF NOT EXISTS.
  5. Tambahkan indeks yang diperlukan, terutama indeks spasial jika model menyertakan kolom geometri.

Pola Komunikasi

Sinkron vs Asinkron

Sistem ini menawarkan dua jalur untuk menjalankan analisis:

Sinkron (waktu-nyata): Pengguna mengunggah file, server langsung menganalisisnya, dan respons dikembalikan dalam koneksi HTTP yang sama. Unggah → analisis → tunggu → hasil. Pengguna mempertahankan koneksi terbuka selama proses berlangsung.

Asinkron (berbasis antrean): Pengguna mengunggah file dan langsung mendapatkan ID antrean. Worker latar belakang mengambil pekerjaan tersebut, menjalankan analisis, menyimpan hasil ke database, dan mengirim notifikasi email. Unggah → antrean → worker latar belakang memproses → notifikasi email.

Bayangkan seperti memesan makanan. Sinkron adalah memesan di konter — Anda berdiri dan menunggu sementara mereka membuatnya, lalu pergi dengan makanan Anda. Asinkron adalah memesan lewat pengiriman — Anda memesan, pergi melakukan hal lain, dan diberi tahu saat pesanan tiba di depan pintu Anda. Makanannya (analisis) sama saja; perbedaannya adalah apakah Anda memblokir dan menunggu atau membebaskan diri.

Jalur sinkron berada di /api/analysis/analyze/{upload_id}. Jalur asinkron menggunakan /api/queue/submit, dengan worker latar belakang di analysis_queue_worker.py yang melakukan polling untuk pekerjaan yang menunggu. Progres waktu-nyata tersedia melalui koneksi WebSocket yang dikelola oleh websocket_manager.py.

Mengapa asyncio.gather?

Ketika dua operasi tidak bergantung satu sama lain, menjalankannya satu per satu membuang waktu. Layanan GLAD mengkueri data optik Landsat dari Google Earth Engine. Layanan RADD mengkueri data radar Sentinel-1 dari GEE. Tidak ada yang membutuhkan hasil dari yang lain untuk melakukan pekerjaannya.

asyncio.gather() menjalankan kedua permintaan secara bersamaan. Jika masing-masing membutuhkan 3 detik, eksekusi berurutan akan memakan waktu 6 detik. Dengan gather, keduanya berjalan bersamaan dan totalnya kira-kira 3 detik — memangkas waktu analisis menjadi setengah.

Parameter return_exceptions=True sangat penting: jika RADD gagal (misalnya, plot berada di luar cakupan tropis), hasil GLAD tetap dipertahankan. Tanpa parameter ini, satu kegagalan akan membatalkan semuanya.

Deduplikasi Peringatan

GLAD dan RADD mungkin mendeteksi peristiwa deforestasi yang sama. GLAD melihatnya melalui citra satelit optik (Landsat, resolusi 30m). RADD melihatnya melalui radar (Sentinel-1, resolusi 10m). Area yang terdampak sering tumpang tindih tetapi jarang sama persis karena kedua sensor memiliki resolusi dan metode deteksi yang berbeda.

Untuk menghindari penghitungan ganda, sistem mengambil max(glad_area, radd_area) sebagai area deforestasi yang dilaporkan daripada menjumlahkannya. Ini memberikan estimasi yang konservatif namun jujur.

Ketika kedua sistem mendeteksi peringatan di area yang sama, sistem menandainya sebagai tervalidasi silang, yang berarti kepercayaan lebih tinggi. Deteksi dari satu sumber saja mungkin merupakan positif palsu (bayangan awan yang salah dibaca sebagai kehilangan, misalnya), tetapi dua sensor independen yang setuju membuat temuan tersebut jauh lebih andal.

Referensi Aliran Data

Langkah-langkah Pipeline Analisis

Langkah Komponen Masukan Keluaran
1. Unggah file FileProcessor GeoJSON / KML / Shapefile PlotData (geometri, area, fitur)
2. Penyimpanan PostGIS PlotData plot_id di database
3. Tutupan hutan GEE Provider geometri tutupan_2020, tutupan_saat_ini, kehilangan%
4. Peringatan GLAD Layanan GLAD geometri + rentang tanggal ada_peringatan, jumlah, area_ha, kehilangan_per_tahun
5. Peringatan RADD Layanan RADD geometri + rentang tanggal ada_peringatan, jumlah, area_ha
6. Penilaian risiko ForestAnalyzer semua di atas + kode negara skor_risiko (0–100)
7. Kepatuhan ForestAnalyzer skor_risiko + ambang batas ComplianceStatus enum
8. Laporan ReportGenerator AnalysisResult File PDF

Model Data

Model File Field Utama
PlotData models/__init__.py geometry, feature_count, total_area_hectares, bounds
AnalysisResult models/__init__.py plot_id, forest_coverage_percent, compliance_status, risk_score, details
ComplianceStatus models/__init__.py COMPLIANT | NON_COMPLIANT | NEEDS_REVIEW | UNKNOWN
RiskLevel models/__init__.py LOW | MEDIUM | HIGH | CRITICAL
DeforestationAlert models/alerts.py plot_id, alert_date, alert_type, confidence, affected_area_hectares