379 lines
10 KiB
Markdown
379 lines
10 KiB
Markdown
|
|
# جریان واقعی `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. هر بلوک کشاورز به چند زیربلوک دادهمحور تقسیم میشود
|
|||
|
|
|
|||
|
|
این دقیقاً همان منطق اصلی جدید سیستم است.
|