UPDATE
This commit is contained in:
@@ -0,0 +1,378 @@
|
||||
# جریان واقعی `location_data`
|
||||
|
||||
این توضیح دقیقاً بر اساس منطق جدید نوشته شده:
|
||||
|
||||
- اول مختصات گوشههای کل زمین گرفته میشود
|
||||
- بعد مختصات بلوکهایی که کشاورز خودش تعریف کرده گرفته میشود
|
||||
- هر بلوک جداگانه به grid های `30×30` تبدیل میشود
|
||||
- برای هر grid دادهی یک بازه زمانی از openEO گرفته میشود
|
||||
- میانگین همان بازه، وضعیت نهایی همان grid حساب میشود
|
||||
- بعد برای همان grid ها `KMeans` اجرا میشود
|
||||
- برای هر `K` مقدار `SSE / Inertia` ذخیره میشود
|
||||
- نمودار `K - SSE` رسم میشود
|
||||
- نقطهای که افت شیب ناگهانی دارد به عنوان تعداد مناسب زیربلوکها انتخاب میشود
|
||||
- در نهایت هر بلوک کشاورز به چند زیربلوک دادهمحور تقسیم میشود
|
||||
|
||||
---
|
||||
|
||||
## 1) ورودی مرحله اول
|
||||
|
||||
در مرحله اول این دادهها ثبت میشوند:
|
||||
|
||||
- مختصات گوشههای کل زمین
|
||||
- مختصات بلوکهایی که کشاورز تعریف کرده
|
||||
- کد هر بلوک
|
||||
|
||||
فایل اصلی:
|
||||
|
||||
- `location_data/views.py`
|
||||
- `location_data/serializers.py`
|
||||
- `location_data/models.py`
|
||||
|
||||
خروجی این مرحله:
|
||||
|
||||
- یک `SoilLocation` برای زمین
|
||||
- یک `block_layout` که داخلش boundary هر بلوک هست
|
||||
- یک `BlockSubdivision` برای هر بلوک، فقط به عنوان تعریف مرز بلوک کشاورز
|
||||
|
||||
نکته مهم:
|
||||
|
||||
- در این مرحله هیچ subdivision سنکرونی اجرا نمیشود
|
||||
- هیچ داده خاکی از adapter قدیمی گرفته نمیشود
|
||||
|
||||
---
|
||||
|
||||
## 2) هر بلوک کشاورز جداگانه grid میشود
|
||||
|
||||
فایل اصلی:
|
||||
|
||||
- `location_data/grid_analysis.py`
|
||||
|
||||
اینجا چه اتفاقی میافتد:
|
||||
|
||||
- boundary هر بلوک خوانده میشود
|
||||
- آن بلوک به cell های `30×30` متر تبدیل میشود
|
||||
- برای هر cell یک رکورد ساخته میشود
|
||||
|
||||
مدل ذخیره:
|
||||
|
||||
- `AnalysisGridCell`
|
||||
|
||||
هر `AnalysisGridCell` این چیزها را نگه میدارد:
|
||||
|
||||
- `cell_code`
|
||||
- `block_code`
|
||||
- `geometry`
|
||||
- `centroid_lat`
|
||||
- `centroid_lon`
|
||||
- `chunk_size_sqm`
|
||||
|
||||
یعنی از اینجا به بعد، کوچکترین واحد تحلیل ما دیگر خود بلوک نیست؛
|
||||
بلکه grid های `30×30` داخل هر بلوک هستند.
|
||||
|
||||
---
|
||||
|
||||
## 3) داده ماهوارهای هر grid از openEO گرفته میشود
|
||||
|
||||
فایل اصلی:
|
||||
|
||||
- `location_data/openeo_service.py`
|
||||
|
||||
منطق این بخش شبیه همان چیزی است که گفتی:
|
||||
|
||||
- برای هر بازه زمانی، cube هر سنجنده load میشود
|
||||
- روی زمان `mean_time()` زده میشود
|
||||
- بعد برای geometry هر grid از `aggregate_spatial(..., reducer=\"mean\")` استفاده میشود
|
||||
|
||||
یعنی:
|
||||
|
||||
- داده خام چند روز یا یک ماهه میآید
|
||||
- میانگین همان بازه زمانی برای هر grid محاسبه میشود
|
||||
- همان مقدار میانگین، وضعیت نهایی آن grid در آن بازه است
|
||||
|
||||
metric هایی که الان گرفته میشوند:
|
||||
|
||||
- `ndvi`
|
||||
- `ndwi`
|
||||
- `lst_c`
|
||||
- `soil_vv`
|
||||
- `soil_vv_db`
|
||||
- `dem_m`
|
||||
- `slope_deg`
|
||||
|
||||
نکته مهم:
|
||||
|
||||
- این دادهها برای **تمام grid های یک بلوک** گرفته میشوند
|
||||
- نه فقط برای مرکز مزرعه
|
||||
- نه فقط برای geometry خام
|
||||
|
||||
---
|
||||
|
||||
## 4) داده هر grid داخل جدول ذخیره میشود
|
||||
|
||||
فایل اصلی:
|
||||
|
||||
- `location_data/tasks.py`
|
||||
|
||||
مدل ذخیره:
|
||||
|
||||
- `AnalysisGridObservation`
|
||||
|
||||
برای هر grid و هر بازه زمانی، این دادهها ذخیره میشوند:
|
||||
|
||||
- `ndvi`
|
||||
- `ndwi`
|
||||
- `lst_c`
|
||||
- `soil_vv`
|
||||
- `soil_vv_db`
|
||||
- `dem_m`
|
||||
- `slope_deg`
|
||||
|
||||
پس هر grid یک بردار ویژگی واقعی دارد.
|
||||
|
||||
یعنی به زبان ساده:
|
||||
|
||||
- هر خانه 30×30 فقط یک polygon نیست
|
||||
- یک وضعیت دادهای واقعی هم دارد
|
||||
|
||||
---
|
||||
|
||||
## 5) اینجا یادگیری بدون نظارت استفاده میشود
|
||||
|
||||
فایل اصلی:
|
||||
|
||||
- `location_data/data_driven_subdivision.py`
|
||||
|
||||
اینجا از:
|
||||
|
||||
- `KMeans`
|
||||
|
||||
استفاده میشود.
|
||||
|
||||
این بخش unsupervised است چون:
|
||||
|
||||
- هیچ label آمادهای نداریم
|
||||
- فقط میخواهیم grid هایی که از نظر رفتار ماهوارهای شبیه هم هستند در یک گروه قرار بگیرند
|
||||
|
||||
---
|
||||
|
||||
## 6) feature matrix دقیقاً از چه چیزی ساخته میشود؟
|
||||
|
||||
هر سطر:
|
||||
|
||||
- یک `AnalysisGridCell`
|
||||
|
||||
هر ستون:
|
||||
|
||||
- یکی از feature های ماهوارهای
|
||||
|
||||
feature های پیشفرض:
|
||||
|
||||
- `ndvi`
|
||||
- `ndwi`
|
||||
- `lst_c`
|
||||
- `soil_vv_db`
|
||||
- `dem_m`
|
||||
- `slope_deg`
|
||||
|
||||
یعنی ورودی `KMeans` از observation های واقعی میآید، نه از مختصات هندسی.
|
||||
|
||||
---
|
||||
|
||||
## 7) داده ناقص چطور مدیریت میشود؟
|
||||
|
||||
قبل از اجرای KMeans:
|
||||
|
||||
- اگر یک grid برای همه feature ها خالی باشد، حذف میشود
|
||||
- اگر فقط بعضی feature ها خالی باشند، مقداردهی میشود
|
||||
|
||||
روش فعلی:
|
||||
|
||||
- `median imputation`
|
||||
|
||||
بعد از آن:
|
||||
|
||||
- دادهها استاندارد میشوند
|
||||
|
||||
روش فعلی:
|
||||
|
||||
- `StandardScaler`
|
||||
|
||||
این کار لازم است چون:
|
||||
|
||||
- مقیاس `ndvi` با `dem_m` فرق دارد
|
||||
- مقیاس `dem_m` با `lst_c` فرق دارد
|
||||
|
||||
---
|
||||
|
||||
## 8) برای هر K مقدار SSE ذخیره میشود
|
||||
|
||||
فایل اصلی:
|
||||
|
||||
- `location_data/data_driven_subdivision.py`
|
||||
- `location_data/block_subdivision.py`
|
||||
|
||||
در زمان انتخاب تعداد خوشه:
|
||||
|
||||
- برای `K = 1, 2, 3, ...`
|
||||
- مدل اجرا میشود
|
||||
- مقدار `SSE / Inertia` ذخیره میشود
|
||||
|
||||
این داده داخل metadata نتیجه clustering ذخیره میشود.
|
||||
|
||||
پس ما برای هر بلوک این را داریم:
|
||||
|
||||
- لیست `K`
|
||||
- مقدار `SSE` هر `K`
|
||||
|
||||
---
|
||||
|
||||
## 9) نمودار `K - SSE` رسم میشود
|
||||
|
||||
منطق رسم نمودار در سیستم وجود دارد و از همان منطق elbow استفاده میشود.
|
||||
|
||||
هدف نمودار:
|
||||
|
||||
- ببینیم از چه جایی به بعد کم شدن SSE دیگر خیلی شدید نیست
|
||||
- یعنی شیب نمودار ناگهان کمتر میشود
|
||||
|
||||
همان نقطه:
|
||||
|
||||
- تعداد مناسب زیربلوکهای آن بلوک است
|
||||
|
||||
به زبان ساده:
|
||||
|
||||
- اگر شیب تا `K=3` خیلی زیاد کم شود
|
||||
- ولی بعد از آن خیلی آرام شود
|
||||
- `K=3` انتخاب مناسب است
|
||||
|
||||
---
|
||||
|
||||
## 10) هر بلوک کشاورز جداگانه خوشهبندی میشود
|
||||
|
||||
این خیلی مهم است:
|
||||
|
||||
- کل مزرعه یکجا خوشهبندی نمیشود
|
||||
- هر بلوکی که کشاورز تعریف کرده جداگانه پردازش میشود
|
||||
|
||||
پس برای هر بلوک:
|
||||
|
||||
1. grid های 30×30 ساخته میشوند
|
||||
2. داده ماهوارهای همان grid ها گرفته میشود
|
||||
3. observation ذخیره میشود
|
||||
4. `KMeans` فقط روی grid های همان بلوک اجرا میشود
|
||||
5. تعداد زیربلوکهای مناسب همان بلوک تعیین میشود
|
||||
|
||||
---
|
||||
|
||||
## 11) نتیجه subdivision جدید کجا ذخیره میشود؟
|
||||
|
||||
مدل اصلی نتیجه:
|
||||
|
||||
- `RemoteSensingSubdivisionResult`
|
||||
|
||||
این مدل چیزهای اصلی را نگه میدارد:
|
||||
|
||||
- `block_code`
|
||||
- `cluster_count`
|
||||
- `selected_features`
|
||||
- `skipped_cell_codes`
|
||||
- `kmeans_params`
|
||||
- `inertia_curve`
|
||||
- `cluster_summaries`
|
||||
|
||||
و برای هر grid هم assignment جدا ذخیره میشود در:
|
||||
|
||||
- `RemoteSensingClusterAssignment`
|
||||
|
||||
یعنی برای هر grid مشخص است:
|
||||
|
||||
- در کدام cluster قرار گرفته
|
||||
- raw feature هایش چه بوده
|
||||
- scaled feature هایش چه بوده
|
||||
|
||||
---
|
||||
|
||||
## 12) `BlockSubdivision` الان چه نقشی دارد؟
|
||||
|
||||
الان `BlockSubdivision` دیگر مدل اصلی خوشهبندی نیست.
|
||||
|
||||
نقشش این است که:
|
||||
|
||||
- boundary بلوک کشاورز را نگه دارد
|
||||
- metadata بلوک را نگه دارد
|
||||
- به grid سازی و pipeline کمک کند
|
||||
|
||||
اما نتیجه اصلی data-driven subdivision در این دو مدل ذخیره میشود:
|
||||
|
||||
- `RemoteSensingSubdivisionResult`
|
||||
- `RemoteSensingClusterAssignment`
|
||||
|
||||
---
|
||||
|
||||
## 13) اجرای async کجا انجام میشود؟
|
||||
|
||||
فایل اصلی:
|
||||
|
||||
- `location_data/tasks.py`
|
||||
|
||||
این pipeline داخل Celery اجرا میشود.
|
||||
|
||||
مراحل run:
|
||||
|
||||
1. run ساخته میشود
|
||||
2. grid های بلوک ساخته میشوند
|
||||
3. داده openEO گرفته میشود
|
||||
4. observation ها ذخیره میشوند
|
||||
5. feature matrix ساخته میشود
|
||||
6. `KMeans` اجرا میشود
|
||||
7. نتیجه نهایی ذخیره میشود
|
||||
|
||||
مدل status:
|
||||
|
||||
- `RemoteSensingRun`
|
||||
|
||||
وضعیتهایی که track میشوند:
|
||||
|
||||
- `pending`
|
||||
- `running`
|
||||
- `failed`
|
||||
- `completed`
|
||||
|
||||
---
|
||||
|
||||
## 14) چیزی که حذف شده
|
||||
|
||||
این بخشها دیگر منبع اصلی داده نیستند و باید حذفشده در نظر گرفته شوند:
|
||||
|
||||
- منطق قدیمی دریافت soil depth
|
||||
- adapter های خاک
|
||||
- وابستگی اصلی به `SoilDepthData`
|
||||
|
||||
منبع اصلی داده از این به بعد:
|
||||
|
||||
- داده ماهوارهای هر grid
|
||||
|
||||
یعنی:
|
||||
|
||||
- به جای جدول depth-based
|
||||
- جدول observation های ماهوارهای grid-based مرجع اصلی است
|
||||
|
||||
---
|
||||
|
||||
## 15) خلاصه خیلی کوتاه
|
||||
|
||||
جریان نهایی این است:
|
||||
|
||||
1. گوشههای زمین و بلوکهای کشاورز ثبت میشوند
|
||||
2. هر بلوک به grid های `30×30` تبدیل میشود
|
||||
3. برای هر grid دادهی ماهوارهای یک بازه زمانی از openEO گرفته میشود
|
||||
4. میانگین آن بازه، وضعیت همان grid میشود
|
||||
5. همه grid ها در جدول observation ذخیره میشوند
|
||||
6. برای هر بلوک، روی feature های grid ها `KMeans` اجرا میشود
|
||||
7. برای هر `K` مقدار `SSE` ذخیره میشود
|
||||
8. نمودار `K - SSE` ساخته میشود
|
||||
9. elbow point تعداد مناسب زیربلوکها را مشخص میکند
|
||||
10. هر بلوک کشاورز به چند زیربلوک دادهمحور تقسیم میشود
|
||||
|
||||
این دقیقاً همان منطق اصلی جدید سیستم است.
|
||||
Reference in New Issue
Block a user