Minggu, 12 Juli 2026
Sumber: NASA Earth Observatory, Joshua Stevens / MODIS data from NASA EOSDIS/LANCE and GIBS/Worldview (Smoke Blankets Borneo)
Pencemaran Udara Perkotaan dan Peranan Inversi Suhu
Pada pagi hari musim kemarau di Jakarta — kota yang kita tinggali — jutaan kendaraan mulai bergerak sementara udara masih terasa dingin dan lembap. Kondisi atmosfer saat itu diam-diam berperan krusial: polutan yang dilepas oleh kendaraan dan industri tidak tersebar ke atas, melainkan terkurung dalam selapis udara tipis di dekat permukaan. Konsentrasi PM2.5 — partikel halus berdiameter di bawah 2,5 mikrometer — melonjak tajam antara pukul 07.00 dan 09.00 WIB, tepat bersamaan dengan puncak jam sibuk yang kita lihat setiap pagi.
Mekanisme atmosfer di balik fenomena ini adalah inversi suhu (temperature inversion): kondisi di mana suhu udara justru naik seiring bertambahnya ketinggian, berlawanan dengan perilaku normal atmosfer. Ketika inversi aktif, udara permukaan yang relatif dingin tidak dapat naik ke atas, dan semua yang diemisikan dari permukaan — asap knalpot, partikel industri, uap reaktif — tetap terperangkap di bawah lapisan inversi seperti di dalam tutup panci yang rapat.
Dampaknya jauh melampaui polusi visual. Menurut WHO, sekitar 7 juta kematian dini setiap tahun disebabkan oleh polusi udara, dan PM2.5 menjadi penyebab utamanya karena partikel sekecil ini mampu menembus paru-paru dan aliran darah. Memahami inversi suhu bukan sekadar soal meteorologi — ini soal kesehatan jutaan warga kota.
Apa Itu Inversi Suhu
Dalam kondisi atmosfer normal, suhu udara turun seiring bertambahnya ketinggian. Laju penurunan rata-rata ini dikenal sebagai environmental lapse rate, yang nilainya sekitar \(6{,}5\ \text{°C/km}\) di troposfer. Untuk setiap kenaikan 1.000 meter, suhu udara rata-rata turun sekitar 6,5 derajat Celsius. Profil "hangat di bawah, dingin di atas" inilah yang memungkinkan parsel udara permukaan untuk naik, membawa uap air, polutan, dan panas ke lapisan atas melalui proses convective mixing.
Inversi suhu membalik kondisi ini. Alih-alih turun, suhu justru naik dengan ketinggian pada lapisan tertentu. Lapisan ini bersifat sangat stabil karena udara yang lebih berat dan dingin di bawah tidak punya energi kinetik yang cukup untuk menembus lapisan udara hangat di atasnya. NOAA National Weather Service merumuskannya ringkas: "An inversion is an increase of temperature with height."
Hasilnya adalah "tutup" atmosfer yang efektif. Gerakan vertikal terhenti, dan mixing height — yang kita sebut batas atas percampuran vertikal — menjadi sangat dangkal, bisa hanya 50–300 meter di atas permukaan. Semua emisi dari kendaraan, industri, dan kebakaran lahan harus berbagi ruang dalam lapisan tipis ini, tanpa bisa "lolos" ke atas.
Sumber: NOAA National Weather Service, Houston/Galveston TX Weather Forecast Office (Temperature Inversions)
Jenis-Jenis Inversi di Kota Tropis
Tidak semua inversi terbentuk dengan cara yang sama. Di kota-kota tropis seperti Jakarta, dua jenis paling sering kita jumpai.
Radiation Inversion
Ini adalah jenis yang paling umum dan paling terkait langsung dengan lonjakan PM2.5 pagi hari. Radiation inversion terbentuk pada malam hari yang cerah dengan angin lemah, ketika permukaan bumi melepaskan panas ke atmosfer melalui radiasi gelombang panjang (longwave radiation). Permukaan mendingin, lapisan udara paling bawah ikut mendingin lebih cepat dari lapisan udara di atasnya — menciptakan profil inversi yang khas.
Inversi ini biasanya dimulai tak lama setelah matahari terbenam dan mencapai intensitas maksimum menjelang fajar. Kedalamannya berkisar 50–300 meter di atas permukaan. Begitu matahari mulai memanaskan permukaan, inversi erosi dari bawah ke atas dan biasanya lenyap menjelang siang. Inilah mengapa puncak PM2.5 yang kita amati antara pukul 07.00–09.00 WIB terjadi tepat saat inversi masih kuat tetapi emisi kendaraan sudah memuncak.
Subsidence Inversion
Jenis ini lebih berbahaya karena dapat bertahan berhari-hari hingga berminggu-minggu. Subsidence inversion terbentuk ketika massa udara yang luas tenggelam (subsides) di bawah sistem tekanan tinggi. Udara yang turun memanas secara adiabatik, membentuk lapisan hangat di ketinggian sekitar 850–600 mb (kira-kira 1.500–4.000 m di atas permukaan). Lapisan hangat ini menekan batas atas planetary boundary layer sehingga mixing height mengempis drastis dan bertahan lama.
Di Indonesia, subsidence inversion paling intens selama musim kemarau (Juni–Agustus) ketika sistem tekanan tinggi benua Australia mendominasi sirkulasi regional. Inversi ini yang memperparah episode polusi perkotaan maupun asap kebakaran lahan, karena tidak ada mekanisme cuaca yang membubarkannya kecuali perubahan pola sinoptik yang signifikan.
Perlu dicatat bahwa frontal inversion — umum di lintang menengah ketika massa udara dingin menyelusup di bawah massa udara hangat — sangat jarang terjadi di dekat ekuator. Intrusi dingin dari lintang menengah hampir tidak pernah mencapai Jakarta dengan intensitas yang cukup untuk membentuk inversi frontal yang berarti.
Sumber: NOAA National Weather Service, Houston/Galveston TX Weather Forecast Office (Temperature Inversions)
Bagaimana Inversi Memerangkap Polutan
Konsep kunci yang menghubungkan inversi suhu dengan kualitas udara adalah mixing height — atau kedalaman planetary boundary layer (PBL) efektif tempat udara permukaan dapat bercampur secara vertikal. Pada hari tanpa inversi, mixing height bisa mencapai 1.500–2.000 m pada siang hari, memberikan ruang vertikal yang luas bagi polutan untuk menyebar dan terdilusi. Ketika inversi aktif, mixing height bisa menciut menjadi hanya 50–200 m — sepuluh kali lipat lebih sedikit ruang udara yang kita hirup dibandingkan hari normal.
Bayangkan seluruh emisi Jakarta — jutaan kendaraan bermotor ditambah industri kawasan Jabodetabek — harus ditampung dalam lapisan udara setebal puluhan lantai gedung, bukan ratusan. Konsentrasi PM2.5 naik hampir proporsional seiring berkurangnya ruang vertikal itu.
Rantai mekanisme: pendinginan permukaan memicu lapisan inversi yang menekan mixing height dan menumpuk PM2.5 di dekat permukaan kota.
Selama musim kemarau, kondisi ini diperparah oleh dua faktor tambahan. Pertama, tidak ada hujan yang membantu wet deposition — proses alami di mana tetesan hujan "mencuci" partikel dan gas terlarut dari udara. Kedua, kecepatan angin permukaan cenderung rendah di bawah dominasi tekanan tinggi, sehingga tidak ada adveksi horizontal yang cukup kuat untuk mengangkut polutan keluar dari kawasan kota. Akumulasi berlangsung berlapis-lapis dari hari ke hari.
PM2.5 yang terperangkap bukan ancaman pasif. Dalam pembaruan 2021, WHO menurunkan guideline tahunan menjadi 5 µg/m³ — separuh dari standar sebelumnya — karena paparan bahkan di bawah standar lama tetap menyebabkan penyakit kardiovaskular, stroke, dan kanker paru-paru. Kelompok paling rentan: anak-anak, lansia, dan penderita penyakit bawaan.
Inversi Suhu dan Episode Pencemaran Udara di Indonesia
Episode Jakarta, Juni 2022
Pada Juni 2022, BMKG merekam lonjakan PM2.5 yang signifikan di Jakarta. Konsentrasi harian mencapai puncak 148 µg/m³ pada 15 Juni — hampir 30 kali lipat guideline tahunan WHO sebesar 5 µg/m³, dan masuk kategori Tidak Sehat menurut skala nasional Indonesia (Perban No. 2/2022: 66–150 µg/m³). Rata-rata bulan Juni mencapai 41 µg/m³, diklasifikasikan Sedang secara nasional tetapi sekitar delapan kali lipat standar WHO.
Dalam siaran resminya, BMKG secara eksplisit menyebut lapisan inversi sebagai penyebab langsung akumulasi PM2.5 dekat permukaan: "lapisan di udara yang ditandai dengan peningkatan suhu udara yang seiring dengan peningkatan ketinggian lapisan." Selain inversi, faktor meteorologi pendukung meliputi kelembapan relatif tinggi yang mendorong konversi gas ke partikel, kecepatan angin rendah, dan angin permukaan dari timur yang membawa PM2.5 dari kawasan industri di pinggiran Jabodetabek ke dalam cekungan kota yang kita huni.
Kebakaran Gambut Kalimantan dan Sumatra, 2019
Episode yang lebih masif terjadi pada September 2019, ketika kebakaran gambut di Kalimantan dan Sumatra menghasilkan asap tebal yang menutup langit kedua pulau tersebut. Citra MODIS dari wahana Aqua NASA merekam selimut asap yang memblokir pandangan hingga ratusan kilometer pada 15 September 2019 — gambar yang menjadi salah satu dokumen visual paling dramatis dari krisis lingkungan Indonesia.
Yang membuat episode itu sangat parah bukan hanya volume asap, tetapi juga kondisi subsidence inversion musim kemarau yang mencegah asap naik dan menyebar ke lapisan atmosfer lebih tinggi. Tanpa mixing vertikal, konsentrasi PM2.5 di kota-kota Kalimantan seperti Palangkaraya menembus level berbahaya selama berminggu-minggu. Sekolah ditutup, penerbangan dibatalkan, dan jutaan warga terpapar partikel halus dari pembakaran gambut — secara kimiawi lebih kompleks dan toksik dibandingkan asap kayu biasa karena kandungan senyawa organik volatilnya yang tinggi.
Peat fires juga sulit dipadamkan karena gambut bisa membara di dalam tanah berbulan-bulan. Ini menciptakan sumber emisi yang hampir konstan sepanjang musim kemarau, dan setiap kali inversi aktif, konsentrasi di lapisan permukaan kembali melonjak.
El Niño sebagai Amplifier
Musim kemarau yang diperpanjang El Niño semakin memperparah kedua jenis episode. Anomali SST positif di Samudra Pasifik tengah-timur memperlemah aliran monsun, sehingga dry season yang semestinya berakhir September bisa berlanjut hingga Oktober–November — memberi lebih banyak waktu bagi subsidence inversion dan kebakaran gambut. Pola ini berulang pada El Niño 2023.
Konteks Global
WHO mencatat lebih dari 90% populasi dunia tinggal di area yang melampaui standar PM2.5 lama 10 µg/m³ — dan dengan standar 2021 sebesar 5 µg/m³, proporsi itu menjadi jauh lebih besar. Diperkirakan sekitar 80% kematian akibat PM2.5 global bisa dicegah jika standar itu tercapai.
Episode di Indonesia bukan anomali terisolasi — mereka cerminan tantangan kesehatan udara global yang berakar pada interaksi meteorologi, emisi antropogenik, dan perubahan iklim. Tidak ada intervensi kualitas udara yang efektif tanpa memahami kondisi atmosfer yang menentukan kapan dan seberapa cepat polutan terakumulasi di dekat permukaan.
Eksplorasi artikel meteorologi lainnya di meteo.my.id — dari dinamika monsun hingga analisis data ERA5 dengan Python.
Referensi
- Temperature Inversions — NOAA/NWS Houston Weather Forecast Office — Penjelasan fisika dan klasifikasi inversi suhu: radiation, subsidence, frontal, dan mekanisme pembentukan masing-masing, lengkap dengan diagram sounding dan skematik.
- Smoke Blankets Borneo — NASA Earth Observatory — Dokumentasi episode asap kebakaran gambut September 2019 di Kalimantan dan Sumatra dengan citra MODIS dan konteks kesehatan PM2.5.
- BMKG: Update Perkembangan Terkini Kondisi Kualitas Udara di Wilayah Jakarta dan Sekitarnya — Siaran pers BMKG Juni 2022 yang mengidentifikasi lapisan inversi sebagai penyebab lonjakan PM2.5 hingga 148 µg/m³ di Jakarta.
- Data BMKG Menjelaskan Penurunan Kualitas Udara di Jakarta Biasa Terjadi Saat Musim Kemarau — Analisis data monitoring 2014–2018 yang menunjukkan pola lonjakan PM2.5 pagi hari pukul 07.00–09.00 WIB saat musim kemarau di Jakarta.
- WHO Global Air Quality Guidelines — World Health Organization Q&A — Panduan kualitas udara WHO 2021 dengan standar PM2.5 tahunan 5 µg/m³ dan perkiraan beban kesehatan global dari polusi udara.
Sabtu, 11 Juli 2026
Mengetahui seberapa tidak stabil kolom atmosfer adalah langkah awal yang kritis dalam prakiraan konveksi dan guntur. Salah satu indeks yang sudah lama digunakan untuk keperluan ini adalah Showalter Stability Index (SSI). Dengan data ERA5 dari ECMWF dan library MetPy, kita bisa menghitung SSI untuk seluruh domain Indonesia secara otomatis—tidak hanya untuk satu titik sounding, tapi untuk ribuan titik grid sekaligus.
Apa itu Indeks Showalter?
SSI pertama kali diperkenalkan oleh A. K. Showalter dalam makalahnya tahun 1953. Formula dasarnya:
$$\text{SI} = T_{500} - T'_{500}$$
di mana \(T_{500}\) adalah suhu lingkungan aktual pada 500 hPa, dan \(T'_{500}\) adalah suhu parsel udara pada 500 hPa setelah diangkat secara adiabatik.
Proses kalkulasinya terdiri dari tiga langkah: (1) angkat parsel dari 850 hPa secara dry-adiabatic hingga LCL (Lifting Condensation Level), yaitu ketinggian di mana suhu parsel sama dengan dewpoint 850 hPa; (2) angkat parsel dari LCL secara moist-adiabatic ke 500 hPa; (3) kurangi suhu parsel tersebut dari suhu lingkungan di 500 hPa. Nilai SI negatif berarti parsel lebih hangat dari lingkungannya—kolom tidak stabil dan konveksi mudah berkembang.
Threshold yang digunakan dalam tutorial ini mengikuti panduan EUMeTrain:
| Rentang SI | Interpretasi |
|---|---|
| \(\text{SI} > +3\) | Stabil, guntur tidak mungkin |
| \(0 < \text{SI} \leq +3\) | Marginal, guntur mungkin dengan forcing kuat |
| \(-3{,}0 \leq \text{SI} \leq 0\) | Tidak stabil, potensi tinggi guntur lebat |
| \(-6 \leq \text{SI} < -3\) | Sangat tidak stabil, guntur parah sangat mungkin |
| \(\text{SI} < -6\) | Ekstrem tidak stabil, potensi cuaca buruk hebat |
SSI berbeda dari Lifted Index (LI) hanya pada titik awal parsel: SSI menggunakan parsel fixed dari 850 hPa, sementara LI menggunakan parsel representatif dari lapisan terendah 50 hPa. Ini membuat SSI lebih tepat dipakai saat terdapat lapisan dingin dangkal di bawah 850 hPa yang menutupi potensi instabilitas sesungguhnya—misalnya saat cold surge memasuki wilayah tropis.
Satu keterbatasan penting: SSI tidak memperhitungkan pemanasan diurnal atau sumber kelembaban di bawah 850 hPa. Jika lapisan dingin meluas di atas 850 hPa, SSI cenderung meremehkan potensi konvektif sesungguhnya.
Menyiapkan dan Membaca Data ERA5
ERA5 menyediakan suhu atmosfer (\(T\)) dan specific humidity (\(q\)) pada 37 pressure level standar, termasuk 500 dan 850 hPa, dengan resolusi spasial ~0,25° (~31 km) dan temporal hourly sejak Januari 1940. Kita butuh dua file: temperature dan specific humidity di level 500 dan 850 hPa.
Download keduanya menggunakan cdsapi—daftar akun gratis di cds.climate.copernicus.eu jika belum punya. Guard if not os.path.exists(OUT) memastikan kita hanya download sekali; jalankan ulang snippet dan cdsapi langsung skip ke pembacaan file lokal.
import os
import cdsapi
import xarray as xr
import numpy as np
OUT_T = "era5_t_pl500-850_indonesia_2024_d.nc"
OUT_Q = "era5_q_pl500-850_indonesia_2024_d.nc"
if not os.path.exists(OUT_T):
c = cdsapi.Client(quiet=True)
c.retrieve(
"reanalysis-era5-pressure-levels",
{
"product_type": "reanalysis",
"variable": "temperature",
"pressure_level": ["500", "850"],
"year": "2024",
"month": [f"{m:02d}" for m in range(1, 13)],
"day": [f"{d:02d}" for d in range(1, 32)],
"time": "00:00",
"area": [6, 95, -11, 141],
"format": "netcdf",
},
OUT_T,
)
if not os.path.exists(OUT_Q):
c = cdsapi.Client(quiet=True)
c.retrieve(
"reanalysis-era5-pressure-levels",
{
"product_type": "reanalysis",
"variable": "specific_humidity",
"pressure_level": ["500", "850"],
"year": "2024",
"month": [f"{m:02d}" for m in range(1, 13)],
"day": [f"{d:02d}" for d in range(1, 32)],
"time": "00:00",
"area": [6, 95, -11, 141],
"format": "netcdf",
},
OUT_Q,
)
ds_t = xr.open_dataset(OUT_T)
ds_q = xr.open_dataset(OUT_Q)
print("=== Temperature dataset ===")
print(ds_t)
print("\n=== Specific humidity dataset ===")
print(ds_q)
=== Temperature dataset ===
<xarray.Dataset> Size: 37MB
Dimensions: (valid_time: 366, pressure_level: 2, latitude: 69,
longitude: 185)
Coordinates:
* valid_time (valid_time) datetime64[ns] 3kB 2024-01-01 ... 2024-12-31
expver (valid_time) <U4 6kB ...
* pressure_level (pressure_level) float64 16B 850.0 500.0
* latitude (latitude) float64 552B 6.0 5.75 5.5 ... -10.5 -10.75 -11.0
* longitude (longitude) float64 1kB 95.0 95.25 95.5 ... 140.8 141.0
number int64 8B ...
Data variables:
t (valid_time, pressure_level, latitude, longitude) float32 37MB ...
Attributes:
GRIB_centre: ecmf
GRIB_centreDescription: European Centre for Medium-Range Weather Forecasts
GRIB_subCentre: 0
Conventions: CF-1.7
institution: European Centre for Medium-Range Weather Forecasts
history: 2026-05-10T04:10 GRIB to CDM+CF via cfgrib-0.9.1...
=== Specific humidity dataset ===
<xarray.Dataset> Size: 37MB
Dimensions: (valid_time: 366, pressure_level: 2, latitude: 69,
longitude: 185)
Coordinates:
* valid_time (valid_time) datetime64[ns] 3kB 2024-01-01 ... 2024-12-31
expver (valid_time) <U4 6kB ...
* pressure_level (pressure_level) float64 16B 850.0 500.0
* latitude (latitude) float64 552B 6.0 5.75 5.5 ... -10.5 -10.75 -11.0
* longitude (longitude) float64 1kB 95.0 95.25 95.5 ... 140.8 141.0
number int64 8B ...
Data variables:
q (valid_time, pressure_level, latitude, longitude) float32 37MB ...
Attributes:
GRIB_centre: ecmf
GRIB_centreDescription: European Centre for Medium-Range Weather Forecasts
GRIB_subCentre: 0
Conventions: CF-1.7
institution: European Centre for Medium-Range Weather Forecasts
history: 2026-05-10T04:16 GRIB to CDM+CF via cfgrib-0.9.1...
Output di atas memperlihatkan dimensi kedua dataset: waktu (satu snapshot per hari selama 2024), pressure level (500 dan 850 hPa), latitude, dan longitude. Koordinat inilah yang akan kita gunakan untuk mengekstrak nilai pada masing-masing level.
Mengkonversi Specific Humidity menjadi Dewpoint
ERA5 menyimpan kandungan uap air sebagai specific humidity \(q\) (kg/kg), bukan dewpoint. Sebelum kita bisa menghitung SSI, \(q\) perlu dikonversi ke dewpoint terlebih dahulu. Konversi ini melewati tiga langkah: mixing ratio \(w = q/(1-q)\), tekanan uap parsial \(e = (w/(\varepsilon + w)) \cdot p\), lalu dewpoint dari \(e\) menggunakan formula Magnus—semua langkah ini sudah ditangani oleh metpy.calc.dewpoint_from_specific_humidity.
Kita pilih snapshot pertama di dataset (1 Januari 2024, 00Z) sebagai contoh representatif. Seluruh array 2D akan digunakan di snippet-snippet berikutnya.
from metpy.calc import dewpoint_from_specific_humidity
from metpy.units import units
# Deteksi nama koordinat waktu dan pressure level secara otomatis
time_coord = "valid_time" if "valid_time" in ds_t.dims else "time"
p_coord = "pressure_level" if "pressure_level" in ds_t.dims else "level"
# Ambil snapshot pertama (1 Januari 2024 00Z)
t_step = ds_t.isel({time_coord: 0})
q_step = ds_q.isel({time_coord: 0})
# Ekstrak array numpy per level
t850 = t_step["t"].sel({p_coord: 850}).values # K, shape (lat, lon)
t500 = t_step["t"].sel({p_coord: 500}).values # K
q850 = q_step["q"].sel({p_coord: 850}).values # kg/kg
q500 = q_step["q"].sel({p_coord: 500}).values # kg/kg
lats = t_step.latitude.values
lons = t_step.longitude.values
# Tampilkan beberapa sampel dewpoint 850 hPa
print("Contoh dewpoint 850 hPa (°C):")
for ii, jj in [(0, 0), (10, 20), (20, 40), (30, 60)]:
td = dewpoint_from_specific_humidity(
850 * units.hPa,
t850[ii, jj] * units.K,
q850[ii, jj] * units("kg/kg"),
)
print(
f" lat={lats[ii]:.2f}°, lon={lons[jj]:.2f}°"
f" T850={t850[ii, jj] - 273.15:.1f}°C"
f" Td850={td.to('degC').magnitude:.1f}°C"
)
Contoh dewpoint 850 hPa (°C):
lat=6.00°, lon=95.00° T850=18.3°C Td850=14.0°C
lat=3.50°, lon=100.00° T850=17.9°C Td850=17.3°C
lat=1.00°, lon=105.00° T850=18.3°C Td850=16.4°C
lat=-1.50°, lon=110.00° T850=18.5°C Td850=17.2°C
Selisih antara T850 dan Td850 di atas mencerminkan dewpoint depression—gap yang lebih kecil berarti udara lebih lembab di 850 hPa, yang penting untuk menentukan LCL dalam perhitungan SSI.
Menghitung Indeks Showalter untuk Seluruh Grid
metpy.calc.showalter_index menerima profil 1D dengan dua level (850 dan 500 hPa, urutan dari tekanan tinggi ke rendah). Untuk menerapkannya ke seluruh grid ERA5, kita loop atas setiap titik. Karena resolusi 0,25° menghasilkan grid ~69 × 185 titik, kita subsample setiap 4 titik ([::4, ::4]) untuk menjaga runtime di bawah batas sandbox—hasilnya tetap merepresentasikan pola regional dengan baik.
import warnings
warnings.filterwarnings("ignore")
from metpy.calc import showalter_index, dewpoint_from_specific_humidity
from metpy.units import units
import numpy as np
# Subsample setiap 4 titik untuk efisiensi
lats_sub = lats[::4]
lons_sub = lons[::4]
t850_sub = t850[::4, ::4]
t500_sub = t500[::4, ::4]
q850_sub = q850[::4, ::4]
q500_sub = q500[::4, ::4]
nlat, nlon = t850_sub.shape
si = np.full((nlat, nlon), np.nan)
for i in range(nlat):
for j in range(nlon):
try:
p = np.array([850.0, 500.0]) * units.hPa
T = np.array([t850_sub[i, j] - 273.15,
t500_sub[i, j] - 273.15]) * units.degC
td850 = dewpoint_from_specific_humidity(
850 * units.hPa,
t850_sub[i, j] * units.K,
q850_sub[i, j] * units("kg/kg"),
)
td500 = dewpoint_from_specific_humidity(
500 * units.hPa,
t500_sub[i, j] * units.K,
q500_sub[i, j] * units("kg/kg"),
)
td = np.array([td850.to("degC").magnitude,
td500.to("degC").magnitude]) * units.degC
ssi = showalter_index(p, T, td)
si[i, j] = ssi[0].magnitude
except Exception:
pass
print(f"Grid subsampled : {nlat} x {nlon} = {nlat * nlon} titik")
print(f"SI min : {np.nanmin(si):.1f}°C")
print(f"SI max : {np.nanmax(si):.1f}°C")
print(f"SI mean : {np.nanmean(si):.1f}°C")
Grid subsampled : 18 x 47 = 846 titik
SI min : -2.6°C
SI max : 9.9°C
SI mean : 0.8°C
Nilai min dan max di atas menggambarkan rentang instabilitas pada tanggal tersebut. Nilai SI sangat negatif biasanya terkonsentrasi di daerah konveksi aktif—Maluku, Kalimantan tengah, atau wilayah ITCZ yang sedang aktif.
Memvisualisasikan Peta Instabilitas Atmosfer
Peta 2D SSI jauh lebih informatif dibanding angka statistik saja. Kita plot menggunakan matplotlib dan cartopy di atas proyeksi PlateCarree, dengan colormap diverging yang memperlihatkan batas threshold secara langsung. Warna merah menandai daerah yang paling tidak stabil (\(\text{SI} < -3\)), dan biru menandai daerah stabil.
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
import cartopy.crs as ccrs
import cartopy.feature as cfeature
import numpy as np
lon2d, lat2d = np.meshgrid(lons_sub, lats_sub)
# Level dan warna per band threshold
levels = [-9, -6, -3, 0, 3, 6]
cmap = plt.cm.RdBu_r
norm = mcolors.BoundaryNorm(levels, cmap.N)
fig, ax = plt.subplots(
figsize=(13, 6),
subplot_kw={"projection": ccrs.PlateCarree()},
)
cf = ax.pcolormesh(
lon2d, lat2d, si,
cmap=cmap, norm=norm,
transform=ccrs.PlateCarree(),
)
ax.add_feature(cfeature.COASTLINE, linewidth=0.9, color="black")
ax.add_feature(cfeature.BORDERS, linewidth=0.4, linestyle=":", color="gray")
ax.add_feature(cfeature.LAND, facecolor="lightgray", alpha=0.15)
ax.set_extent([95, 141, -11, 6], crs=ccrs.PlateCarree())
gl = ax.gridlines(draw_labels=True, linewidth=0.5, color="gray", alpha=0.5, linestyle="--")
gl.top_labels = False
gl.right_labels = False
cbar = fig.colorbar(cf, ax=ax, orientation="vertical", pad=0.02, shrink=0.85, extend="both")
cbar.set_label("Showalter Index (°C)", fontsize=11)
cbar.set_ticks(levels)
ax.set_title(
"Peta Showalter Stability Index — Indonesia\nERA5 data tahun 2024, 1 Jan 00Z (grid subsampled 1°)",
fontsize=12, pad=10,
)
# Annotasi threshold
for val, label, ypos in [
(-7.5, "Ekstrem tidak stabil", 0.15),
(-4.5, "Sangat tidak stabil", 0.30),
(-1.5, "Tidak stabil", 0.48),
( 1.5, "Marginal", 0.65),
( 4.5, "Stabil", 0.82),
]:
cbar.ax.text(
2.5, ypos, label,
transform=cbar.ax.transAxes,
fontsize=7.5, va="center", color="black",
)
plt.tight_layout()
plt.savefig("si_indonesia_map.png", dpi=120, bbox_inches="tight")
print("Peta disimpan: si_indonesia_map.png")
Peta di atas menunjukkan distribusi spasial instabilitas atmosfer. Pada colormap ini, daerah merah tua (\(\text{SI} < -6\)) akan menandai zona konveksi potensial paling kuat bila ada, sementara warna biru menunjukkan kolom atmosfer yang stabil. Perhatikan bahwa untuk snapshot 1 Januari 2024 00Z ini SI minimum hanya mencapai \(-2{,}6\)°C, sehingga peta didominasi warna biru-hijau (marginal hingga tidak stabil) tanpa zona merah—kondisi yang lazim di awal tahun. Coba tanggal pada Februari–Maret atau Oktober–November untuk melihat kontras instabilitas yang lebih tajam.
Interpretasi Hasil dan Penerapan Praktis
Setelah kita punya array si dua dimensi, langkah praktis berikutnya adalah menghitung berapa banyak grid point yang jatuh ke tiap band threshold. Ini memberi gambaran cepat tentang proporsi wilayah Indonesia yang berada dalam kondisi stabil vs tidak stabil pada tanggal tersebut.
import numpy as np
valid = si[~np.isnan(si)]
total = len(valid)
bands = [
(">+3", valid > 3, "Stabil"),
("0 s.d. +3", (valid > 0) & (valid <= 3), "Marginal"),
("-3 s.d. 0", (valid >= -3) & (valid <= 0), "Tidak stabil"),
("<-3", valid < -3, "Sangat/Ekstrem tdk stabil"),
]
print(f"Total grid point valid: {total}")
print("-" * 55)
print(f"{'Band SI':<14} {'Label':<30} {'Titik':>6} {'%':>6}")
print("-" * 55)
for rng, mask, label in bands:
n = int(np.sum(mask))
print(f"{rng:<14} {label:<30} {n:>6} {100*n/total:>5.1f}%")
print("-" * 55)
Total grid point valid: 846
-------------------------------------------------------
Band SI Label Titik %
-------------------------------------------------------
>+3 Stabil 71 8.4%
0 s.d. +3 Marginal 476 56.3%
-3 s.d. 0 Tidak stabil 299 35.3%
<-3 Sangat/Ekstrem tdk stabil 0 0.0%
-------------------------------------------------------
Persentase ini berguna untuk membandingkan kondisi antar tanggal atau antar musim. Misalnya, kita bisa looping snippet-3 dan snippet-5 atas seluruh 366 hari di ERA5 data tahun 2024 dan membuat time series proporsi daerah tidak stabil—cara sederhana untuk melihat pola seasonal instabilitas atmosfer di Indonesia.
Dua batasan penting perlu diingat saat menginterpretasi hasil SSI. Pertama, SSI tidak memperhitungkan kelembaban dan pemanasan di bawah 850 hPa, sehingga bisa meremehkan instabilitas saat boundary layer sangat lembab atau saat lapisan dingin dangkal berada di bawah 850 hPa. Kedua, SSI adalah indeks termodinamik statis—ia tidak menangkap forcing dinamis (wind shear, divergensi, vortisitas) yang menentukan apakah konveksi benar-benar terjadi atau tidak. Gunakan SSI bersama indeks lain seperti CAPE, CIN, dan K-Index untuk gambaran yang lebih lengkap.
Kesimpulan dan Langkah Berikutnya
Kita telah menjalani workflow lengkap: download data ERA5 pressure-level via cdsapi, buka file dengan xarray, konversi specific humidity ke dewpoint menggunakan MetPy, hitung Showalter Index per grid point dengan loop efisien, lalu visualisasikan distribusi spasialnya di atas Indonesia menggunakan Cartopy. Seluruh workflow berjalan dari satu snapshot tunggal (1 Januari 2024 00Z) tapi mudah dikembangkan ke analisis multitemporal.
Langkah berikutnya yang layak dicoba: bandingkan SSI dengan Lifted Index untuk domain yang sama menggunakan metpy.calc.lifted_index, buat time series harian proporsi grid tidak stabil sepanjang 2024, atau integrasikan SSI ke dalam decision support sederhana yang mempertemukan threshold SSI dengan data curah hujan IMERG.
Eksplorasi artikel meteorologi lainnya di meteo.my.id — kunjungi meteo.my.id.
Referensi
- Skew-T Parameters and Indices — NOAA National Weather Service — Penjelasan lengkap NWS tentang Showalter Index, prosedur tiga langkah, tabel threshold, dan perbandingannya dengan Lifted Index.
- Glossary: Showalter Index — NOAA National Weather Service — Definisi resmi SSI sebagai indeks stabilitas untuk prakiraan guntur beserta keterbatasannya.
- Stability Indices — EUMeTrain / EUMETSAT — Tabel threshold SSI yang digunakan dalam tutorial ini: \(\text{SI} > +3\) stabil, \(-3\) s.d. \(0\) tidak stabil, \(< -3\) sangat tidak stabil.
- showalter_index — MetPy 1.7 (Unidata/UCAR) — Dokumentasi API resmi MetPy untuk
showalter_indexdandewpoint_from_specific_humidity, termasuk persyaratan pint.Quantity dan langkah konversi dari specific humidity ERA5. - ERA5: data documentation — ECMWF / Copernicus Climate Change Service — Dokumentasi resmi ERA5: 37 pressure level standar, variabel yang tersedia (termasuk \(T\) dan \(q\)), resolusi spasial ~0,25°, dan cakupan temporal.