# توضیح 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 است.