This commit is contained in:
2026-05-11 00:36:02 +03:30
parent 2a6321a263
commit 1740c20ddb
23 changed files with 1214 additions and 89 deletions
-5
View File
@@ -97,7 +97,6 @@
برای هر cell و بازه زمانی:
- `ndvi`
- `ndwi`
- `lst_c`
- `soil_vv`
- `soil_vv_db`
- `dem_m`
@@ -359,7 +358,6 @@ step_m = sqrt(900) = 30m
- `temporal_end`
- `ndvi`
- `ndwi`
- `lst_c`
- `soil_vv`
- `soil_vv_db`
- `dem_m`
@@ -499,7 +497,6 @@ https://openeofed.dataspace.copernicus.eu
- `ndvi` از `SENTINEL2_L2A`
- `ndwi` از `SENTINEL2_L2A`
- `lst_c` از `SENTINEL3_SLSTR_L2_LST`
- `soil_vv` از `SENTINEL1_GRD`
- `soil_vv_db` در Python از `soil_vv`
- `dem_m` از `COPERNICUS_30`
@@ -542,7 +539,6 @@ aggregate_spatial(geometries=feature_collection, reducer="mean")
"cell-1": {
"ndvi": ...,
"ndwi": ...,
"lst_c": ...,
"soil_vv": ...,
"soil_vv_db": ...,
"dem_m": ...,
@@ -775,7 +771,6 @@ retry می‌کند.
- `cell_count`
- `ndvi_mean`
- `ndwi_mean`
- `lst_c_mean`
- `soil_vv_db_mean`
- `dem_m_mean`
- `slope_deg_mean`
@@ -72,7 +72,7 @@
| `status_label` | `failed` | نسخه نرمال‌شده برای client |
| `pipeline_status` | `failed` | تکرار client-facing status |
| `stage` | `observations_persisted` | آخرین stage ذخیره‌شده در metadata |
| `selected_features` | `ndvi`, `ndwi`, `lst_c`, `soil_vv_db`, `dem_m`, `slope_deg` | featureهایی که pipeline فکر می‌کند برای clustering لازم‌اند |
| `selected_features` | `ndvi`, `ndwi`, `soil_vv_db`, `dem_m`, `slope_deg` | featureهایی که pipeline فکر می‌کند برای clustering لازم‌اند |
| `requested_cluster_count` | `null` | تعداد cluster صریح از کاربر نیامده و الگوریتم باید تصمیم بگیرد |
| `error_message` | متن فارسی خطا | خطای نهایی ثبت‌شده روی run |
| `started_at` | timestamp | زمان شروع واقعی run |
@@ -258,7 +258,6 @@
- `ndvi`
- `ndwi`
- `lst_c`
- `soil_vv_db`
هم عملاً `None` شده باشند یا آن‌طور که clustering انتظار دارد قابل مصرف نبوده باشند.
@@ -385,7 +384,7 @@
بر اساس payload و کد، نتیجه عملی این است:
1. openEO jobها برای `ndvi`, `ndwi`, `lst_c`, `soil_vv` اجرا شده‌اند
1. openEO jobها برای `ndvi`, `ndwi`, `soil_vv` اجرا شده‌اند
2. 12 observation در DB ساخته شده‌اند
3. pipeline وارد مرحله clustering شده
4. clustering هیچ observation usable پیدا نکرده
@@ -407,7 +406,6 @@
2. `DEFAULT_CLUSTER_FEATURES` را با metricهای واقعی sync کنید:
- `ndvi`
- `ndwi`
- `lst_c`
- `soil_vv_db`
3. progress tracker را طوری اصلاح کنید که:
@@ -0,0 +1,642 @@
# توضیح response سنجش‌ازدور
این فایل response زیر را توضیح می‌دهد:
- کد HTTP داخلی: `200`
- پیام: `success`
- وضعیت نهایی تحلیل: `completed`
- منبع response: `database`
این response نشان می‌دهد که pipeline سنجش‌ازدور برای یک مزرعه با موفقیت اجرا شده، داده‌های ماهواره‌ای برای 12 سلول grid ذخیره شده، و در نهایت subdivision داده‌محور با 2 خوشه ساخته شده است.
## جمع‌بندی سریع همین response
- تحلیل مربوط به بازه `2026-04-09` تا `2026-05-09` است.
- درخواست در `2026-05-10T20:17:34Z` شروع شده و در `2026-05-10T20:28:29Z` کامل شده است.
- 12 سلول grid با اندازه `900` مترمربع پردازش شده‌اند.
- feature های استفاده‌شده برای clustering این‌ها هستند:
- `ndvi`
- `ndwi`
- `soil_vv_db`
- هیچ metricی fail نشده است.
- همه 12 observation قابل استفاده بوده‌اند:
- `usable_observation_count = 12`
- `fully_null_observation_count = 0`
- نتیجه نهایی clustering برابر `2` خوشه است.
## ساختار کلی response
ساختار سطح بالا این response به صورت زیر است:
```json
{
"code": 200,
"msg": "success",
"data": {
"status": "completed",
"source": "database",
"run": {...},
"task": {...},
"location": {...},
"summary": {...},
"cells": [...],
"subdivision_result": {...},
"pagination": {...}
}
}
```
هر بخش یک نقش جدا دارد:
- `run`: رکورد اصلی اجرای تحلیل
- `task`: وضعیت orchestration و stageهای Celery/pipeline
- `location`: اطلاعات مزرعه و layout بلوک‌ها
- `summary`: خلاصه آماری observationها
- `cells`: داده خام هر سلول grid
- `subdivision_result`: خروجی clustering و assignment هر سلول
- `pagination`: اطلاعات صفحه‌بندی برای لیست cellها و assignmentها
## بخش `code` و `msg`
- `code = 200`
- یعنی endpoint با موفقیت جواب داده است.
- `msg = "success"`
- پیام عمومی موفقیت است.
این دو فیلد بیشتر برای client-side handling مفید هستند.
## بخش `data.status` و `data.source`
- `status = "completed"`
- یعنی فرآیند تحلیلی کامل شده و نتیجه نهایی آماده است.
- `source = "database"`
- یعنی response از داده‌های ذخیره‌شده در دیتابیس ساخته شده، نه از اجرای زنده openEO در همان لحظه.
نکته:
- این به معنی آن نیست که openEO استفاده نشده؛ برعکس، openEO قبلاً استفاده شده و خروجی آن در DB persist شده است.
- فقط endpoint فعلی نتیجه را از cache دیتابیسی برگردانده است.
## بخش `run`
بخش `run` رکورد اصلی اجرای remote sensing را توصیف می‌کند.
### فیلدهای پایه
- `id = 1`
- شناسه اجرای تحلیل
- `block_code = ""`
- اجرای تحلیل روی block پیش‌فرض/کل محدوده انجام شده است
- `chunk_size_sqm = 900`
- هر cell حدود 900 مترمربع است
- `temporal_start = "2026-04-09"`
- `temporal_end = "2026-05-09"`
- بازه زمانی داده‌های ماهواره‌ای
### وضعیت run
- `status = "success"`
- وضعیت خام دیتابیس
- `status_label = "completed"`
- نسخه نرمال‌شده برای client
- `pipeline_status = "completed"`
- وضعیت نهایی قابل نمایش برای frontend
- `stage = "completed"`
- آخرین stage ثبت‌شده
### featureهای انتخاب‌شده
- `selected_features = ["ndvi", "ndwi", "soil_vv_db"]`
یعنی clustering فقط با این سه feature انجام شده است.
### `requested_cluster_count`
- `requested_cluster_count = null`
یعنی کاربر تعداد cluster را مستقیماً مشخص نکرده و سیستم آن را خودش انتخاب کرده است.
## بخش `run.metadata`
این بخش metadata کامل اجرای pipeline را نگه می‌دارد.
### `scope`
- `scope = "all_blocks"`
یعنی اجرا در scope کل blockهای قابل تحلیل ثبت شده است.
### `service`
این بخش مشخص می‌کند metricها از کدام backend آمده‌اند.
- `backend = "openeo"`
- `backend_url = "https://openeofed.dataspace.copernicus.eu"`
- `collections_used = ["SENTINEL2_L2A", "SENTINEL1_GRD"]`
یعنی:
- `ndvi` و `ndwi` از Sentinel-2
- `soil_vv` از Sentinel-1
- `soil_vv_db` به صورت مشتق‌شده از `soil_vv`
### `job_refs`
این‌ها شناسه jobهای openEO هستند:
- `ndvi`
- `ndwi`
- `soil_vv`
این شناسه‌ها برای trace کردن jobهای backend خیلی مهم‌اند.
### `failed_metrics`
- `failed_metrics = []`
یعنی هیچ metricی fail نشده است.
### `payload_diagnostics`
برای هر metric یک summary از payload خام openEO ذخیره شده:
- `returned_cell_count = 12`
- `payload_keys_sample = ["0", "1", "2", "3", "4"]`
- `available_features = []`
تعبیر این بخش:
- backend برای هر metric 12 نتیجه برگردانده
- payload به صورت positional/list-based بوده، نه با `cell_code`های صریح
- `available_features = []` طبیعی است، چون payload از نوع لیستی عددی بوده و structure دیکشنری feature-based نداشته است
## بخش `run.metadata.summary`
این خلاصه اجرایی run است:
- `source = "openeo"`
- `status = "completed"`
- `cell_count = 12`
- `processed_cell_count = 12`
- `created_observation_count = 12`
- `updated_observation_count = 0`
- `existing_observation_count = 0`
- `failed_metric_count = 0`
- `cluster_count = 2`
- `subdivision_result_id = 1`
معنی عملی:
- همه 12 سلول تازه ساخته و پردازش شده‌اند
- چیزی از قبل reuse نشده
- pipeline بدون failure تا انتها رفته
## بخش `timestamps`
این timestamps جریان کامل pipeline را نشان می‌دهند:
- `queued_at`: زمان queue شدن task
- `started_at`: زمان شروع واقعی task
- `preparing_analysis_grid_at`: زمان شروع ساخت grid
- `analysis_grid_ready_at`: زمان آماده شدن grid
- `analysis_cells_selected_at`: زمان انتخاب cellهای هدف
- `fetching_remote_metrics_at`: زمان شروع fetch از openEO
- `remote_metrics_fetched_at`: زمان تکمیل دریافت metricها
- `observations_persisted_at`: زمان ذخیره observationها در DB
- `clustering_completed_at`: زمان تکمیل clustering
- `completed_at`: زمان پایان کامل pipeline
برای این response:
- start: `2026-05-10T20:17:34.570353+00:00`
- complete: `2026-05-10T20:28:29.469326+00:00`
پس کل فرآیند حدود 10 دقیقه و 55 ثانیه طول کشیده است.
## بخش `stage_details`
این بخش مهم‌ترین قسمت برای debugging و فهم pipeline است.
### `analysis_grid_ready`
```json
{
"created": true,
"total_count": 12,
"created_count": 12,
"existing_count": 0
}
```
یعنی:
- grid analysis تازه ساخته شده
- 12 سلول جدید ایجاد شده
### `analysis_cells_selected`
```json
{
"force_refresh": false,
"total_cell_count": 12,
"existing_cell_count": 0,
"cell_count_to_process": 12
}
```
یعنی:
- force refresh فعال نبوده
- هیچ cell cache‌شده‌ای برای reuse وجود نداشته
- هر 12 سلول باید از openEO پردازش می‌شدند
### `fetching_remote_metrics`
این بخش دو چیز را نشان می‌دهد:
- `target_cells`
- لیست سلول‌هایی که برایشان metric گرفته شده
- `metric_progress`
- وضعیت پیشرفت metricها
در این response:
- `total_metrics = 3`
- metricهای کامل‌شده:
- `ndvi`
- `ndwi`
- `soil_vv_db`
نکته:
- job_ref `soil_vv_db` در اصل به job مربوط به `soil_vv` map شده، چون `soil_vv_db` metric مشتق‌شده است.
### `remote_metrics_fetched`
این بخش metadata سرویس را بعد از fetch نگه می‌دارد و تأیید می‌کند:
- metricها از openEO آمده‌اند
- هیچ metricی fail نشده
- برای هر metric 12 سلول نتیجه برگشته
### `observations_persisted`
این بخش نشان می‌دهد داده‌ها با موفقیت در DB ذخیره شده‌اند:
- `created_count = 12`
- `updated_count = 0`
- `matched_cell_count = 12`
- `usable_observation_count = 12`
- `fully_null_observation_count = 0`
- `unmatched_db_cell_codes = []`
- `unmatched_payload_cell_codes = []`
این یکی از مهم‌ترین بخش‌های response است، چون ثابت می‌کند:
- matching بین payload و سلول‌های DB کامل بوده
- هیچ observation خالی persist نشده
- تمام cellها usable بوده‌اند
### `clustering_completed`
این بخش خروجی clustering را خلاصه می‌کند:
- `cluster_count = 2`
- `used_cell_count = 12`
- `skipped_cell_count = 0`
- `subdivision_result_id = 1`
و پارامترهای KMeans:
- `max_k = 10`
- `n_init = 10`
- `random_state = 42`
- `selection_strategy = "elbow"`
- `selected_k = 2`
یعنی سیستم با روش elbow، مقدار `K = 2` را بهترین انتخاب دیده است.
## بخش `task`
بخش `task` نسخه task-oriented همین اجرا را نشان می‌دهد.
### `current_stage`
- `current_stage = "completed"`
یعنی دیگر stage فعالی وجود ندارد و task بسته شده است.
### `stages`
این آرایه تاریخچه stageها را نگه می‌دارد:
- `queued`
- `preparing_analysis_grid`
- `analysis_grid_ready`
- `analysis_cells_selected`
- `fetching_remote_metrics`
- `remote_metrics_fetched`
- `observations_persisted`
- `clustering_completed`
- `completed`
این ترتیب دقیق pipeline را نشان می‌دهد.
### `metric_progress`
این بخش برای UI بسیار مفید است:
- `total_metrics = 3`
- `completed_metric_count = 3`
- `failed_metrics = []`
- `active_metric = null`
پس هیچ metric نیمه‌کاره یا fail شده‌ای باقی نمانده است.
### `celery`
این بخش وضعیت Celery task را نشان می‌دهد:
- `state = "SUCCESS"`
- `ready = true`
- `successful = true`
- `failed = false`
و در `info` هم خلاصه اجرایی برگردانده شده:
- 12 سلول پردازش شده
- 12 observation ساخته شده
- 2 cluster تولید شده
## بخش `location`
این بخش context مکانی تحلیل را نشان می‌دهد.
### اطلاعات پایه
- `id = 1`
- `lon = "50.000000"`
- `lat = "50.000000"`
- `input_block_count = 1`
### `farm_boundary`
یک polygon مربعی کوچک اطراف مختصات 50,50 است.
### `block_layout`
در `blocks` دو ورودی دیده می‌شود:
1. block پیش‌فرض:
- `source = "default"`
- `block_code = "block-1"`
2. block تولیدشده از remote sensing:
- `source = "remote_sensing"`
- `block_code = ""`
- `needs_subdivision = true`
- دارای 2 زیر‌بلوک (`cluster-0`, `cluster-1`)
این یعنی سیستم علاوه بر block اولیه، یک layout تحلیلی جدید هم بر اساس داده‌های remote sensing ساخته است.
### `analysis_grid_summary`
- `cell_count = 12`
- `chunk_size_sqm = 900`
یعنی farm boundary به 12 cell با اندازه 900 مترمربع شکسته شده است.
### `satellite_snapshots`
دو snapshot وجود دارد:
1. برای `block-1`
- `status = "missing"`
- یعنی برای آن block خاص snapshot مستقلی وجود ندارد
2. برای `block_code = ""`
- `status = "completed"`
- `run_id = 1`
- `cell_count = 12`
- `resolved_metrics`:
- `ndvi = 0.686502`
- `ndwi = -0.598028`
- `soil_vv_db = -13.374155`
این اعداد همان summary ساده‌ی metrics در کل محدوده هستند.
## بخش `summary`
این بخش خلاصه آماری کل observationها است:
```json
{
"cell_count": 12,
"ndvi_mean": 0.686502,
"ndwi_mean": -0.598028,
"soil_vv_db_mean": -13.374155
}
```
معنی:
- 12 سلول در summary لحاظ شده‌اند
- میانگین `ndvi` حدود `0.6865`
- میانگین `ndwi` حدود `-0.5980`
- میانگین `soil_vv_db` حدود `-13.3742`
## بخش `cells`
این آرایه، داده خام هر سلول را نگه می‌دارد.
هر item شامل این‌ها است:
- `cell_code`
- `block_code`
- `chunk_size_sqm`
- `centroid_lat`
- `centroid_lon`
- `geometry`
- `temporal_start`
- `temporal_end`
- `ndvi`
- `ndwi`
- `soil_vv`
- `soil_vv_db`
- `metadata`
### مثال از یک cell
برای اولین سلول:
- `cell_code = loc-1__block-farm__chunk-900__r0000c0000`
- `ndvi = 0.6622872683737013`
- `ndwi = -0.583760056230757`
- `soil_vv = 0.0290423126684294`
- `soil_vv_db = -15.369688`
این یعنی این cell هم داده خام خطی Sentinel-1 (`soil_vv`) را دارد، هم نسخه dB آن (`soil_vv_db`).
### `cells[].metadata`
metadata هر سلول شامل این‌ها است:
- `run_id`
- `job_refs`
- `backend_name`
- `backend_url`
- `collections_used`
- `failed_metrics`
- `payload_diagnostics`
این metadata برای traceability خیلی مفید است، چون مشخص می‌کند این observation از کدام run و کدام jobهای openEO آمده است.
## بخش `subdivision_result`
این بخش خروجی اصلی clustering را نشان می‌دهد.
### فیلدهای پایه
- `id = 1`
- `cluster_count = 2`
- `selected_features = ["ndvi", "ndwi", "soil_vv_db"]`
- `skipped_cell_codes = []`
یعنی:
- نتیجه نهایی clustering دو خوشه دارد
- هیچ cellی حذف نشده
### `metadata.scaler_means`
میانگین هر feature قبل از scaling:
- `ndvi = 0.6865018435098507`
- `ndwi = -0.5980279920277772`
- `soil_vv_db = -13.374155250000005`
### `metadata.scaler_scales`
انحراف معیار/scale هر feature:
- `ndvi = 0.018948282260331236`
- `ndwi = 0.012494317547431832`
- `soil_vv_db = 0.87754098540943`
### `metadata.imputer_statistics`
چون imputer از نوع median بوده:
- median `ndvi`
- median `ndwi`
- median `soil_vv_db`
برای این run ذخیره شده‌اند، حتی اگر در این مورد missing value نداشته‌ایم.
### `metadata.missing_value_counts`
```json
{
"ndvi": 0,
"ndwi": 0,
"soil_vv_db": 0
}
```
این خیلی مهم است، چون نشان می‌دهد برای featureهای clustering هیچ داده‌ی گم‌شده‌ای وجود نداشته است.
### `metadata.inertia_curve`
این آرایه SSE را برای Kهای مختلف نگه می‌دارد:
- `k=1 => sse=36`
- `k=2 => sse=14.987928`
- ...
- `k=10 => sse=0.140512`
سیستم از این curve برای انتخاب elbow استفاده کرده و در نهایت `k=2` را برداشته است.
### `metadata.cluster_summaries`
خلاصه هر cluster:
- `cluster-0`
- `cell_count = 9`
- `centroid_lat = 49.999995`
- `centroid_lon = 50.000223`
- `cluster-1`
- `cell_count = 3`
- `centroid_lat = 50.000174`
- `centroid_lon = 49.99985`
یعنی تقسیم‌بندی نهایی مزرعه به دو زیر‌بلوک 9تایی و 3تایی انجام شده است.
### `assignments`
این آرایه برای هر cell مشخص می‌کند:
- عضو کدام cluster است
- raw feature value آن چیست
- scaled feature value آن چیست
مثلاً:
- `loc-1__block-farm__chunk-900__r0000c0000`
- `cluster_label = 1`
- `raw_feature_values.ndvi = 0.662287...`
- `raw_feature_values.ndwi = -0.583760...`
- `raw_feature_values.soil_vv_db = -15.369688`
این بخش برای تحلیل این‌که چرا یک cell داخل یک cluster خاص افتاده بسیار مفید است.
## بخش `pagination`
این بخش صفحه‌بندی را برای دو لیست نشان می‌دهد:
- `cells`
- `assignments`
در هر دو مورد:
- `page = 1`
- `page_size = 100`
- `total_items = 12`
- `total_pages = 1`
- `has_next = false`
- `has_previous = false`
یعنی تمام داده‌ها در یک صفحه جا شده‌اند.
## نتیجه نهایی این response
اگر بخواهیم این response را در یک جمله خلاصه کنیم:
- سیستم در تاریخ `2026-05-10` یک تحلیل سنجش‌ازدور موفق روی 12 سلول grid انجام داده، metricهای `ndvi`, `ndwi`, `soil_vv_db` را بدون missing value ذخیره کرده، و مزرعه را با روش elbow-based KMeans به 2 زیر‌بلوک تقسیم کرده است.
## مهم‌ترین فیلدها برای استفاده عملی
اگر فقط چند بخش برای frontend یا debugging مهم باشد، این‌ها از همه مهم‌ترند:
- `data.status`
- `data.run.selected_features`
- `data.run.metadata.summary`
- `data.run.metadata.stage_details.observations_persisted`
- `data.summary`
- `data.cells`
- `data.subdivision_result.metadata.cluster_summaries`
- `data.subdivision_result.assignments`
## برداشت فنی از سلامت این run
این response از نظر pipeline یک run سالم را نشان می‌دهد:
- status نهایی `completed` است
- Celery در `SUCCESS` است
- هیچ metricی fail نشده
- همه cellها match شده‌اند
- هیچ observationی null کامل نیست
- clustering روی همه سلول‌ها اجرا شده
- output نهایی subdivision ساخته شده
پس این response نمونه‌ی یک اجرای موفق و کامل remote sensing subdivision است.