أكثر

كيف يمكنني الحصول على القيم التي يتم إرجاعها بواسطة كائن حدود OpenLayers بتنسيق خط الطول / خط العرض؟

كيف يمكنني الحصول على القيم التي يتم إرجاعها بواسطة كائن حدود OpenLayers بتنسيق خط الطول / خط العرض؟


لقد قمت بإنشاء خريطة وأضفت طبقة باستخدام مكتبة OpenLayers:

map = new OpenLayers.Map ('map') ؛ var gphy = new OpenLayers.Layer.Google ("Google Physical" ، {type: G_PHYSICAL_MAP}) ؛ map.addLayer (gphy) ؛

يتم تحميل الخريطة ويمكنني توسيط خريطتي:

map.setCenter (OpenLayers.LonLat الجديد (-114.922485 ، 56.400224) ، 4) ؛

لقد قمت بعد ذلك بإنشاء معالج مربع ، لكن الحدود التي تم إرجاعها ليست بتنسيق خط الطول / خط العرض. عند رسم مربع حول مركز خريطتي ، يقوم الكائن المرتبط بي بإرجاع ما يلي:

يسار لأسفل = (278،245) يمين أعلى = (304،211)

كيف يمكنني تحويل هذه القيم إلى خط الطول / خط العرض؟

القرار بفضل unicoletti:

map.getLonLatFromPixel (OpenLayers.Pixel جديد (حدود اليسار ، حدود ، أسفل))

بافتراض أن هذه إحداثيات بكسل يمكنك استخدامها:

map.getLonLatFromPixel

أو أحد وحدات البكسل الأخرى إلى وظائف تحويل خطوط الطول / العرض لكائن الخريطة. تحقق من الوثائق ذات الصلة بإصدار OL الخاص بك للحصول على شرح مفصل.


يحتوي مثيل OpenLayers.Bounds الذي تبحث عنه على 4 خصائص: يسار ، وأسفل ، ويمين ، وأعلى. خط الطول للزاوية اليسرى السفلية محدد ، اليسار ، خط العرض محدد ، أسفل.

لاحظ ، مع ذلك ، أن الإحداثيات المستخدمة من قبل OpenLayers.Bounds و OpenLayers.LonLat ليست بالضرورة خطوط عرض وخطوط طول. أنها تعتمد على إسقاط الطبقة الأساسية. بالنسبة لـ Web mercator ، وهو الإسقاط عند تكوين طبقة Google الأساسية الخاصة بك باستخدام sphericalMercator: صحيح ، ستكون القيم مختلفة تمامًا. للحصول على خط الطول وخط العرض في هذه الحالة ، يمكنك استخدام طريقة التحويل ، على سبيل المثال

bounds.transform (map.getProjectObject () ، OpenLayers.Project جديد ("EPSG: 4326")) ؛

كيفية معالجة بيانات الطقس GRIB2 لتطبيقات توربينات الرياح (GeoJSON)

كتب بواسطة
إليوت ووبلر
مهندس مبيعات تقني

ملخص

يغطي هذا البرنامج التعليمي كيفية العمل مع بيانات التوقعات العالمية Spire Weather & # 8217s بتنسيق GRIB2 باستخدام Python.

إذا لم تكن قد عملت مع بيانات GRIB2 من قبل ، فمن المستحسن أن تبدأ بالبرنامج التعليمي للبدء ، لأن هذا البرنامج الحالي سيتناول موضوعات أكثر تقدمًا قليلاً.

على وجه التحديد ، يوضح هذا البرنامج التعليمي كيفية استرداد سرعة الرياح واتجاهها على مستويات رأسية مختلفة (أي الارتفاعات ذات الصلة بتوربينات الرياح) داخل حدود مضلع معقد (مثل حدود الأمة # 8217s).

بنهاية هذا البرنامج التعليمي ، ستعرف كيفية:

  1. قم بتحميل الملفات التي تحتوي على رسائل GRIB2 في برنامج Python
  2. افحص بيانات GRIB2 لفهم متغيرات الطقس المضمنة
  3. قم بتصفية بيانات GRIB2 لتتوافق مع متغيرات الطقس ذات الأهمية على المستويات الرأسية المختلفة
  4. احسب سرعة الرياح واتجاهها من مكونات الرياح باتجاه الشرق والشمال
  5. قم بقص بيانات GRIB2 إلى المنطقة المحددة بواسطة إدخال ملف GeoJSON
  6. قم بتحويل بيانات GRIB2 المحولة إلى ملف إخراج CSV لمزيد من التحليل والتصور

تنزيل البيانات

الخطوة الأولى هي تنزيل البيانات من Spire Weather & # 8217s File API.

يتوقع هذا البرنامج التعليمي أن تحتوي رسائل GRIB2 على بيانات NWP من حزمة بيانات الطاقة المتجددة Spire & # 8217s.

للحصول على معلومات حول استخدام نقاط نهاية Spire Weather & # 8217s File API ، يرجى الاطلاع على وثائق API والأسئلة الشائعة.

تحتوي الأسئلة الشائعة أيضًا على أمثلة مفصلة تغطي كيفية تنزيل ملفات توقعات متعددة مرة واحدة باستخدام cURL.

لأغراض هذا البرنامج التعليمي ، من المفترض أن بيانات GRIB2 قد تم تنزيلها بالفعل بنجاح ، إذا لم تحصل على عينة هنا.

فهم أسماء الملفات

تشترك جميع الملفات التي تم تنزيلها من Spire Weather & # 8217s API في نفس اصطلاح تسمية الملفات.

بمجرد النظر إلى اسم الملف ، يمكننا تحديد:

  • تاريخ ووقت إصدار التنبؤ
  • تاريخ ووقت صلاحية البيانات المتوقعة
  • الدقة الأفقية لبيانات التنبؤ العالمية
  • متغيرات بيانات الطقس المضمنة في الملف (انظر القائمة الكاملة لحزم بيانات Spire Weather & # 8217s التجارية)

لمزيد من المعلومات التفصيلية حول ما ورد أعلاه ، يرجى الرجوع إلى الأسئلة الشائعة.

متطلبات بايثون

حزم Python التالية مطلوبة لهذا البرنامج التعليمي.

على الرغم من أن استخدام conda ليس مطلوبًا تمامًا ، إلا أنه الطريقة الموصى بها رسميًا لتثبيت PyNIO (انظر الرابط أدناه).

بمجرد إنشاء بيئة conda وتفعيلها ، يمكن تشغيل الأوامر التالية مباشرةً:

فحص البيانات

بعد تنزيل البيانات وإعداد بيئة Python بالحزم المطلوبة ، فإن الخطوة التالية هي فحص محتويات البيانات لتحديد متغيرات الطقس المتاحة للوصول إليها. يمكن إجراء فحص البيانات باستخدام PyNIO فقط ، ولكن في هذا البرنامج التعليمي سنستخدم PyNIO كمحرك لـ xarray وتحميل البيانات في مجموعة بيانات xarray للتحويل. لاحظ أن الاستيراد الصريح لـ PyNIO غير مطلوب ، طالما أنه & # 8217s مثبتًا بشكل صحيح في بيئة Python النشطة.

أولاً ، قم باستيراد حزمة xarray:

بعد ذلك ، افتح بيانات GRIB2 باستخدام xarray باستخدام PyNIO كمحركها (لاحظ أن بيانات GRIB2 يجب أن تكون من Spire & # 8217s طاقة متجددة حزمة البيانات):

ds = xr.open_dataset ("path_to_renewable_energy_file.grib2" ، المحرك = "pynio")

أخيرًا ، لكل من المتغيرات ، اطبع مفتاح البحث والاسم الذي يمكن قراءته ووحدات القياس:

يجب أن يبدو الناتج أعلاه شيئًا كهذا ، مع إعطاء نظرة عامة واضحة على حقول البيانات المتاحة:

نظرًا لأن هذا البرنامج التعليمي يغطي العمل مع بيانات GRIB2 على مستويات رأسية مختلفة ، يجب علينا أيضًا فحص حقل level_type:

يجب أن تبدو مخرجات ما سبق كما يلي:

لاحظ أن ثلاثة من المتغيرات المضمنة لها نفس قيمة نوع المستوى للارتفاع المحدد فوق متوسط ​​مستوى سطح البحر (بالمتر).

هذا يعني أنه يمكن استخدام نفس المنهجية الدقيقة لمعالجة هذه المتغيرات على مستويات رأسية مختلفة ، على الرغم من أنه لغرض هذا البرنامج التعليمي سنلتزم بالنظر في متغيرات مكون الرياح فقط: UGRD_P0_L103_GLL0 و VGRD_P0_L103_GLL0.

فهم قيم الارتفاع

لفهم قيم العمق المتاحة بشكل أفضل ، يمكننا البدء بطباعة البيانات الوصفية لأحد متغيرات مكونات الرياح:
طباعة (ds ["UGRD_P0_L103_GLL0"])
يجب أن يبدو ناتج ما سبق كما يلي:

في نهاية السطر الأول ، لا تحتوي القائمة على أسماء الفهرس lat_0 و lon_0 التي نتوقعها بعد البرنامج التعليمي الأساسي فحسب ، بل تحتوي أيضًا على اسم جديد يسمى lv_HTGL0.
نعلم من بيان الطباعة السابق أن lv_HTGL0 يشير إلى مستوى الارتفاع المحدد فوق الأرض (م) ، وأن السطر الرابع من أحدث مخرجات الطباعة يوفر معاينة لقيم lv_HTGL0. من هذه المعلومات ، يمكننا أن نستنتج أن هناك فهرسًا ثالثًا لهذه البيانات يسمى lv_HTGL0 والذي يتوافق مع ارتفاع البيانات بالأمتار.
يمكننا طباعة البيانات الوصفية على فهرس بنفس الطريقة المستخدمة لفحص المتغيرات:
طباعة (ds ["lv_HTGL0"])
يجب أن تبدو مخرجات ما سبق كما يلي:

يخبرنا السطر الأول من الناتج أن هناك ثلاث قيم محتملة ، معبرًا عنها كـ (lv_HTGL0: 3) ، ويخبرنا السطر الثاني ما هي هذه القيم: [80. ، 100. ، 120.]
هذا يعني أنه لكل زوج فريد من إحداثيات lat_0 و lon_0 ، هناك ثلاث قيم رأسية مميزة (أي ارتفاع) يمكن استردادها عن طريق تحديد قيمة lv_HTGL0 تبلغ 80 أو 100 أو 120.

معالجة البيانات

الآن بعد أن عرفنا متغيرات الطقس والمستويات الرأسية المضمنة في بيانات GRIB2 ، يمكننا البدء في معالجة مجموعة بيانات xarray الخاصة بنا.

تصفية بيانات xarray لمتغير معين

باستخدام xarray ، يتم تصفية مجموعة البيانات & # 8217s محتويات إلى متغيرات اهتمامنا من خلال تحديد مصفوفة من السلاسل:

يوصى بإجراء هذه الخطوة & # 8217s قبل تحويل مجموعة بيانات xarray إلى pandas DataFrame (بدلاً من تصفية DataFrame لاحقًا) ، نظرًا لأنه يقلل من حجم البيانات التي يتم تحويلها وبالتالي يقلل من وقت التشغيل الكلي.

تحويل بيانات xarray إلى pandas.DataFrame

لتحويل مجموعة بيانات xarray التي تمت تصفيتها إلى pandas DataFrame ، ما عليك سوى تشغيل ما يلي:

تصفية pandas.DataFrame لارتفاع معين

باستخدام المعلومات التي تم جمعها من فهم قيم الارتفاع في القسم ، يمكننا الآن تصفية DataFrame إلى ارتفاع معين.

أول شيء نقوم به هو نسخ قيم مؤشر الارتفاع (بالأمتار) في عمود DataFrame جديد:

بعد ذلك ، نقوم بإنشاء التعبير الذي سنستخدمه لتصفية DataFrame.

يمكننا تصفية بيانات مكونات الرياح إلى مستوى ارتفاع 100 متر بالتعبير التالي:

height_filter = (df ["الارتفاع"] == 100)

أخيرًا ، نطبق المرشح على DataFrame:

تمت الآن تصفية DataFrame الخاص بنا ليشمل فقط بيانات مكونات الرياح على ارتفاع 100 متر.

تحميل ملف GeoJSON مع حزمة GDAL Python

على الرغم من تسمية الحزمة التي قمنا بتثبيتها مع conda باسم gdal ، فإننا نستوردها إلى Python باسم osgeo. هذا اختصار لمؤسسة Open Source Geospatial Foundation ، والتي تم ترخيص GDAL / OGR (برنامج مجاني ومفتوح المصدر) من خلاله.

لتحميل بيانات GeoJSON في GDAL ، نستخدم فقط دالة CreateGeometryFromJSON # 8217s:

يعد تنسيق GeoJSON معيارًا شائعًا في عالم أنظمة المعلومات الجغرافية. يمكن تنزيل العديد من مناطق GeoJSON الموجودة مسبقًا مجانًا عبر الإنترنت (مثل الحدود الوطنية والمناطق الاقتصادية الحصرية وما إلى ذلك) ويمكن أيضًا إنشاء أشكال مخصصة في مجموعة متنوعة من أدوات البرامج المجانية ، مثل geojson.io أو geoman.io. في هذا البرنامج التعليمي ، نستخدم دولة إيطاليا كمضلع معقد لدينا ، ولكن هذا يمكن أن يكون بنفس السهولة امتداد مزرعة أو بعض المناطق دون الإقليمية الأخرى.

عند تحميل بيانات GeoJSON في GDAL ، لا يلزم سوى قسم الهندسة للميزة. فيما يلي مثال بسيط لما يمكن أن يحتوي عليه ملف إدخال GeoJSON:

يمكن تحميل ملف GeoJSON في Python باستخدام حزمة json القياسية ، وبعد ذلك يجب تحويله إلى سلسلة Python:

بمجرد تحميل تعريف GeoJSON الخاص بنا في سلسلة Python ، يمكننا إنشاء كائن هندسة GDAL مثل هذا:

الحصول على الصندوق المحيط الذي يحتوي على منطقة GeoJSON

في النهاية سنقوم بقص البيانات إلى المنطقة المحددة المحددة بواسطة ملف GeoJSON ، ولكن هذه عملية مكلفة من الناحية الحسابية ، لذا من الأفضل تحديد حجم البيانات أولاً. من الناحية النظرية ، يمكننا تخطي خطوة الاقتصاص إلى مربع بسيط تمامًا ، ولكن من الناحية العملية ، فإن الأمر يستحق القيام بذلك لتقليل وقت التشغيل الكلي.

يجعل GDAL من السهل حساب المربع المحيط الخشن الذي يحتوي على منطقة GeoJSON المعقدة:

يمكن بعد ذلك الوصول إلى قيم الإحداثيات بشكل فردي من المصفوفة الناتجة:

يعد ترتيب الإحداثيات الجغرافية المكانية مصدرًا شائعًا للارتباك ، لذا احرص على ملاحظة أن دالة GDAL & # 8217s GetEnvelope ترجع مصفوفة حيث تأتي قيم خط الطول قبل قيم خط العرض.

اقتصاص pandas.DataFrame إلى مربع إحاطة جغرافية مكانية

الآن بعد أن تم تحويل البيانات التي تمت تصفيتها إلى إطار بيانات الباندا ولدينا الحدود التي تحتوي على مجال اهتمامنا ، يمكننا اقتصاص البيانات في مربع بسيط.

تتمثل الخطوة الأولى في هذه العملية في تفريغ قيم خطوط الطول والعرض من فهرس DataFrame & # 8217s ، والذي يمكن الوصول إليه من خلال أسماء الفهرس لـ lat_0 و lon_0:

على الرغم من أن قيم خط العرض موجودة بالفعل في النطاق القياسي لـ -90 تحط من +90 درجات ، قيم خط الطول تقع في نطاق 0 ل +360.

لتسهيل التعامل مع البيانات ، نقوم بتحويل قيم خطوط الطول إلى النطاق القياسي لـ -180 درجات ل +180 درجات:

مع بيانات خطوط الطول والعرض الآن في نطاقات القيمة المطلوبة ، يمكننا تخزينها كأعمدة جديدة في DataFrame الموجود لدينا:

بعد ذلك ، نستخدم قيم المربع المحيط من القسم السابق (مكونات مصفوفة bbox) لإنشاء تعبيرات مرشح DataFrame:

أخيرًا ، نطبق عوامل التصفية على DataFrame الموجود لدينا:

تم اقتصاص DataFrame الناتج إلى حدود المربع الذي يحتوي على منطقة GeoJSON المعقدة.

اقتصاص pandas.DataFrame للحدود الدقيقة لمنطقة GeoJSON

من أجل اقتصاص DataFrame إلى الحدود الدقيقة لمنطقة GeoJSON المعقدة ، سنحتاج إلى التحقق من كل زوج إحداثيات في بياناتنا. على غرار القسم السابق حيث قمنا بإعادة تعيين كل قيمة من قيم خطوط الطول ، سنقوم بهذا الإجراء باستخدام تعبير خريطة.

لتمرير كل زوج إحداثيات إلى وظيفة الخريطة ، نقوم بإنشاء عمود DataFrame جديد يسمى النقطة حيث تكون كل قيمة عبارة عن مجموعة تحتوي على كل من خطوط الطول والعرض:

يمكننا بعد ذلك تمرير كل قيمة tuple زوجية إلى وظيفة الخريطة ، جنبًا إلى جنب مع منطقة GeoJSON التي تم تحميلها مسبقًا ، ومعالجتها في وظيفة تسمى check_point_in_area والتي سنحددها أدناه. سترجع الدالة check_point_in_area إما صواب أو خطأ للإشارة إلى ما إذا كان زوج الإحداثيات المقدم داخل المنطقة أم لا. نتيجة لذلك ، سننتهي مع عمود DataFrame جديد من القيم المنطقية يسمى inArea:

بمجرد ملء عمود inArea ، نقوم بإجراء مرشح بسيط لإزالة الصفوف حيث تكون قيمة inArea خطأ. يؤدي هذا إلى إزالة البيانات بشكل فعال لجميع مواقع النقاط التي ليست ضمن منطقة GeoJSON:

بالطبع ، يعتمد نجاح ما سبق على المنطق داخل دالة check_point_in_area ، والتي لم ننفذها بعد. نظرًا لأنه تم تحميل منطقة GeoJSON بـ GDAL ، يمكننا الاستفادة من طريقة هندسة GDAL تسمى تحتوي على للتحقق بسرعة مما إذا كانت المنطقة تحتوي على نقطة معينة. للقيام بذلك ، يجب أولاً تحويل زوج الإحداثيات إلى هندسة wkbPoint في GDAL:

بمجرد أن نحصل على هندسة wkbPoint الخاصة بنا ، نقوم ببساطة بتمريرها إلى المنطقة. تحتوي على طريقة للتحقق مما إذا كانت المنطقة تحتوي على النقطة:

بتجميع الأجزاء معًا ، إليك ما نحصل عليه لوظيفة check_point_in_area النهائية الخاصة بنا:

كما ترى ، المتغير الوحيد الذي يتم إرجاعه بواسطة دالة check_point_in_area هو قيمة منطقية تشير إلى ما إذا كانت النقطة المحددة في المنطقة أم لا. ثم تملأ هذه القيم المنطقية عمود inArea DataFrame الجديد. يتيح لنا ذلك تطبيق الفلتر من الأعلى وينتهي بنا الأمر بالبيانات المقطوعة بدقة التي نريدها:

حساب سرعة واتجاه الرياح من مكونات الرياح

الآن بعد أن تم اقتصاص البيانات إلى منطقة اهتمامنا & # 8211 تقليل الحجم الإجمالي لنقاط البيانات الخاصة بنا & # 8211 ، يمكننا حساب سرعة الرياح واتجاهها من قيم مكونات الرياح باتجاه الشرق (U) والشمال (V).

أولاً ، نحتاج إلى استيراد بعض وظائف المرافق من وحدة الرياضيات Python & # 8217s:

بعد ذلك ، يمكن حساب سرعة الرياح بما يلي:

يمكن حساب اتجاه الرياح على النحو التالي:

لاحظ أن القيم التي تم إرجاعها بواسطة الدالة wind_direction_from_u_v تشير إلى تمثيل الأرصاد الجوية لاتجاه الرياح بالدرجات:

من أجل تطبيق هذه الوظائف عبر جميع نقاط البيانات في DataFrame لدينا ، نحتاج إلى استخدام وظائف lambda:

بمجرد تحديد وظائف lambda ، يمكننا تطبيقها على DataFrame وتعيين مخرجاتها إلى أعمدة بيانات جديدة:

لدينا الآن أعمدة بيانات جديدة تسمى سرعة الرياح واتجاه الرياح والتي تحتوي على القيم المحسوبة لكل موقع.

تحليل وقت التنبؤ من اسم الملف

يحتوي كل ملف فردي على بيانات توقعات الطقس العالمية لنفس النقطة الزمنية.

باستخدام معرفتنا من فهم أسماء الملفات في هذا البرنامج التعليمي ، وبافتراض أن وسيطة اسم الملف بالتنسيق المتوقع ، يمكننا كتابة دالة لتحليل وقت التنبؤ الصالح من اسم الملف:

بعد ذلك ، يمكننا إنشاء عمود DataFrame جديد للوقت والذي يخزن هذه القيمة كسلسلة في كل صف:

على الرغم من أنه قد يبدو من غير الضروري تخزين نفس قيمة الطابع الزمني بالضبط في كل صف ، فهذه خطوة مهمة إذا أردنا في النهاية ربط DataFrame لدينا ببيانات التنبؤ لأوقات أخرى (موضحة أدناه في معالجة ملفات بيانات متعددة).

حفظ البيانات في ملف إخراج CSV

قم بإجراء مرشح نهائي على DataFrame الخاص بنا لتحديد الأعمدة التي نريدها فقط في مخرجاتنا:

احفظ DataFrame الذي تمت معالجته في ملف إخراج CSV:

يضمن ضبط الفهرس = False أن أعمدة فهرس DataFrame لم يتم تضمينها في الإخراج. بهذه الطريقة ، نستبعد قيم lat_0 و lon_0 و lv_HTGL0 نظرًا لأن لدينا بالفعل أعمدة لخط العرض وخط الطول المعاد تعيينه (وجميع البيانات المتبقية على نفس الارتفاع بعد التصفية).

يرجى ملاحظة أن التحويل من GRIB2 إلى CSV يمكن أن يؤدي إلى أحجام ملفات كبيرة جدًا، خاصةً إذا لم يتم اقتصاص البيانات أو تصفيتها بشكل كبير.

معالجة ملفات بيانات متعددة

غالبًا ما يكون من المرغوب فيه معالجة ملفات بيانات متعددة في وقت واحد ، من أجل دمج النتائج في ملف إخراج CSV واحد موحد.

على سبيل المثال ، لنفترض & # 8217s أننا استخدمنا للتو Spire Weather API لتنزيل توقعات كاملة بقيمة & # 8217s لبيانات GRIB2 في دليل محلي يسمى بيانات التنبؤ /. يمكننا بعد ذلك قراءة أسماء الملفات هذه في قائمة وفرزها أبجديًا لإجراء قياس جيد:

من هنا ، يمكننا التكرار من خلال أسماء الملفات وتمرير كل منها إلى وظيفة تؤدي الخطوات الموضحة في ملف معالجة البيانات قسم من هذا البرنامج التعليمي.

بمجرد أن تصبح جميع إطارات DataFrame النهائية لدينا جاهزة ، يمكننا استخدام الباندا لربطها ببعضها البعض على هذا النحو (حيث تمثل final_dataframes قائمة من إطارات البيانات):

ننتهي مع DataFrame مدمج يسمى output_df والذي يمكننا حفظه في ملف CSV الناتج كما فعلنا من قبل:

كود كامل

يوجد أدناه نص Python تشغيلي يستخدم التقنيات الموضحة في هذا البرنامج التعليمي ويتضمن أيضًا تعليقات توضيحية مضمنة.

يأخذ البرنامج النصي ثلاث وسائط (أسماء متغيرات مكون الرياح مشفرة في البرنامج النصي):

الدليل المحلي حيث يتم تخزين بيانات GRIB2 لطقس الطاقة المتجددة

المسار إلى ملف GeoJSON يحدد منطقة الاهتمام

قيمة مؤشر الارتفاع لتصفية البيانات إلى مستوى رأسي واحد (80 أو 100 أو 120)

على سبيل المثال ، يمكن تشغيل البرنامج النصي على النحو التالي:

python script.py --source-data grib_directory / --geojson italy.json --height 100

ها هو الكود الكامل:

ملاحظات نهائية

باستخدام إخراج بيانات CSV من البرنامج النصي النهائي ، يمكننا الآن بسهولة تصور البيانات المعالجة في أداة مجانية مثل kepler.gl. يمكننا أيضًا تعيين عتبات للتنبيهات أو إنشاء إحصائيات أو دمج مجموعات البيانات الأخرى.

تقدم Spire Weather أيضًا تصورات تم إنشاؤها مسبقًا من خلال واجهة برمجة تطبيقات Web Map Service (WMS) والتي يمكنك قراءة المزيد عنها هنا.

للحصول على عينات أكواد إضافية ، تحقق من مستودع GitHub العام لـ Spire Weather & # 8217s.

هل ترغب في حجز استشارة؟

تعرف على المزيد حول واجهات برمجة التطبيقات الخاصة بالطقس وكيف يمكن لـ Spire Weather مساعدتك في تمكين ميزة البيانات.


كيفية معالجة بيانات الطقس GRIB2 للتطبيقات الزراعية (GeoJSON)

كتب بواسطة
إليوت ووبلر
مهندس الحلول الفنية

يغطي هذا البرنامج التعليمي كيفية العمل مع بيانات التوقعات العالمية لـ Spire Weather بتنسيق GRIB2 باستخدام Python.

يستخدم هذا البرنامج التعليمي إدخال GeoJSON.

ملخص

يغطي هذا البرنامج التعليمي كيفية العمل مع بيانات التوقعات العالمية Spire Weather & # 8217s بتنسيق GRIB2 باستخدام Python.

إذا لم تكن قد عملت مع بيانات GRIB2 من قبل ، فمن المستحسن أن تبدأ بالبرنامج التعليمي للبدء ، لأن هذا البرنامج الحالي سيتناول موضوعات أكثر تقدمًا قليلاً.

على وجه التحديد ، يوضح هذا البرنامج التعليمي كيفية استرداد بيانات رطوبة التربة على أعماق مختلفة داخل حدود مضلع معقد (على سبيل المثال ، حدود الأمة # 8217s).

بنهاية هذا البرنامج التعليمي ، ستعرف كيفية:

  1. قم بتحميل الملفات التي تحتوي على رسائل GRIB2 في برنامج Python
  2. افحص بيانات GRIB2 لفهم متغيرات الطقس المضمنة
  3. تصفية بيانات GRIB2 لمتغيرات الطقس ذات الأهمية على أعماق مختلفة
  4. قم بقص بيانات GRIB2 إلى المنطقة المحددة بواسطة إدخال ملف GeoJSON
  5. قم بتحويل بيانات GRIB2 المحولة إلى ملف إخراج CSV لمزيد من التحليل والتصور

تنزيل البيانات

الخطوة الأولى هي تنزيل البيانات من Spire Weather & # 8217s File API.

يتوقع هذا البرنامج التعليمي أن تحتوي رسائل GRIB2 على بيانات NWP من حزمة البيانات الزراعية Spire & # 8217s.

للحصول على معلومات حول استخدام نقاط نهاية Spire Weather & # 8217s File API ، يرجى الاطلاع على وثائق API والأسئلة الشائعة.

تحتوي الأسئلة الشائعة أيضًا على أمثلة مفصلة تغطي كيفية تنزيل ملفات توقعات متعددة مرة واحدة باستخدام cURL.

لأغراض هذا البرنامج التعليمي ، من المفترض أن بيانات GRIB2 قد تم تنزيلها بالفعل بنجاح ، إذا لم تحصل على عينة هنا.

فهم أسماء الملفات

تشترك جميع الملفات التي تم تنزيلها من Spire Weather & # 8217s API في نفس اصطلاح تسمية الملفات.

بمجرد النظر إلى اسم الملف ، يمكننا تحديد:

  • تاريخ ووقت إصدار التنبؤ
  • تاريخ ووقت صلاحية البيانات المتوقعة
  • الدقة الأفقية لبيانات التنبؤ العالمية
  • متغيرات بيانات الطقس المضمنة في الملف (انظر القائمة الكاملة لحزم البيانات التجارية Spire Weather & # 8217s)

لمزيد من المعلومات التفصيلية حول ما ورد أعلاه ، يرجى الرجوع إلى الأسئلة الشائعة.

متطلبات بايثون

حزم Python التالية مطلوبة لهذا البرنامج التعليمي.

على الرغم من أن استخدام conda ليس مطلوبًا تمامًا ، إلا أنه الطريقة الموصى بها رسميًا لتثبيت PyNIO (انظر الرابط أدناه).

بمجرد إنشاء بيئة conda وتفعيلها ، يمكن تشغيل الأوامر التالية مباشرةً:

فحص البيانات

بعد تنزيل البيانات وإعداد بيئة Python بالحزم المطلوبة ، فإن الخطوة التالية هي فحص محتويات البيانات لتحديد متغيرات الطقس المتاحة للوصول إليها. يمكن إجراء فحص البيانات باستخدام PyNIO فقط ، ولكن في هذا البرنامج التعليمي سنستخدم PyNIO كمحرك لـ xarray وتحميل البيانات في مجموعة بيانات xarray للتحويل. لاحظ أن الاستيراد الصريح لـ PyNIO غير مطلوب ، طالما أنه & # 8217s مثبتًا بشكل صحيح في بيئة Python النشطة.

أولاً ، قم باستيراد حزمة xarray:

بعد ذلك ، افتح بيانات GRIB2 باستخدام xarray باستخدام PyNIO كمحركها (لاحظ أن بيانات GRIB2 يجب أن تكون من Spire & # 8217s زراعي حزمة البيانات):

ds = xr.open_dataset ("path_to_agricultural_file.grib2" ، المحرك = "pynio")

أخيرًا ، لكل من المتغيرات ، اطبع مفتاح البحث والاسم الذي يمكن قراءته ووحدات القياس:

يجب أن يبدو الناتج أعلاه شيئًا كهذا ، مع إعطاء نظرة عامة واضحة على حقول البيانات المتاحة:

نظرًا لأن هذا البرنامج التعليمي يغطي العمل مع بيانات GRIB2 على مستويات رأسية مختلفة ، يجب علينا أيضًا فحص حقل level_type:

يجب أن تبدو مخرجات ما سبق كما يلي:

لاحظ أن lv_DBLL0_l0 و lv_DBLL0_l1 غائبان الآن عن الإخراج. هذا لأنها حقول خاصة تحتوي على بيانات تصف نطاقات العمق المتاحة. سنعود إلى هذين الحقلين في القسم التالي: فهم قيم العمق.

هناك شيء آخر يجب الإشارة إليه هنا وهو أن SOILW_P0_2L106_GLL0 و TSOIL_P0_2L106_GLL0 لهما نفس قيمة level_type. هذا يعني أنه يمكن استخدام نفس المنهجية الدقيقة لمعالجة رطوبة التربة أو درجة حرارة التربة على أعماق مختلفة ، على الرغم من أنه لغرض هذا البرنامج التعليمي سنلتزم بالنظر في رطوبة التربة فقط.

فهم قيم العمق

لفهم قيم العمق المتاحة بشكل أفضل ، يمكننا البدء بطباعة البيانات الوصفية لمتغير رطوبة التربة:
طباعة (ds ["SOILW_P0_2L106_GLL0"])
يجب أن يبدو ناتج ما سبق كما يلي:

في نهاية السطر الأول ، لا تحتوي القائمة على أسماء الفهرس lat_0 و lon_0 التي نتوقعها بعد البرنامج التعليمي الأساسي فحسب ، بل تحتوي أيضًا على اسم جديد يسمى lv_DBLL0.
نعلم من بيان الطباعة السابق أن lv_DBLL0 يشير إلى العمق تحت سطح الأرض ، ويخبرنا السطر السادس من أحدث إخراج للطباعة أن lv_DBLL0 هو بُعد بدون إحداثيات. من هذه المعلومات ، يمكننا أن نستنتج أن هناك فهرسًا ثالثًا لهذه البيانات يسمى lv_DBLL0 والذي يشير إلى مستوى العمق في التربة الذي تتوافق معه بيانات الرطوبة.
يمكننا طباعة البيانات الوصفية على فهرس بنفس الطريقة المستخدمة لفحص المتغيرات:
طباعة (ds ["lv_DBLL0"])
يجب أن تبدو مخرجات ما سبق كما يلي:

يخبرنا السطر الأول من الناتج أن هناك أربع قيم محتملة ، معبرًا عنها كـ (lv_DBLL0: 4) ، ويخبرنا السطر الثاني ما هي هذه القيم: [0 ، 1 ، 2 ، 3]
هذا يعني أنه لكل زوج فريد من إحداثيات lat_0 و lon_0 ، توجد أربع قيم مميزة لرطوبة التربة يمكن استردادها عن طريق تحديد قيمة lv_DBLL0 تبلغ 0 أو 1 أو 2 أو 3.
من أجل تحديد نطاقات العمق التي تتوافق معها قيم الفهرس هذه فعليًا ، نحتاج إلى مزيد من البحث عن طريق فحص المتغيرات ذات الصلة من مخرجات الطباعة الأولية: lv_DBLL0_l0 و lv_DBLL0_l1
طباعة (ds ["lv_DBLL0_l0"])
يجب أن تبدو مخرجات ما سبق كما يلي:

يمكننا بعد ذلك فعل الشيء نفسه مع المتغير lv_DBLL0_l1:
طباعة (ds ["lv_DBLL0_l1"])
يجب أن تبدو مخرجات ما سبق كما يلي:

ما يخبرنا به هذا هو أن:

تتوافق قيمة lv_DBLL0 التي تبلغ 0 مع قيمة lv_DBLL0_l0 تبلغ 0.0 متر وقيمة lv_DBLL0_l1 تبلغ 0.1 متر

تتوافق قيمة lv_DBLL0 البالغة 1 مع قيمة lv_DBLL0_l0 تبلغ 0.1 متر وقيمة lv_DBLL0_l1 تساوي 0.4 متر

قيمة lv_DBLL0 2 تقابل lv_DBLL0_l0 قيمة 0.4 متر وقيمة lv_DBLL0_l1 1.0 متر

قيمة lv_DBLL0 3 تقابل lv_DBLL0_l0 قيمة 1.0 متر وقيمة lv_DBLL0_l1 2.0 متر

تتوافق قيمة 1 lv_DBLL0 مع عمق 10 سم إلى 40 سم

تتوافق قيمة lv_DBLL0 البالغة 2 مع عمق 40 سم إلى 100 سم

قيمة lv_DBLL0 3 تقابل عمق 100 سم إلى 200 سم

معالجة البيانات

الآن بعد أن عرفنا متغيرات الطقس والمستويات الرأسية المضمنة في بيانات GRIB2 ، يمكننا البدء في معالجة مجموعة بيانات xarray الخاصة بنا.

تصفية بيانات xarray لمتغير معين

باستخدام xarray ، تكون تصفية مجموعة البيانات & # 8217 s إلى متغير واحد مهم أمرًا بسيطًا للغاية:

من الممكن أيضًا تحديد متغيرات متعددة باستخدام مصفوفة من السلاسل كمدخل: ds = ds.get ([var1، var2])

يوصى بإجراء هذه الخطوة & # 8217s قبل تحويل مجموعة بيانات xarray إلى pandas DataFrame (بدلاً من تصفية DataFrame لاحقًا) ، نظرًا لأنه يقلل من حجم البيانات التي يتم تحويلها وبالتالي يقلل من وقت التشغيل الكلي.

تحويل بيانات xarray إلى pandas.DataFrame

لتحويل مجموعة بيانات xarray التي تمت تصفيتها إلى pandas DataFrame ، ما عليك سوى تشغيل ما يلي:

تصفية pandas.DataFrame إلى نطاق عمق معين

باستخدام المعلومات التي تم جمعها من فهم قيم العمق في القسم ، يمكننا الآن تصفية DataFrame إلى نطاق عمق معين.

أول شيء نقوم به هو نسخ قيم مؤشر العمق إلى عمود DataFrame جديد:

بعد ذلك ، نقوم بإنشاء التعبير الذي سنستخدمه لتصفية DataFrame.

نعلم من تحليلنا السابق أن قيمة lv_DBLL0 التي تساوي 0 تقابل عمق 0 سم إلى 10 سم.

لذلك ، يمكننا تصفية بيانات رطوبة التربة إلى نطاق عمق يتراوح من 0 إلى 10 سم بالتعبير التالي:

أخيرًا ، نطبق المرشح على DataFrame:

تمت الآن تصفية DataFrame الخاص بنا ليشمل فقط بيانات رطوبة التربة في نطاق عمق 0-10 سم.

تحميل ملف GeoJSON مع حزمة GDAL Python

على الرغم من تسمية الحزمة التي قمنا بتثبيتها مع conda باسم gdal ، فإننا نستوردها إلى Python باسم osgeo. هذا اختصار لمؤسسة Open Source Geospatial Foundation ، والتي تم ترخيص GDAL / OGR (برنامج مجاني ومفتوح المصدر) من خلاله.

لتحميل بيانات GeoJSON في GDAL ، نستخدم فقط دالة CreateGeometryFromJSON # 8217s:

يعد تنسيق GeoJSON معيارًا شائعًا في عالم أنظمة المعلومات الجغرافية. يمكن تنزيل العديد من مناطق GeoJSON الموجودة مسبقًا مجانًا عبر الإنترنت (مثل الحدود الوطنية والمناطق الاقتصادية الحصرية وما إلى ذلك) ويمكن أيضًا إنشاء أشكال مخصصة في مجموعة متنوعة من أدوات البرامج المجانية ، مثل geojson.io أو geoman.io. في هذا البرنامج التعليمي ، نستخدم دولة إيطاليا كمضلع معقد لدينا ، ولكن هذا يمكن أن يكون بنفس السهولة امتداد مزرعة أو بعض المناطق دون الإقليمية الأخرى.

عند تحميل بيانات GeoJSON في GDAL ، لا يلزم سوى قسم الهندسة للميزة. فيما يلي مثال بسيط لما يمكن أن يحتوي عليه ملف إدخال GeoJSON:

يمكن تحميل ملف GeoJSON في Python باستخدام حزمة json القياسية ، وبعد ذلك يجب تحويله إلى سلسلة Python:

بمجرد تحميل تعريف GeoJSON الخاص بنا في سلسلة Python ، يمكننا إنشاء كائن هندسة GDAL مثل هذا:

الحصول على الصندوق المحيط الذي يحتوي على منطقة GeoJSON

في النهاية سنقوم بقص البيانات إلى المنطقة المحددة المحددة بواسطة ملف GeoJSON ، ولكن هذه عملية مكلفة من الناحية الحسابية ، لذا من الأفضل تحديد حجم البيانات أولاً. من الناحية النظرية ، يمكننا تخطي خطوة الاقتصاص إلى مربع بسيط تمامًا ، ولكن من الناحية العملية ، فإن الأمر يستحق القيام بذلك لتقليل وقت التشغيل الكلي.

يجعل GDAL من السهل حساب المربع المحيط الخشن الذي يحتوي على منطقة GeoJSON المعقدة:

يمكن بعد ذلك الوصول إلى قيم الإحداثيات بشكل فردي من المصفوفة الناتجة:

يعد ترتيب الإحداثيات الجغرافية المكانية مصدرًا شائعًا للارتباك ، لذا احرص على ملاحظة أن دالة GDAL & # 8217s GetEnvelope ترجع مصفوفة حيث تأتي قيم خط الطول قبل قيم خط العرض.

اقتصاص pandas.DataFrame إلى مربع إحاطة جغرافية مكانية

الآن بعد أن تم تحويل البيانات التي تمت تصفيتها إلى إطار بيانات الباندا ولدينا الحدود التي تحتوي على مجال اهتمامنا ، يمكننا اقتصاص البيانات في مربع بسيط.

تتمثل الخطوة الأولى في هذه العملية في تفريغ قيم خطوط الطول والعرض من فهرس DataFrame & # 8217s ، والذي يمكن الوصول إليه من خلال أسماء الفهرس لـ lat_0 و lon_0:

على الرغم من أن قيم خط العرض موجودة بالفعل في النطاق القياسي لـ -90 تحط من +90 درجات ، قيم خط الطول تقع في نطاق 0 ل +360.

لتسهيل التعامل مع البيانات ، نقوم بتحويل قيم خطوط الطول إلى النطاق القياسي لـ -180 درجات ل +180 درجات:

مع بيانات خطوط الطول والعرض الآن في نطاقات القيمة المطلوبة ، يمكننا تخزينها كأعمدة جديدة في DataFrame الموجود لدينا:

بعد ذلك ، نستخدم قيم المربع المحيط من القسم السابق (مكونات مصفوفة bbox) لإنشاء تعبيرات مرشح DataFrame:

أخيرًا ، نطبق عوامل التصفية على DataFrame الموجود لدينا:

تم اقتصاص DataFrame الناتج إلى حدود المربع الذي يحتوي على منطقة GeoJSON المعقدة.

اقتصاص pandas.DataFrame للحدود الدقيقة لمنطقة GeoJSON

من أجل اقتصاص DataFrame إلى الحدود الدقيقة لمنطقة GeoJSON المعقدة ، سنحتاج إلى التحقق من كل زوج إحداثيات في بياناتنا. على غرار القسم السابق حيث قمنا بإعادة تعيين كل قيمة من قيم خطوط الطول ، سنقوم بهذا الإجراء باستخدام تعبير خريطة.

لتمرير كل زوج إحداثيات إلى وظيفة الخريطة ، نقوم بإنشاء عمود DataFrame جديد يسمى النقطة حيث تكون كل قيمة عبارة عن مجموعة تحتوي على كل من خطوط الطول والعرض:

يمكننا بعد ذلك تمرير كل قيمة tuple زوجية إلى وظيفة الخريطة ، جنبًا إلى جنب مع منطقة GeoJSON التي تم تحميلها مسبقًا ، ومعالجتها في وظيفة تسمى check_point_in_area والتي سنحددها أدناه. سترجع الدالة check_point_in_area إما صواب أو خطأ للإشارة إلى ما إذا كان زوج الإحداثيات المقدم داخل المنطقة أم لا. نتيجة لذلك ، سننتهي مع عمود DataFrame جديد من القيم المنطقية يسمى inArea:

بمجرد ملء عمود inArea ، نقوم بإجراء مرشح بسيط لإزالة الصفوف حيث تكون قيمة inArea خطأ. يؤدي هذا إلى إزالة البيانات بشكل فعال لجميع مواقع النقاط التي ليست ضمن منطقة GeoJSON:

بالطبع ، يعتمد نجاح ما سبق على المنطق داخل دالة check_point_in_area ، والتي لم ننفذها بعد. نظرًا لأنه تم تحميل منطقة GeoJSON بـ GDAL ، يمكننا الاستفادة من طريقة هندسة GDAL تسمى تحتوي على للتحقق بسرعة مما إذا كانت المنطقة تحتوي على نقطة معينة. للقيام بذلك ، يجب أولاً تحويل زوج الإحداثيات إلى هندسة wkbPoint في GDAL:

Once we have our wkbPoint geometry, we simply pass it into the area.Contains method to check if the area contains the point:

Putting the pieces together, here is what we get for our final check_point_in_area function:

As you can see, the only variable returned by the check_point_in_area function is a boolean value indicating whether the specified point is in the area or not. These boolean values then populate the new inArea DataFrame column. This allows us to apply the filter from above and end up with the precisely cropped data we want:

Parsing the forecast time from the filename

Each individual file contains global weather forecast data for the same point in time.

Using our knowledge from the Understanding Filenames section of this tutorial, and assuming that the filename argument is in the expected format, we can write a function to parse the valid forecast time from the filename:

Then, we can create a new DataFrame column for time which stores this value as a string in every row:

Although it may seem unnecessary to store the same exact timestamp value in every row, this is an important step if we want to eventually concatenate our DataFrame with forecast data for other times (demonstrated below in Processing Multiple Data Files).

Saving the data to a CSV output file

Perform a final filter on our DataFrame to select only the columns that we want in our output, where variable is a string like "SOILW_P0_2L106_GLL0" :

Save the processed DataFrame to an output CSV file:

Setting the index=False parameter ensures that the DataFrame index columns are not included in the output. This way, we exclude the lat_0 , lon_0 , and lv_DBLL0 values since we already have columns for latitude and remapped longitude (and all remaining data is at the same depth after our filtering).

Please note that converting from GRIB2 to CSV can result in very large file sizes, especially if the data is not significantly cropped or filtered.

Processing Multiple Data Files

It is often desirable to process multiple data files at once, in order to combine the results into a single unified CSV output file.

For example, let’s say that we have just used the Spire Weather API to download a full forecast’s worth of GRIB2 data into a local directory called forecast_data/ . We can then read those filenames into a list and sort them alphabetically for good measure:

From here, we can iterate through the filenames and pass each one into a function that performs the steps outlined in the Processing the Data section of this tutorial.

Once all of our final DataFrames are ready, we can use pandas to concatenate them together like so (where final_dataframes is a list of DataFrames):

We end up with a combined DataFrame called output_df which we can save to an output CSV file like we did before:

Complete Code

Below is an operational Python script which uses the techniques described in this tutorial and also includes explanatory in-line comments.

The script takes four arguments:

The weather data variable of interest ( SOILW_P0_2L106_GLL0 or TSOIL_P0_2L106_GLL0 )

The local directory where the Agricultural Weather GRIB2 data is stored

The path to the GeoJSON file defining the area of interest

The depth range index value for filtering the data to a single vertical level ( 0 , 1 , 2 , or 3 )

For example, the script can be run like this:

python script.py --variable SOILW_P0_2L106_GLL0 --source-data grib_directory/ --geojson italy.json --depth 0

Here is the complete code:

Final Notes

Using the CSV data output from our final script, we can now easily visualize the processed data in a free tool such as kepler.gl. We can also set thresholds for alerts, generate statistics, or fuse with other datasets.

The visualization included below – originally featured in a Spire data story – was created with Kepler using the techniques covered in this tutorial. Spire Weather also offers pre-created visualizations through the Web Map Service (WMS) API which you can read more about here.

For additional code samples, check out Spire Weather’s public GitHub repository.


OpenLayers.Map

Instances of OpenLayers.Map are interactive maps embedded in a web page. Create a new map with the OpenLayers.Map constructor.

On their own maps do not provide much functionality. To extend a map it&rsquos necessary to add controls (OpenLayers.Control) and layers (OpenLayers.Layer) to the map.

OpenLayers.MapInstances of OpenLayers.Map are interactive maps embedded in a web page.
Constants
Z_INDEX_BASE Base z-indexes for different classes of thing
EVENT_TYPES Supported application event types.
ملكيات
events An events object that handles all events on the map
allOverlays Allow the map to function with &ldquooverlays&rdquo only.
div The element that contains the map (or an id for that element).
طبقات Ordered list of layers in the map
baseLayer The currently selected base layer.
tileSize Set in the map options to override the default tile size for this map.
تنبؤ Set in the map options to override the default projection string this map - also set maxExtent, maxResolution, and units if appropriate.
الوحدات The map units.
resolutions A list of map resolutions (map units per pixel) in descending order.
maxResolution Default max is 360 deg / 256 px, which corresponds to zoom level 0 on gmaps.
minResolution
maxScale
الحد الأدنى
maxExtent The maximum extent for the map.
minExtent
restrictedExtent Limit map navigation to this extent where possible.
numZoomLevels Number of zoom levels for the map.
سمة Relative path to a CSS file from which to load theme styles.
displayProjection Requires proj4js support.Projection used by several controls to display data to user.
fallThrough Should OpenLayers allow events on the map to fall through to other elements on the page, or should it swallow them?
eventListeners If set as an option at construction, the eventListeners object will be registered with <OpenLayers.Events.on>.
panMethod The Easing function to be used for tweening.
البناء
OpenLayers.MapConstructor for a new OpenLayers.Map instance.
المهام
يقدم - يجعلRender the map to a specified container.
هدمDestroy this map
setOptionsChange the map options
getTileSizeGet the tile size for the map
getByGet a list of objects given a property and a match item.
getLayersByGet a list of layers with properties matching the given criteria.
getLayersByNameGet a list of layers with names matching the given name.
getLayersByClassGet a list of layers of a given class (CLASS_NAME).
getControlsByGet a list of controls with properties matching the given criteria.
getControlsByClassGet a list of controls of a given class (CLASS_NAME).
getLayerGet a layer based on its id
addLayer
addLayers
removeLayerRemoves a layer from the map by removing its visual element (the layer.div property), then removing it from the map&rsquos internal list of layers, setting the layer&rsquos map property to null.
getNumLayers The number of layers attached to the map.
getLayerIndex
setLayerIndexMove the given layer to the specified (zero-based) index in the layer list, changing its z-index in the map display.
raiseLayerChange the index of the given layer by delta.
setBaseLayerAllows user to specify one of the currently-loaded layers as the Map&rsquos new base layer.
addControl
getControl
removeControlRemove a control from the map.
addPopup
removePopup
getSize An OpenLayers.Size object that represents the size, in pixels, of the div into which OpenLayers has been loaded.
updateSizeThis function should be called by any external code which dynamically changes the size of the map div (because mozilla wont let us catch the &ldquoonresize&rdquo for an element)
getCenter
getZoom
حرمانAllows user to pan by a value of screen pixels
panToAllows user to pan to a new lonlat If the new lonlat is in the current extent the map will slide smoothly
setCenterSet the map center (and optionally, the zoom level).
getProjectionThis method returns a string representing the projection.
getProjectionObjectReturns the projection obect from the baselayer.
getMaxResolution The Map&rsquos Maximum Resolution
getMaxExtent
getNumZoomLevels The total number of zoom levels that can be displayed by the current baseLayer.
getExtent A Bounds object which represents the lon/lat bounds of the current viewPort.
getResolution The current resolution of the map.
getUnits The current units of the map.
getScale The current scale denominator of the map.
getZoomForExtent
getResolutionForZoom
getZoomForResolution
zoomToZoom to a specific zoom level
zoomIn
zoomOut
zoomToExtentZoom to the passed in bounds, recenter
zoomToMaxExtentZoom to the full extent and recenter.
zoomToScaleZoom to a specified scale
getViewPortPxFromLonLat
getLonLatFromPixel
getPixelFromLonLatReturns a pixel location given a map location.
getViewPortPxFromLayerPx
getLayerPxFromViewPortPx
getLayerPxFromLonLat
Constants
TILE_WIDTH 256 Default tile width (unless otherwise specified)
TILE_HEIGHT 256 Default tile height (unless otherwise specified)

Constants

Z_INDEX_BASE

Base z-indexes for different classes of thing

EVENT_TYPES

Supported application event types. Register a listener for a particular event with the following syntax:

Listeners will be called with a reference to an event object. The properties of this event depends on exactly what happened.

All event objects have at least the following properties

  • مفعولA reference to map.events.object.
  • جزءA reference to map.events.element.

Browser events have the following additional properties

  • س ص The pixel location of the event (relative to the the map viewport).
  • other properties that come with browser events

Supported map event types

  • preaddlayer triggered before a layer has been added. The event object will include a طبقة property that references the layer to be added.
  • addlayer triggered after a layer has been added. The event object will include a طبقة property that references the added layer.
  • removelayer triggered after a layer has been removed. The event object will include a طبقة property that references the removed layer.
  • changelayer triggered after a layer name change, order change, opacity change or visibility change (due to resolution thresholds). Listeners will receive an event object with طبقة و خاصية الخصائص. ال طبقة property will be a reference to the changed layer. ال خاصية property will be a key to the changed property (name, order, opacity or visibility).
  • بدء تشغيل triggered after the start of a drag, pan, or zoom
  • نقل triggered after each drag, pan, or zoom
  • تحرك triggered after a drag, pan, or zoom completes
  • زوميند triggered after a zoom completes
  • addmarker triggered after a marker has been added
  • removemarker triggered after a marker has been removed
  • clearmarkers triggered after markers have been cleared
  • تمرير الماوس triggered after mouseover the map
  • تجاوز الماوس triggered after mouseout the map
  • تحرك الماوس triggered after mousemove the map
  • dragstart Does not work. Register for movestart instead.
  • يجر Does not work. Register for move instead.
  • dragend Does not work. Register for moveend instead.
  • changebaselayer triggered after the base layer changes

ملكيات

Events

An events object that handles all events on the map

AllOverlays

Allow the map to function with &ldquooverlays&rdquo only. Defaults to false. If true, the lowest layer in the draw order will act as the base layer. In addition, if set to true, all layers will have isBaseLayer set to false when they are added to the map.

If you set map.allOverlays to true, then you لا تستطيع use map.setBaseLayer or layer.setIsBaseLayer. With allOverlays true, the lowest layer in the draw layer is the base layer. So, to change the base layer, use setLayerIndex or raiseLayer to set the layer index to 0.

The element that contains the map (or an id for that element). If the OpenLayers.Map constructor is called with two arguments, this should be provided as the first argument. Alternatively, the map constructor can be called with the options object as the only argument. In this case (one argument), a div property may or may not be provided. If the div property is not provided, the map can be rendered to a container later using the render method.

Note: If you calling render after map construction, do not use maxResolution auto. Instead, divide your maxExtent by your maximum expected dimension.


شبكات

Grid — Visibility of latitude and longitude lines 'on' (default) | on/off logical value

Visibility of latitude and longitude lines on the map, specified as 'on' or 'off' , or as numeric or logical 1 ( true ) or 0 ( false ). A value of 'on' is equivalent to true , and 'off' is equivalent to false . Thus, you can use the value of this property as a logical value. The value is stored as an on/off logical value of type matlab.lang.OnOffSwitchState .

'off' – Do not show grid lines.

مثال: gx.Grid = 'off'

GridLineStyle — Line style for grid lines '-' (default) | '--' | ':' | '-.' | 'لا أحد'

Line style for grid lines, specified as one of the line styles in this table.

To display the grid lines, use the grid on command or set the Grid property to 'on' .

مثال: gx.GridLineStyle = '--'

GridColor — Color of grid lines [0.15 0.15 0.15] (default) | RGB triplet | hexadecimal color code | color name | short color name

Background color, specified as an RGB triplet, a hexadecimal color code, a color name, or a short color name.

For a custom color, specify an RGB triplet or a hexadecimal color code.

An RGB triplet is a three-element row vector whose elements specify the intensities of the red, green, and blue components of the color. The intensities must be in the range [0,1] for example, [0.4 0.6 0.7] .

A hexadecimal color code is a character vector or a string scalar that starts with a hash symbol ( # ) followed by three or six hexadecimal digits, which can range from 0 to F . The values are not case sensitive. Thus, the color codes '#FF8800' , '#ff8800' , '#F80' , and '#f80' are equivalent.

Alternatively, you can specify some common colors by name. This table lists the named color options, the equivalent RGB triplets, and hexadecimal color codes.

Here are the RGB triplets and hexadecimal color codes for the default colors MATLAB uses in many types of plots.

For example, create a geographic axis object with red grid lines. Set the GridAlpha property to 0.5 to increase visibility.

مثال: gx.GridColor = [0 0 1]

مثال: gx.GridColor = 'b'

مثال: gx.GridColor = 'blue'

مثال: gx.GridColor = '#0000FF'

GridColorMode — Property for setting grid color 'auto' (default) | 'manual'

Property for setting the grid color, specified as one of these values:

'auto' — Object automatically selects the color.

'manual' — To set the grid line color for all directions, use GridColor .

GridAlpha — Grid-line transparency 0.15 (default) | value in the range [0,1]

Grid-line transparency, specified as a value in the range [0,1] . A value of 1 means opaque and a value of 0 means completely transparent.

مثال: gx.GridAlpha = 0.5

GridAlphaMode — Selection mode for GridAlpha 'auto' (default) | 'manual'

Selection mode for the GridAlpha property, specified as one of these values:

'auto' — Object selects the transparency value.

'manual' — To specify the transparency value, use the GridAlpha property.

مثال: gx.GridAlphaMode = 'auto'


List index out of bounds error

When trying out a proposed solution to my previous question, Displaying multiple names from different objects from a query in VF, while there is no error in the developer console, I am receiving an error when I preview the page. The query without the where portion gets me the data I need (I tested it without the where portion in the query editor), but I believe there is an issue stemming from the أين portion of the query. The controller is:

How do I make the array index in bounds?

I understand what an array out of bounds error is but what I don't get is the line:

Doesn't the query end after the ] bracket? What is the purpose and meaning of the [0].PartsinProducts__r? I think my issue stems from my lack of understanding of this line of code. Is there nothing in the array? I'm quite sure 0 index of an array indicates the first element in that array.

The controller can be seen in the link but I will put it here anyways:

This is the error message I get from the two huge code blocks above:

The query that I run in the query editor and its results:


The only thing you can do with a class SphericalImage is to project an image onto cube faces. The few functions it has to manipulate the stored image are just there to help with the projection. Instead of using a class , perhaps it is better to just have a single function that takes an image, and splits it into six cube faces. It could look like this:

Basically, you give it an ImageBuf , and you get six ImageBuf s back. You can add additional parameters for your algorithm, like threshold , centerWeighted , possibly with default values. Your main() should then be able to look like:

Note that this doesn't mean you have to put all the functionality inside that function, you can still have helper functions. These should then be made static .


How can I get the values returned by an OpenLayers bounds object in Longitude / Latitude format? - نظم المعلومات الجغرافية

Geocoder is a library which helps you build geo-aware applications. It provides an abstraction layer for geocoding manipulations. The library is split in two parts: HttpAdapter and Provider and is really extensible.

HttpAdapters are responsible to get data from remote APIs.

Currently, there are the following adapters:

  • BuzzHttpAdapter to use Buzz, a lightweight PHP 5.3 library for issuing HTTP requests
  • CurlHttpAdapter to use cURL
  • GuzzleHttpAdapter to use Guzzle, PHP 5.3+ HTTP client and framework for building RESTful web service clients
  • SocketHttpAdapter to use a socket
  • ZendHttpAdapter to use Zend Http Client.

الموفرون contain the logic to extract useful information.

Currently, there are many providers for the following APIs:

    as IP-Based geocoding provider as IP-Based geocoding provider as IP-Based geocoding provider (city precision) as Address-Based geocoding and reverse geocoding provider as Address-Based geocoding and reverse geocoding provider as Address-Based geocoding and reverse geocoding provider as Address-Based geocoding and reverse geocoding provider (based on the Nominatim provider) as Address-Based geocoding and reverse geocoding provider as Address-Based geocoding and reverse geocoding provider , the PHP extension, as IP-Based geocoding provider
  • ChainProvider is a special provider that takes a list of providers and iterates over this list to get information as Address-Based geocoding and reverse geocoding provider as very accurate Address-Based geocoding and reverse geocoding provider (exclusively in Denmark) as Address-Based geocoding and reverse geocoding provider (exclusively in USA & Canada) as Address-Based geocoding provider (exclusively in USA) as Address-Based geocoding provider (exclusively in France) as IP-Based geocoding provider or an Address-Based provider (exclusively in USA & Canada) as Address-Based geocoding and reverse geocoding provider as IP-Based geocoding provider as IP-Based geocoding provider as IP-Based geocoding provider (City/ISP/Org and Omni services) as IP-Based geocoding provider as Place-Based geocoding and reverse geocoding provider as IP-Based geocoding provider (very accurate in Russia) as Address-Based geocoding and reverse geocoding provider (exclusively in China) as Address-Based geocoding and reverse geocoding provider as Address-Based geocoding and reverse geocoding provider.

The Geocoder Extra library contains even more providers!

The recommended way to install Geocoder is through composer.

Just create a composer.json file for your project:

Protip: you should browse the willdurand/geocoder page to choose a stable version to use, avoid the @stable meta constraint.

And run these two commands to install it:

Now you can add the autoloader, and you will have access to the library:

If you don't use either Composer أو أ ClassLoader in your application, just require the provided autoloader:

First, you need an adapter to query an API:

The BuzzHttpAdapter is tweakable, actually you can pass a Browser object to this adapter:

Now, you have to choose a provider which is closed to what you want to get.

The FreeGeoIpProvider named free_geo_ip is able to geocode IPv4 and IPv6 addresses فقط.

The HostIpProvider named host_ip is able to geocode IPv4 addresses فقط.

The IpInfoDbProvider named ip_info_db is able to geocode IPv4 addresses فقط. A valid api key is required.

The GoogleMapsProvider named google_maps is able to geocode and reverse geocode street addresses.

The GoogleMapsBusinessProvider named google_maps_business is able to geocode and reverse geocode street addresses. A valid Client ID is required. The private key is optional.

The BingMapsProvider named bing_maps is able to geocode and reverse geocode street addresses. A valid api key is required.

The OpenStreetMapProvider named openstreetmap is able to geocode and reverse geocode street addresses.

تحذير: The OpenStreetMapsProvider is deprecated, and you should rather use the OpenStreetMapProvider . See issue #269.

The NominatimProvider named nominatim is able to geocode and reverse geocode street addresses. Access to a Nominatim server is required. See the Nominatim Wiki Page for more information.

The CloudMadeProvider named cloudmade is able to geocode and reverse geocode street addresses. A valid api key is required.

The GeoipProvider named geoip is able to geocode IPv4 and IPv6 addresses فقط. No need to use an HttpAdapter as it uses a local database. See the MaxMind page for more information.

The ChainProvider named chain is a special provider that takes a list of providers and iterates over this list to get information.

The MapQuestProvider named map_quest is able to geocode and reverse geocode street addresses. A valid api key is required.

The OIORestProvider named oio_rest is able to geocode and reverse geocode street addresses, exclusively in Denmark.

The GeocoderCaProvider named geocoder_ca is able to geocode and reverse geocode street addresses, exclusively in USA & Canada.

The GeocoderUsProvider named geocoder_us is able to geocode street addresses only, exclusively in USA.

The IGNOpenLSProvider named ign_openls is able to geocode street addresses only, exclusively in France. A valid OpenLS api key is required.

The DataScienceToolkitProvider named data_science_toolkit is able to geocode IPv4 addresses و street adresses, exclusively in USA & Canada.

The YandexProvider named yandex is able to geocode and reverse geocode street addresses. The default language-locale is ru-RU , you can choose between uk-UA , be-BY , en-US , en-BR and tr-TR . This provider can also reverse information based on coordinates (latitude, longitude). It's possible to precise the toponym to get more accurate result for reverse geocoding: house , street , metro , district and locality .

The GeoPluginProvider named geo_plugin is able to geocode IPv4 addresses and IPv6 addresses فقط.

The GeoIPsProvider named geo_ips is able to geocode IPv4 addresses فقط. A valid api key is required.

The MaxMindProvider named maxmind is able to geocode IPv4 and IPv6 addresses فقط. A valid City/ISP/Org or Omni service's api key is required. This provider provides two constants CITY_EXTENDED_SERVICE by default and OMNI_SERVICE .

The GeonamesProvider named geonames is able to geocode and reverse geocode places. A valid username is required.

The IpGeoBaseProvider named ip_geo_base is able to geocode IPv4 addresses only, very accurate in Russia.

The BaiduProvider named baidu is able to geocode and reverse geocode street addresses, exclusively in China. A valid api key is required.

The TomTomProvider named tomtom is able to geocode and reverse geocode street addresses. The default langage-locale is en , you can choose between de , es , fr , it , nl , pl , pt and sv . A valid api key is required.

The ArcGISOnlineProvider named arcgis_online is able to geocode and reverse geocode street addresses. It's possible to specify a sourceCountry to restrict result to this specific country thus reducing request time (note that this doesn't work on reverse geocoding). This provider also supports SSL.

You can use one of them or write your own provider. You can also register all providers and decide later. That's we'll do:

  • $locale is available for YandexProvider , BingMapsProvider and TomTomProvider .
  • $region is available for GoogleMapsProvider and GoogleMapsBusinessProvider .
  • $toponym is available for YandexProvider .
  • $service is available for MaxMindProvider .
  • $useSsl is available for GoogleMapsProvider , GoogleMapsBusinessProvider , MaxMindProvider and ArcGISOnlineProvider .
  • $sourceCountry is available for ArcGISOnlineProvider .
  • $rootUrl is available for NominatimProvider .

As said it's a special provider that takes a list of providers and iterates over this list to get information. Note that it توقف its iteration when a provider returns a result. The result is returned by GoogleMapsProvider because FreeGeoIpProvider and HostIpProvider cannot geocode street addresses. BingMapsProvider is ignored.

The main method is called geocode() which receives a value to geocode. It can be an IP address or a street address (partial or not).

The geocode() method returns a Geocoded result object with the following API, this object also implements the ArrayAccess interface:

  • getCoordinates() will return an array with latitude and longitude values
  • getLatitude() will return the latitude value
  • getLongitude() will return the longitude value
  • getBounds() will return an array with south , west , north and east values
  • getStreetNumber() will return the street number/house number value
  • getStreetName() will return the street name value
  • getCity() will return the city
  • getZipcode() will return the zipcode
  • getCityDistrict() will return the city district , or sublocality
  • getCounty() will return the county
  • getCountyCode() will return the county code (county short name)
  • getRegion() will return the region
  • getRegionCode() will return the region code (region short name)
  • getCountry() will return the country
  • getCountryCode() will return the ISO country code
  • getTimezone() will return the timezone .

The Geocoder's API is fluent, you can write:

The using() method allows you to choose the provider to use by its name. When you deal with multiple providers, you may want to choose one of them. The default behavior is to use the first one but it can be annoying.

The limit() method allows you to configure the maximum number of results being returned. Depending on the provider you may not get as many results as expected, it is a maximum limit, not the expected number of results.

This library provides a reverse() method to retrieve information from coordinates:

Geocoder provides dumpers that aim to transform a ResultInterface object in standard formats.

ال GPS eXchange format is designed to share geolocated data like point of interests, tracks, ways, but also coordinates. Geocoder provides a dumper to convert a ResultInterface object in an GPX compliant format.

Assuming we got a $result object as seen previously:

GeoJSON is a format for encoding a variety of geographic data structures.

لغة ترميز ثقب المفتاح (KML)

Keyhole Markup Language is an XML notation for expressing geographic annotation and visualization within Internet-based, two-dimensional maps and three-dimensional Earth browsers.

The Well-Known Binary (WKB) representation for geometric values is defined by the OpenGIS specification.

Well-known text (WKT) is a text markup language for representing vector geometry objects on a map, spatial reference systems of spatial objects and transformations between spatial reference systems.

A common use case is to print geocoded data. Thanks to the Formatter class, it's really easy to format a ResultInterface object as a string:


Visualforce - Apex - Google maps

I have been trying to get something to work with Google maps in combination with Apex and Visualforce pages, but I can't figure out what I'm doing wrong. What I want is to set different icons مع ألوان مختلفة in a Google map. More exactly, I want to modify an existing code that was doing the job but only with two icons, one for current location (Account object), and another icon for accounts around the current location.

If I take a look to the Visualforce page that is part of the Account page layout, which contains the Google maps, I can see this section of the code that takes care of the icons and some other stuff:

So I though, ok, I want to add a different icon to each account base on a value of a custom field (Point of Sales), in the Account object. What I did was to created a custom text field in the Account object, Google_marker_URL__c, to assigned a URL to different icons that are in the Documents object, base on the values in the Point of Sales حقل. This was easy and it works! All I needed was to change the icon: '' to icon:'' . The problem is that is picking up the current account Google_marker_URL__c for all the accounts around, which it is obvious. now :( So my question is, how can I change that? How can I use the icon that it is assigned to the accounts that are around the current account?

I have been trying all day different things but it won't work the way I want. I use four different icons with four different colors. Any ideas on how to change this code to do what I want?


Options:

offset — The position, in the input term, of the last character that the service uses to match predictions. For example, if the input is 'Google' and the offset is 3, the service will match on 'Goo'. The string determined by the offset is matched against the first word in the input term only. For example, if the input term is 'Google abc' and the offset is 3, the service will attempt to match against 'Goo abc'. If no offset is supplied, the service will use the whole term. The offset should generally be set to the position of the text caret.

location — The point around which you wish to retrieve place information. Must be specified as latitude,longitude.

radius — The distance (in meters) within which to return place results. Note that setting a radius biases results to the indicated area, but may not fully restrict results to the specified area. See Location Biasing below.

language — The language code, indicating in which language the results should be returned, if possible. Searches are also biased to the selected language results in the selected language may be given a higher ranking. See the list of supported languages and their codes. Note that we often update supported languages so this list may not be exhaustive. If language is not supplied, the Place Autocomplete service will attempt to use the native language of the domain from which the request is sent.

types — The types of place results to return. See Place Types below. If no type is specified, all types will be returned.

components — A grouping of places to which you would like to restrict your results. Currently, you can use components to filter by country. The country must be passed as a two character, ISO 3166-1 Alpha-2 compatible country code. For example: components=country:fr would restrict your results to places within France.


Visualizing the cluster-reduced spatial data

This interactive CartoDB map shows both the full and reduced data sets as separate layers, along with informational pop-ups when you hover over a point. You can turn each layer on or off and zoom in to see how well the reduced set of points represents the full data set:

Now I can save the final reduced data set to CSV and use it in other applications that need a low-overhead spatial data set to render a visualization quickly and responsively. In particular, you might be interested in this notebook that uses this technique to cluster 1.2 million spatial data points and this post about that project. You can also read the paper here.


شاهد الفيديو: للحصول علي خطوط الطول و دوائر العرض عن طريق جوجل