Earth Engine में बनाए गए एल्गोरिदम, Google क्लाउड में चलते हैं. ये कई कंप्यूटर पर डिस्ट्रिब्यूट किए जाते हैं. डीबग करना मुश्किल हो सकता है, क्योंकि गड़बड़ियां क्लाइंट-साइड कोड या कोड किए गए निर्देशों के सर्वर-साइड पर होने वाली प्रोसेस में हो सकती हैं. साथ ही, ये गड़बड़ियां स्केलिंग की समस्याओं के साथ-साथ सिंटैक्स या लॉजिकल गड़बड़ियों की वजह से भी हो सकती हैं. क्लाउड में चल रहे प्रोग्राम के हिस्सों की जांच तब तक नहीं की जा सकती, जब तक आप उनका अनुरोध न करें. इस दस्तावेज़ में, डीबग करने की रणनीतियों, टूल, और समाधानों के बारे में बताया गया है. इनकी मदद से, आम तौर पर होने वाली गड़बड़ियों को ठीक किया जा सकता है और Earth Engine स्क्रिप्ट को डीबग किया जा सकता है.
सिंटैक्स की गड़बड़ियां
सिंटैक्स की गड़बड़ियां तब होती हैं, जब आपका कोड प्रोग्रामिंग भाषा के नियमों का उल्लंघन करता है. Earth Engine में, ये गड़बड़ियां JavaScript या Python में हो सकती हैं. इन गड़बड़ियों की वजह से, आपका कोड नहीं चल पाता. आम तौर पर, ये गड़बड़ियां कोड के लागू होने से पहले ही पकड़ ली जाती हैं. अगर आपको सिंटैक्स से जुड़ी कोई गड़बड़ी मिलती है, तो हाइलाइट की गई लाइन या गड़बड़ी के मैसेज की ध्यान से समीक्षा करें. साथ ही, Python भाषा के रेफ़रंस या Google JavaScript स्टाइल गाइड जैसे रिसॉर्स देखें. कोड लिंटर से भी इन समस्याओं का पता लगाने और उन्हें ठीक करने में मदद मिल सकती है.
क्लाइंट-साइड गड़बड़ियां
सिंटैक्स के हिसाब से सही कोड होने के बावजूद, स्क्रिप्ट के एक जैसे होने या लॉजिक से जुड़ी गड़बड़ियां हो सकती हैं. यहां दिए गए उदाहरणों में, ऐसे वैरिएबल और तरीके का इस्तेमाल करने से होने वाली गड़बड़ियों के बारे में बताया गया है जो मौजूद नहीं हैं.
गड़बड़ी — यह कोड काम नहीं कर रहा है!
कोड एडिटर (JavaScript)
// Load a Sentinel-2 image. var image = ee.Image('USGS/SRTMGL1_003'); // Error: "bandNames" is not defined in this scope. var display = image.visualize({bands: bandNames, min: 0, max: 9000}); // Error: image.selfAnalyze is not a function var silly = image.selfAnalyze();
import ee import geemap.core as geemap
Colab (Python)
# Load a Sentinel-2 image. image = ee.Image('USGS/SRTMGL1_003') # NameError: name 'band_names' is not defined. display = image.visualize(bands=band_names, min=0, max=9000) # AttributeError: 'Image' object has no attribute 'selfAnalyze'. silly = image.selfAnalyze()
पहली गड़बड़ी से आपको पता चलता है कि bandNames
वैरिएबल को उस दायरे में तय नहीं किया गया है जिसमें उसका रेफ़रंस दिया गया है. इसका समाधान करने के लिए, वैरिएबल सेट करें या bands
पैरामीटर के लिए सूची वाला आर्ग्युमेंट दें. दूसरी गड़बड़ी से पता चलता है कि selfAnalyze()
फ़ंक्शन के मौजूद न होने पर क्या होता है. इमेज पर ऐसा करना,
सही तरीका नहीं है. इसलिए, गड़बड़ी का यह मैसेज दिखता है कि यह कोई फ़ंक्शन नहीं है. दोनों ही मामलों में, गड़बड़ी की जानकारी में समस्या के बारे में बताया गया है.
ऑब्जेक्ट टाइप कास्टिंग की जानकारी नहीं है
"...is not a function
" गड़बड़ी का मतलब यह हो सकता है कि Earth Engine को वैरिएबल का टाइप पता न हो. इस समस्या के आम तौर पर ये कारण होते हैं:
first()
से मिले ऑब्जेक्ट पर कुछ करना (कलेक्शन में मौजूद एलिमेंट का टाइपget()
से मिले ऑब्जेक्ट पर कुछ करना (प्रॉपर्टी में सेव किए गए एलिमेंट का टाइप पता नहीं है).- फ़ंक्शन में, फ़ंक्शन के आर्ग्युमेंट के साथ कुछ ऐसा करना जिसका टाइप पता न हो.
पहले मामले का उदाहरण:
गड़बड़ी — यह कोड काम नहीं कर रहा है!
कोड एडिटर (JavaScript)
var collection = ee.FeatureCollection('USDOS/LSIB_SIMPLE/2017'); // Error: collection.first(...).area is not a function var area = collection.first().area();
import ee import geemap.core as geemap
Colab (Python)
collection = ee.FeatureCollection('USDOS/LSIB_SIMPLE/2017') # AttributeError: 'Element' object has no attribute 'area'. area = collection.first().area()
सभी मामलों में, अज्ञात टाइप के ऑब्जेक्ट को, ज्ञात टाइप के कंस्ट्रक्टर के साथ कास्ट करना ही समाधान है. पिछले उदाहरण को जारी रखते हुए, इसका समाधान यह है कि स्क्रीन को
ee.Feature
पर कास्ट करें:
समाधान — कास्ट का इस्तेमाल करें!
कोड एडिटर (JavaScript)
var area = ee.Feature(collection.first()).area();
import ee import geemap.core as geemap
Colab (Python)
area = ee.Feature(collection.first()).area()
(ध्यान दें कि यहां Element
पर किसी भी तरीके को सुरक्षित तरीके से कॉल किया जा सकता है, क्योंकि Earth Engine के हिसाब से यही सही तरीका है).
क्लाइंट और सर्वर फ़ंक्शन को एक साथ इस्तेमाल करने से बचें
नीचे दिया गया उदाहरण कम साफ़ है:
गड़बड़ी — यह कोड आपकी ज़रूरत के मुताबिक काम नहीं करता
कोड एडिटर (JavaScript)
// Don't mix EE objects and JavaScript objects. var image = ee.Image('USGS/SRTMGL1_003'); var nonsense = image + 2; // You can print this, but it's not what you were hoping for. print(nonsense); // Error: g.eeObject.name is not a function Map.addLayer(nonsense);
import ee import geemap.core as geemap
Colab (Python)
# Don't mix EE objects and Python objects. image = ee.Image('USGS/SRTMGL1_003') nonsense = image + 2 # TypeError: unsupported operand type(s) for +: 'Image' and 'int'. display(nonsense) # TypeError: unsupported operand type(s) for +: 'Image' and 'int'. m = geemap.Map() m.add_layer(nonsense) m
मान लें कि इस कोड के लेखक का मकसद इमेज के हर पिक्सल में 2
जोड़ना था, तो ऐसा करने का यह सही तरीका नहीं है. खास तौर पर, यह कोड क्लाइंट-साइड ऑपरेटर (+
) के साथ,
सर्वर-साइड ऑब्जेक्ट (image
) को गलत तरीके से मिलाता है. इससे आपको आश्चर्यजनक नतीजे मिल सकते हैं. पहले मामले में, JavaScript कोड एडिटर में
nonsense
को प्रिंट करने पर, image
और 2
, दोनों को स्ट्रिंग में बदलकर,
उन्हें जोड़कर, अनुरोध किया गया ऑपरेशन (+
) किया जाएगा. इस वजह से, अनचाही स्ट्रिंग बन जाती है. Python में, TypeError का मैसेज दिखता है.
दूसरे मामले में, मैप में nonsense
जोड़ने पर, JavaScript कोड एडिटर में g.eeObject.name is not a function
गड़बड़ी का मैसेज दिखता है. ऐसा इसलिए होता है, क्योंकि मैप में जोड़ा जा रहा ऑब्जेक्ट, nonsense
एक स्ट्रिंग है, न कि EE ऑब्जेक्ट. Python में, TypeError का मैसेज दिखता है. अनचाहे नतीजों और जानकारी न देने वाली गड़बड़ियों से बचने के लिए, सर्वर ऑब्जेक्ट और फ़ंक्शन को क्लाइंट ऑब्जेक्ट, प्राइमिटिव या फ़ंक्शन के साथ न मिलाएं. इस उदाहरण में, सर्वर फ़ंक्शन का इस्तेमाल करके समस्या हल की गई है.
समाधान — सर्वर फ़ंक्शन का इस्तेमाल करें!
कोड एडिटर (JavaScript)
Map.addLayer(image.add(2));
import ee import geemap.core as geemap
Colab (Python)
m = geemap.Map() m.add_layer(image.add(2)) m
ज़्यादा जानकारी के लिए, क्लाइंट बनाम सर्वर पेज देखें.
JavaScript कोड एडिटर ब्राउज़र लॉक
क्लाइंट में JavaScript को चलने में ज़्यादा समय लगने या Earth Engine से किसी चीज़ का इंतज़ार करने पर, ब्राउज़र फ़्रीज़ या लॉक हो सकता है. इस गड़बड़ी के दो सामान्य सोर्स हैं:
आपके JavaScript कोड एडिटर के कोड में, for-लूप और/या getInfo()
. सबसे खराब स्थिति में, getInfo()
को for-लूप के अंदर इस्तेमाल किया जा सकता है. For-लूप की वजह से, ब्राउज़र लॉक हो सकता है, क्योंकि कोड आपकी मशीन पर चलता है. दूसरी ओर,
getInfo()
, Earth Engine से गणना के नतीजे का अनुरोध सिंक्रोनस तरीके से करता है. साथ ही, नतीजा मिलने तक ब्लॉक करता है. अगर कैलकुलेशन में ज़्यादा समय लगता है, तो हो सकता है कि ब्लॉक करने की वजह से आपका ब्राउज़र लॉक हो जाए. कोड एडिटर में काम करते समय, for-लूप और getInfo()
, दोनों का इस्तेमाल करने से बचें. ज़्यादा जानकारी के लिए,
क्लाइंट बनाम सर्वर पेज देखें.
सर्वर-साइड गड़बड़ियां
क्लाइंट कोड में लॉजिकल कंसिस्टेंसी होने के बावजूद, ऐसे बग हो सकते हैं जो सिर्फ़ सर्वर पर रन टाइम के दौरान दिखते हैं. इस उदाहरण से पता चलता है कि ऐसा बैंड पाने पर क्या होता है जो मौजूद नहीं है.
गड़बड़ी — यह कोड काम नहीं कर रहा है!
कोड एडिटर (JavaScript)
// Load a Sentinel-2 image. var s2image = ee.Image( 'COPERNICUS/S2_HARMONIZED/20160625T100617_20160625T170310_T33UVR'); // Error: Image.select: Pattern 'nonBand' did not match any bands. print(s2image.select(['nonBand']));
import ee import geemap.core as geemap
Colab (Python)
# Load a Sentinel-2 image. s2image = ee.Image( 'COPERNICUS/S2_HARMONIZED/20160625T100617_20160625T170310_T33UVR' ) # EEException: Image.select: Band pattern 'non_band' did not match any bands. print(s2image.select(['non_band']).getInfo())
इस उदाहरण में, गड़बड़ी की जानकारी से पता चलता है कि nonBand
नाम का कोई बैंड नहीं है. इस समस्या को हल करने का सबसे आसान तरीका यह है कि बैंड का ऐसा नाम डालें जो मौजूद हो. इमेज को प्रिंट करके और Console में उसकी जांच करके, बैंड के नामों का पता लगाया जा सकता है. इसके अलावा, image.bandNames()
से मिली बैंड के नामों की सूची को प्रिंट करके भी, बैंड के नामों का पता लगाया जा सकता है.
इम्यूटेबल
Earth Engine में बनाए गए सर्वर साइड ऑब्जेक्ट,
immutable. (कोई भी
ee.Object
, सर्वर साइड Object
होता है). इसका मतलब है कि अगर आपको ऑब्जेक्ट में बदलाव करना है, तो आपको बदली गई स्थिति को नए वैरिएबल में सेव करना होगा. उदाहरण के लिए, यह Sentinel-2 इमेज पर प्रॉपर्टी सेट करने के लिए काम नहीं करेगा:
गड़बड़ी — यह कोड आपकी ज़रूरत के मुताबिक काम नहीं करता!
कोड एडिटर (JavaScript)
var s2image = ee.Image( 'COPERNICUS/S2_HARMONIZED/20160625T100617_20160625T170310_T33UVR'); s2image.set('myProperty', 'This image is not assigned to a variable'); // This will not result in an error, but will not find 'myProperty'. print(s2image.get('myProperty')); // null
import ee import geemap.core as geemap
Colab (Python)
s2image = ee.Image( 'COPERNICUS/S2_HARMONIZED/20160625T100617_20160625T170310_T33UVR' ) s2image.set('my_property', 'This image is not assigned to a variable') # This will not result in an error, but will not find 'my_property'. display(s2image.get('my_property')) # None
इस उदाहरण में, s2image.set()
नई प्रॉपर्टी के साथ इमेज की कॉपी दिखाता है, लेकिन s2image
वैरिएबल में सेव की गई इमेज में कोई बदलाव नहीं होता. आपको s2image.set()
से मिली इमेज को किसी नए वैरिएबल में सेव करना होगा. उदाहरण के लिए:
समाधान — नतीजे को वैरिएबल में कैप्चर करें!
कोड एडिटर (JavaScript)
s2image = s2image.set('myProperty', 'OK'); print(s2image.get('myProperty')); // OK
import ee import geemap.core as geemap
Colab (Python)
s2image = s2image.set('my_property', 'OK') display(s2image.get('my_property')) # OK
मैप किए गए फ़ंक्शन
मैप किए गए फ़ंक्शन में भी क्लाइंट और सर्वर फ़ंक्शन एक साथ काम नहीं करते. खास तौर पर, मैप किए गए फ़ंक्शन से तय किए गए ऑपरेशन, क्लाउड में चलते हैं. इसलिए, getInfo
और Export
जैसे क्लाइंट फ़ंक्शन (साथ ही, JavaScript कोड एडिटर में Map
और Chart
पर print
और तरीका) मैप किए गए फ़ंक्शन में काम नहीं करेंगे. उदाहरण के लिए:
गड़बड़ी — यह कोड काम नहीं कर रहा है!
कोड एडिटर (JavaScript)
var collection = ee.ImageCollection('MODIS/006/MOD44B'); // Error: A mapped function's arguments cannot be used in client-side operations var badMap3 = collection.map(function(image) { print(image); return image; });
import ee import geemap.core as geemap
Colab (Python)
collection = ee.ImageCollection('MODIS/006/MOD44B') # Error: A mapped function's arguments cannot be used in client-side operations. bad_map_3 = collection.map(lambda image: print(image.getInfo()))
यह गड़बड़ी, Earth Engine की उस प्रोसेस की वजह से होती है जिसका इस्तेमाल करके, इस कोड को निर्देशों के ऐसे सेट में बदला जाता है जिसे Google के सर्वर पर चलाया जा सकता है. मैप किए गए फ़ंक्शन में दी गई आर्ग्युमेंट इमेज पर काम करने के लिए, क्लाइंट-साइड फ़ंक्शन और कंट्रोल स्ट्रक्चर का इस्तेमाल नहीं किया जा सकता. इस गड़बड़ी से बचने के लिए, मैप किए गए फ़ंक्शन में क्लाइंट-साइड फ़ंक्शन का इस्तेमाल न करें. क्लाइंट और सर्वर फ़ंक्शन के बीच के अंतर के बारे में ज़्यादा जानने के लिए, क्लाइंट बनाम सर्वर पेज देखें.
मैप किए गए फ़ंक्शन के लिए कुछ और ज़रूरी शर्तें होती हैं. उदाहरण के लिए, मैप किए गए फ़ंक्शन को कुछ रिटर्न करना चाहिए:
गड़बड़ी — यह कोड काम नहीं कर रहा है!
कोड एडिटर (JavaScript)
var collection = ee.ImageCollection('MODIS/006/MOD44B'); // Error: User-defined methods must return a value. var badMap1 = collection.map(function(image) { // Do nothing. });
import ee import geemap.core as geemap
Colab (Python)
collection = ee.ImageCollection('MODIS/006/MOD44B') # Error: User-defined methods must return a value. bad_map_1 = collection.map(lambda image: None)
समस्या को हल करने का सबसे आसान तरीका यह है कि आप आइटम लौटा दें. हालांकि, यह किसी भी तरह की जानकारी नहीं दिखा सकता. खास तौर पर, ImageCollection
या
FeatureCollection
पर मैप किए गए फ़ंक्शन को Image
या
Feature
दिखाना चाहिए. उदाहरण के लिए, ImageCollection
पर मैप किए गए फ़ंक्शन से तारीख नहीं दिखाई जा सकती:
गड़बड़ी — यह कोड काम नहीं कर रहा है!
कोड एडिटर (JavaScript)
var collection = ee.ImageCollection('MODIS/006/MOD44B'); var badMap2 = collection.map(function(image) { return image.date(); }); // Error: Collection.map: A mapped algorithm must return a Feature or Image. print(badMap2);
import ee import geemap.core as geemap
Colab (Python)
collection = ee.ImageCollection('MODIS/006/MOD44B') bad_map_2 = collection.map(lambda image: image.date()) # EEException: Collection.map: # A mapped algorithm must return a Feature or Image. print(bad_map_2.getInfo())
इससे बचने के लिए, इनपुट इमेज को नए प्रॉपर्टी सेट के साथ दिखाएं. इसके बाद, अगर आपको कलेक्शन में मौजूद इमेज की तारीखों की सूची चाहिए, तो aggregate_array()
का इस्तेमाल करें:
समाधान — कोई प्रॉपर्टी सेट करें!
कोड एडिटर (JavaScript)
var collection = ee.ImageCollection('MODIS/006/MOD44B'); var okMap2 = collection.map(function(image) { return image.set('date', image.date()); }); print(okMap2); // Get a list of the dates. var datesList = okMap2.aggregate_array('date'); print(datesList);
import ee import geemap.core as geemap
Colab (Python)
collection = ee.ImageCollection('MODIS/006/MOD44B') ok_map_2 = collection.map(lambda image: image.set('date', image.date())) print(ok_map_2.getInfo()) # Get a list of the dates. dates_list = ok_map_2.aggregate_array('date') print(dates_list.getInfo())
प्रोसेस से जुड़ी गड़बड़ियां
पैटर्न को बिना बैंड वाली इमेज पर लागू किया गया था
"Pattern 'my_band' was applied to an Image with no bands"
गड़बड़ी का मतलब है कि बैंड की खाली सूची वाली इमेज के लिए ee.Image.select()
कॉल है. इस समस्या को ठीक करने के लिए, यह तरीका अपनाएं:
- अगर इमेज को किसी ImageCollection से रिड्यूसर की मदद से या
first()
याtoBands()
कॉल का इस्तेमाल करके बनाया गया है, तो पक्का करें कि सोर्स कलेक्शन खाली न हो. - अगर इमेज को
ee.Dictionary().toImage()
का इस्तेमाल करके किसी डिक्शनरी से बनाया गया है, तो पक्का करें कि डिक्शनरी खाली न हो. - अगर इमेज स्टैंडअलोन है, तो पक्का करें कि उसमें डेटा हो (और सिर्फ़
ee.Image(0)
न हो).
स्केलिंग से जुड़ी गड़बड़ियां
हो सकता है कि कोई स्क्रिप्ट व्याकरण के हिसाब से सही हो, उसमें लॉजिकल गड़बड़ियां न हों, और वह सर्वर के लिए निर्देशों का मान्य सेट दिखाती हो. हालांकि, कैलकुलेशन को पैरलल और लागू करने पर, हो सकता है कि नतीजे वाले ऑब्जेक्ट बहुत बड़े हों, बहुत ज़्यादा हों या उन्हें कैलकुलेट करने में काफ़ी समय लगे. ऐसे में, आपको गड़बड़ी का एक मैसेज मिलेगा. इसमें बताया जाएगा कि एल्गोरिदम को स्केल नहीं किया जा सकता. आम तौर पर, इन गड़बड़ियों का पता लगाना और उन्हें ठीक करना सबसे मुश्किल होता है. इस तरह की गड़बड़ी के उदाहरणों में ये शामिल हैं:
- कैलकुलेशन का समय खत्म हो गया
- एक साथ बहुत ज़्यादा एग्रीगेशन
- उपयोगकर्ता के लिए मेमोरी की सीमा पार हो गई है
- आंतरिक गड़बड़ी हुई है.
अपने कोड को स्केल करने की सुविधा को बेहतर बनाने से, आपको तेज़ी से नतीजे मिलेंगे. साथ ही, सभी उपयोगकर्ताओं के लिए कंप्यूटिंग संसाधनों की उपलब्धता भी बेहतर होगी. हर तरह की गड़बड़ी के बारे में, यहां दिए गए सेक्शन में बताया गया है. इसके बाद, reduceRegion()
के बारे में थोड़ी जानकारी दी गई है. यह एक आम तौर पर इस्तेमाल किया जाने वाला फ़ंक्शन है, जो स्केलिंग से जुड़ी हर तरह की गड़बड़ी का कारण बन सकता है.
reduceRegion()
reduceRegion()
, कई तरह की गड़बड़ियां ट्रिगर करने के लिए, ज़रूरत से ज़्यादा पिक्सल का इस्तेमाल करता है. हालांकि, गिनती को कंट्रोल करने के लिए पैरामीटर भी होते हैं, ताकि गड़बड़ियों को ठीक किया जा सके. उदाहरण के लिए, यहां दिए गए उदाहरण में, बिड घटाने का सुझाव नहीं दिया गया है:
गड़बड़ी — यह कोड काम नहीं कर रहा है!
कोड एडिटर (JavaScript)
var absurdComputation = ee.Image(1).reduceRegion({ reducer: 'count', geometry: ee.Geometry.Rectangle([-180, -90, 180, 90], null, false), scale: 100, }); // Error: Image.reduceRegion: Too many pixels in the region. // Found 80300348117, but only 10000000 allowed. print(absurdComputation);
import ee import geemap.core as geemap
Colab (Python)
absurd_computation = ee.Image(1).reduceRegion( reducer='count', geometry=ee.Geometry.Rectangle([-180, -90, 180, 90], None, False), scale=100, ) # EEException: Image.reduceRegion: Too many pixels in the region. # Found 80300348117, but only 10000000 allowed. print(absurd_computation.getInfo())
यह उदाहरण सिर्फ़ डेमो के लिए दिया गया है. इस गड़बड़ी का मकसद आपसे पूछना है कि क्या आपको 80300348117 (यानी 80 बिलियन) पिक्सल को वाकई कम करना है. अगर ऐसा नहीं है, तो scale
(पिक्सल का साइज़ मीटर में) को बढ़ाएं या
बड़े स्केल को अपने-आप फिर से कैलकुलेट करने के लिए, bestEffort
को 'सही' पर सेट करें. इन पैरामीटर के बारे में ज़्यादा जानकारी के लिए,
reduceRegion()
पेज देखें.
कैलकुलेशन का समय खत्म हो गया
मान लें कि आपको अपने हिसाब लगाने के लिए उन सभी पिक्सल की ज़रूरत है. अगर ऐसा है, तो कैलकुलेशन पूरा करने के लिए,
maxPixels
पैरामीटर को बढ़ाया जा सकता है. हालांकि, कैलकुलेशन पूरा होने में Earth Engine को कुछ समय लगेगा. इस वजह से, "गणना पूरी होने में ज़्यादा समय लगा" वाली गड़बड़ी का मैसेज दिख सकता है:
गलत — ऐसा न करें!
कोड एडिटर (JavaScript)
var ridiculousComputation = ee.Image(1).reduceRegion({ reducer: 'count', geometry: ee.Geometry.Rectangle([-180, -90, 180, 90], null, false), scale: 100, maxPixels: 1e11 }); // Error: Computation timed out. print(ridiculousComputation);
import ee import geemap.core as geemap
Colab (Python)
ridiculous_computation = ee.Image(1).reduceRegion( reducer='count', geometry=ee.Geometry.Rectangle([-180, -90, 180, 90], None, False), scale=100, maxPixels=int(1e11), ) # Error: Computation timed out. print(ridiculous_computation.getInfo())
इस गड़बड़ी का मतलब है कि Earth Engine ने कंप्यूटेशन को रोकने से पहले, करीब पांच मिनट इंतज़ार किया. एक्सपोर्ट करने की सुविधा की मदद से, Earth Engine किसी ऐसे एनवायरमेंट में कंप्यूटेशन कर सकता है जिसमें प्रोसेस को ज़्यादा समय तक चलाया जा सकता है. हालांकि, इसमें ज़्यादा मेमोरी का इस्तेमाल नहीं किया जा सकता. reduceRegion()
से मिलने वाली वैल्यू एक डिक्शनरी होती है. इसलिए, डिक्शनरी का इस्तेमाल करके, किसी ऐसी सुविधा की प्रॉपर्टी सेट की जा सकती है जिसकी ज्यामिति शून्य है:
अच्छा — Export
का इस्तेमाल करें!
कोड एडिटर (JavaScript)
Export.table.toDrive({ collection: ee.FeatureCollection([ ee.Feature(null, ridiculousComputation) ]), description: 'ridiculousComputation', fileFormat: 'CSV' });
import ee import geemap.core as geemap
Colab (Python)
task = ee.batch.Export.table.toDrive( collection=ee.FeatureCollection([ee.Feature(None, ridiculous_computation)]), description='ridiculous_computation', fileFormat='CSV', ) # task.start()
एक साथ बहुत ज़्यादा एग्रीगेशन
इस गड़बड़ी के "एग्रीगेशन" हिस्से का मतलब उन कार्रवाइयों से है जो कई मशीनों पर की जाती हैं. जैसे, एक से ज़्यादा टाइल में होने वाली गड़बड़ियां. Earth Engine में ऐसी कई प्रोसेस एक साथ चलने से रोकने के लिए सीमाएं तय की गई हैं. इस उदाहरण में, मैप में डेटा की संख्या कम होने की वजह से, "एक साथ कई एग्रीगेशन" गड़बड़ी ट्रिगर होती है:
गलत — ऐसा न करें!
कोड एडिटर (JavaScript)
var collection = ee.ImageCollection('LANDSAT/LT05/C02/T1') .filterBounds(ee.Geometry.Point([-123, 43])); var terribleAggregations = collection.map(function(image) { return image.set(image.reduceRegion({ reducer: 'mean', geometry: image.geometry(), scale: 30, maxPixels: 1e9 })); }); // Error: Quota exceeded: Too many concurrent aggregations. print(terribleAggregations);
import ee import geemap.core as geemap
Colab (Python)
collection = ee.ImageCollection('LANDSAT/LT05/C02/T1').filterBounds( ee.Geometry.Point([-123, 43]) ) def apply_mean_aggregation(image): return image.set( image.reduceRegion( reducer='mean', geometry=image.geometry(), scale=30, maxPixels=int(1e9), ) ) terrible_aggregations = collection.map(apply_mean_aggregation) # EEException: Computation timed out. print(terrible_aggregations.getInfo())
मान लें कि इस कोड का मकसद हर इमेज के लिए इमेज के आंकड़े पाना है, तो एक संभावित समाधान यह है कि नतीजे को Export
करें. उदाहरण के लिए, इस बात का इस्तेमाल करके कि ImageCollection
भी FeatureCollection
है, इमेज से जुड़े मेटाडेटा को टेबल के तौर पर एक्सपोर्ट किया जा सकता है:
अच्छा — Export
का इस्तेमाल करें!
कोड एडिटर (JavaScript)
Export.table.toDrive({ collection: terribleAggregations, description: 'terribleAggregations', fileFormat: 'CSV' });
import ee import geemap.core as geemap
Colab (Python)
task = ee.batch.Export.table.toDrive( collection=terrible_aggregations, description='terrible_aggregations', fileFormat='CSV', ) # task.start()
उपयोगकर्ता के लिए मेमोरी की सीमा पार हो गई है
Earth Engine में आपके एल्गोरिदम को एक साथ चलाने का एक तरीका यह है कि इनपुट को टाइल में बांटकर, हर टाइल पर एक ही कैलकुलेशन को अलग-अलग चलाया जाए. इसके बाद, उन नतीजों को जोड़ें. इसलिए, आउटपुट टाइल का हिसाब लगाने के लिए ज़रूरी सभी इनपुट, स्मृति में होने चाहिए. उदाहरण के लिए, अगर इनपुट कई बैंड वाली इमेज है, तो कैलकुलेशन में सभी बैंड का इस्तेमाल करने पर, बहुत ज़्यादा मेमोरी का इस्तेमाल हो सकता है. उदाहरण के लिए, इस इमेज में पूरे इमेज कलेक्शन को टाइल में दिखाने के लिए, बहुत ज़्यादा स्टोरेज का इस्तेमाल किया गया है. ऐसा करना ज़रूरी नहीं है:
गलत — ऐसा न करें!
कोड एडिटर (JavaScript)
var bands = ['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7']; var memoryHog = ee.ImageCollection('LANDSAT/LT05/C02/T1').select(bands) .toArray() .arrayReduce(ee.Reducer.mean(), [0]) .arrayProject([1]) .arrayFlatten([bands]) .reduceRegion({ reducer: 'mean', geometry: ee.Geometry.Point([-122.27, 37.87]).buffer(1000), scale: 1, bestEffort: true, }); // Error: User memory limit exceeded. print(memoryHog);
import ee import geemap.core as geemap
Colab (Python)
bands = ['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7'] memory_hog = ( ee.ImageCollection('LANDSAT/LT05/C02/T1') .select(bands) .toArray() .arrayReduce(ee.Reducer.mean(), [0]) .arrayProject([1]) .arrayFlatten([bands]) .reduceRegion( reducer=ee.Reducer.mean(), geometry=ee.Geometry.Point([-122.27, 37.87]).buffer(1000), scale=1, bestEffort=True, ) ) # EEException: User memory limit exceeded. print(memory_hog.getInfo())
इस बहुत खराब कोड से पता चलता है कि जब तक ज़रूरत न हो, तब तक ऐरे का इस्तेमाल न करें. इसके बारे में ज़्यादा जानने के लिए, 'आवश्यकता न होने पर टाइप बदलने से बचें' सेक्शन देखें. जब उस कलेक्शन को एक बड़े ऐरे में बदला जाता है, तो ऐरे को एक साथ मेमोरी में लोड करना पड़ता है. यह इमेज की लंबी सीरीज़ है, इसलिए ऐरे बड़ा है और यह स्मृति में नहीं फ़िट होगा.
इस समस्या को हल करने का एक तरीका यह है कि tileScale
पैरामीटर की वैल्यू को ज़्यादा पर सेट करें. tileScale की ज़्यादा वैल्यू से टाइल,
tileScale^2
गुना छोटी हो जाती हैं. उदाहरण के लिए, नीचे दिए गए फ़ॉर्मूले से कैलकुलेशन की प्रोसेस पूरी हो जाती है:
कोड एडिटर (JavaScript)
var bands = ['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7']; var smallerHog = ee.ImageCollection('LANDSAT/LT05/C02/T1').select(bands) .toArray() .arrayReduce(ee.Reducer.mean(), [0]) .arrayProject([1]) .arrayFlatten([bands]) .reduceRegion({ reducer: 'mean', geometry: ee.Geometry.Point([-122.27, 37.87]).buffer(1000), scale: 1, bestEffort: true, tileScale: 16 }); print(smallerHog);
import ee import geemap.core as geemap
Colab (Python)
bands = ['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7'] smaller_hog = ( ee.ImageCollection('LANDSAT/LT05/C02/T1') .select(bands) .toArray() .arrayReduce(ee.Reducer.mean(), [0]) .arrayProject([1]) .arrayFlatten([bands]) .reduceRegion( reducer=ee.Reducer.mean(), geometry=ee.Geometry.Point([-122.27, 37.87]).buffer(1000), scale=1, bestEffort=True, tileScale=16, ) ) print(smaller_hog.getInfo())
हालांकि, ज़्यादातर मामलों में अरे का इस्तेमाल ज़रूरी नहीं होता. इसलिए, आपको tileScale
के साथ परेशान होने की ज़रूरत नहीं है:
अच्छा — ऐरे का इस्तेमाल न करें!
कोड एडिटर (JavaScript)
var bands = ['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7']; var okMemory = ee.ImageCollection('LANDSAT/LT05/C02/T1').select(bands) .mean() .reduceRegion({ reducer: 'mean', geometry: ee.Geometry.Point([-122.27, 37.87]).buffer(1000), scale: 1, bestEffort: true, }); print(okMemory);
import ee import geemap.core as geemap
Colab (Python)
bands = ['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7'] ok_memory = ( ee.ImageCollection('LANDSAT/LT05/C02/T1') .select(bands) .mean() .reduceRegion( reducer=ee.Reducer.mean(), geometry=ee.Geometry.Point([-122.27, 37.87]).buffer(1000), scale=1, bestEffort=True, ) ) print(ok_memory.getInfo())
जब तक किसी मेमोरी गड़बड़ी को ठीक करने के लिए ज़रूरी न हो, तब तक आपको tileScale
को सेट नहीं करना चाहिए.
इसकी वजह यह है कि छोटी टाइल से भी पैरलल प्रोसेसिंग में ज़्यादा ओवरहेड होता है.
अंदरूनी गड़बड़ियां
आपको इस तरह की गड़बड़ी दिख सकती है:
अगर आपको यह गड़बड़ी दिखती है, तो JavaScript कोड एडिटर कंसोल में दिखने वाले "गड़बड़ी की शिकायत करें" लिंक पर क्लिक करें. सहायता बटन से भी सुझाव, शिकायत या राय भेजी जा सकती है. यह गड़बड़ी, आपकी स्क्रिप्ट में लॉजिकल गड़बड़ियों की वजह से हो सकती है, जो सिर्फ़ रनटाइम पर दिखती हैं. इसके अलावा, यह Earth Engine के काम करने के तरीके से जुड़ी समस्या की वजह से भी हो सकती है. दोनों ही मामलों में, गड़बड़ी की जानकारी नहीं मिलती. इसलिए, इसकी शिकायत की जानी चाहिए, ताकि इसे ठीक किया जा सके.
अंदरूनी गड़बड़ियों में request
आईडी शामिल होता है, जैसे कि:
ये स्ट्रिंग, यूनीक आइडेंटिफ़ायर के तौर पर काम करती हैं. इससे Earth Engine टीम को खास समस्याओं की पहचान करने में मदद मिलती है. गड़बड़ी की रिपोर्ट में यह स्ट्रिंग शामिल करें.
डीबग करने के तरीके
आपने अपने विश्लेषण को कोड में बदला, उसे चलाया, और आपको गड़बड़ी का मैसेज मिला. अब क्या करें? इस सेक्शन में, समस्या को अलग करने और उसे ठीक करने के लिए, डीबग करने की सामान्य तकनीकों के बारे में बताया गया है.
वैरिएबल और मैप लेयर की जांच करना
मान लें कि आपके पास बहुत मुश्किल विश्लेषण है, जिससे गड़बड़ी होती है. अगर यह साफ़ तौर पर नहीं पता चल रहा है कि गड़बड़ी कहां से शुरू हुई है, तो शुरुआत में एक अच्छी रणनीति यह है कि इंटरमीडिएट ऑब्जेक्ट को प्रिंट या विज़ुअलाइज़ करें. साथ ही, उनकी जांच करके यह पक्का करें कि ऑब्जेक्ट का स्ट्रक्चर, आपकी स्क्रिप्ट के लॉजिक के मुताबिक है या नहीं. खास तौर पर, कोड एडिटर या geemap इंस्पेक्टर टूल की मदद से, मैप में जोड़ी गई लेयर की पिक्सल वैल्यू की जांच की जा सकती है. अगर आपको कुछ प्रिंट करना है, तो प्रॉपर्टी को बड़ा करने के लिए, ज़िपी (▶) का इस्तेमाल करें. इन बातों की जांच करना न भूलें:
- बैंड के नाम. क्या इमेज बैंड के नाम आपके कोड से मेल खाते हैं?
- पिक्सल वैल्यू. क्या आपके डेटा में सही रेंज है? क्या इसे सही तरीके से मास्क किया गया है?
- शून्य. क्या कोई वैल्यू शून्य है, जो शून्य नहीं होनी चाहिए?
- साइज़. क्या साइज़ शून्य है, जबकि ऐसा नहीं होना चाहिए?
aside()
विश्लेषण के हर चरण को वैरिएबल में डालना मुश्किल हो सकता है, ताकि इसे प्रिंट किया जा सके और उसकी जांच की जा सके. फ़ंक्शन कॉल की लंबी चेन से इंटरमीडिएट वैल्यू प्रिंट करने के लिए, aside()
तरीके का इस्तेमाल किया जा सकता है. उदाहरण के लिए:
कोड एडिटर (JavaScript)
var image = ee.Image(ee.ImageCollection('COPERNICUS/S2') .filterBounds(ee.Geometry.Point([-12.29, 168.83])) .aside(print) .filterDate('2011-01-01', '2016-12-31') .first());
import ee import geemap.core as geemap
Colab (Python)
image = ee.Image( ee.ImageCollection('COPERNICUS/S2_HARMONIZED') .filterBounds(ee.Geometry.Point([-12.29, 168.83])) .aside(display) .filterDate('2011-01-01', '2016-12-31') .first() )
बस याद रखें कि aside(print)
(JavaScript कोड एडिटर) और
aside(display)
(Python geemap), क्लाइंट साइड फ़ंक्शन को कॉल कर रहे हैं. इसके बावजूद, यह मैप किए गए फ़ंक्शन में काम नहीं करेगा. उपयोगकर्ता के तय किए गए फ़ंक्शन के साथ भी, aside का इस्तेमाल किया जा सकता है. उदाहरण के लिए:
कोड एडिटर (JavaScript)
var composite = ee.ImageCollection('LANDSAT/LC08/C02/T1_TOA') .filterBounds(ee.Geometry.Point([106.91, 47.91])) .map(function(image) { return image.addBands(image.normalizedDifference(['B5', 'B4'])); }) .aside(Map.addLayer, {bands: ['B4', 'B3', 'B2'], max: 0.3}, 'collection') .qualityMosaic('nd'); Map.setCenter(106.91, 47.91, 11); Map.addLayer(composite, {bands: ['B4', 'B3', 'B2'], max: 0.3}, 'composite');
import ee import geemap.core as geemap
Colab (Python)
m = geemap.Map() m.set_center(106.91, 47.91, 11) composite = ( ee.ImageCollection('LANDSAT/LC08/C02/T1_TOA') .filterBounds(ee.Geometry.Point([106.91, 47.91])) .map(lambda image: image.addBands(image.normalizedDifference(['B5', 'B4']))) .aside(m.add_layer, {'bands': ['B4', 'B3', 'B2'], 'max': 0.3}, 'collection') .qualityMosaic('nd') ) m.add_layer(composite, {'bands': ['B4', 'B3', 'B2'], 'max': 0.3}, 'composite') m
first()
पर कोई फ़ंक्शन चलाना
उपलब्ध होने पर, प्रिंट करने और विज़ुअलाइज़ करने की सुविधा, डीबग करने के लिए काम की होती है. हालांकि, किसी कलेक्शन पर मैप किए गए फ़ंक्शन को डीबग करते समय, फ़ंक्शन को प्रिंट नहीं किया जा सकता. इस बारे में मैप किए गए फ़ंक्शन सेक्शन में बताया गया है. इस मामले में, कलेक्शन में समस्या वाले एलिमेंट को अलग करना और किसी एक एलिमेंट पर मैप किए गए फ़ंक्शन की जांच करना मददगार होता है. फ़ंक्शन को मैप किए बिना उसकी जांच करते समय, समस्या को समझने के लिए प्रिंट स्टेटमेंट का इस्तेमाल किया जा सकता है. नीचे दिया गया उदाहरण देखें.
गड़बड़ी — यह कोड काम नहीं कर रहा है!
कोड एडिटर (JavaScript)
var image = ee.Image( 'COPERNICUS/S2_HARMONIZED/20150821T111616_20160314T094808_T30UWU'); var someFeatures = ee.FeatureCollection([ ee.Feature(ee.Geometry.Point([-2.02, 48.43])), ee.Feature(ee.Geometry.Point([-2.80, 48.37])), ee.Feature(ee.Geometry.Point([-1.22, 48.29])), ee.Feature(ee.Geometry.Point([-1.73, 48.65])), ]); var problem = someFeatures.map(function(feature) { var dictionary = image.reduceRegion({ reducer: 'first', geometry: feature.geometry(), scale: 10, }); return feature.set({ result: ee.Number(dictionary.get('B5')) .divide(dictionary.get('B4')) }); }); // Error in map(ID=2): // Number.divide: Parameter 'left' is required. print(problem);
import ee import geemap.core as geemap
Colab (Python)
image = ee.Image( 'COPERNICUS/S2_HARMONIZED/20150821T111616_20160314T094808_T30UWU' ) some_features = ee.FeatureCollection([ ee.Feature(ee.Geometry.Point([-2.02, 48.43])), ee.Feature(ee.Geometry.Point([-2.80, 48.37])), ee.Feature(ee.Geometry.Point([-1.22, 48.29])), ee.Feature(ee.Geometry.Point([-1.73, 48.65])), ]) # Define a function to be mapped over the collection. def function_to_map(feature): dictionary = image.reduceRegion( reducer=ee.Reducer.first(), geometry=feature.geometry(), scale=10 ) return feature.set( {'result': ee.Number(dictionary.get('B5')).divide(dictionary.get('B4'))} ) problem = some_features.map(function_to_map) # EEException: Error in map(ID=2): # Number.divide: Parameter 'left' is required. print(problem.getInfo())
इसे डीबग करने के लिए, गड़बड़ी की जांच करना ज़रूरी है. गड़बड़ी का यह मैसेज, आपको ID=2
की सुविधा में आ रही समस्या के बारे में बताता है. ज़्यादा जानकारी पाने के लिए, कोड को थोड़ा रीफ़ैक्टर करना मददगार होता है. खास तौर पर, जब फ़ंक्शन को किसी कलेक्शन पर मैप किया गया हो, तो उसमें प्रिंट स्टेटमेंट नहीं हो सकते. इस बारे में इस सेक्शन में बताया गया है. डीबग करने का मकसद, समस्या वाली सुविधा को अलग करना और उसमें कुछ प्रिंट स्टेटमेंट के साथ फ़ंक्शन को चलाना है. पहले इस्तेमाल की गई इमेज और सुविधाओं के साथ:
कोड एडिटर (JavaScript)
// Define a function to be mapped over the collection. var functionToMap = function(feature) { var dictionary = image.reduceRegion({ reducer: 'first', geometry: feature.geometry(), scale: 10, }); // Debug: print(dictionary); return feature.set({ result: ee.Number(dictionary.get('B5')) .divide(dictionary.get('B4')) }); }; // Isolate the feature that's creating problems. var badFeature = ee.Feature(someFeatures .filter(ee.Filter.eq('system:index', '2')) .first()); // Test the function with print statements added. functionToMap(badFeature); // Inspect the bad feature in relation to the image. Map.centerObject(badFeature, 11); Map.addLayer(badFeature, {}, 'bad feature'); Map.addLayer(image, {bands: ['B4', 'B3', 'B2'], max: 3000}, 'image');
import ee import geemap.core as geemap
Colab (Python)
# Define a function to be mapped over the collection. def function_to_map(feature): dictionary = image.reduceRegion( reducer=ee.Reducer.first(), geometry=feature.geometry(), scale=10 ) # Debug: display(dictionary) return feature.set( {'result': ee.Number(dictionary.get('B5')).divide(dictionary.get('B4'))} ) # Isolate the feature that's creating problems. bad_feature = ee.Feature( some_features.filter(ee.Filter.eq('system:index', '2')).first() ) # Test the function with print statements added. function_to_map(bad_feature) # Inspect the bad feature in relation to the image. m = geemap.Map() m.center_object(bad_feature, 11) m.add_layer(bad_feature, {}, 'bad feature') m.add_layer(image, {'bands': ['B4', 'B3', 'B2'], 'max': 3000}, 'image') m
अब, फ़ंक्शन सिर्फ़ एक सुविधा पर चलता है, इसलिए इसके अंदर एक प्रिंट (`display` for
Python geemap) कॉल डाला जा सकता है. प्रिंट किए गए ऑब्जेक्ट की जांच करके पता लगाएं कि reduceRegion()
से मिले ऑब्जेक्ट में हर बैंड के लिए वैल्यू null है. इससे यह पता चलता है कि डिवीज़न क्यों काम नहीं कर रहा है: शून्य को शून्य से नहीं बांटा जा सकता. यह पहले से ही शून्य क्यों है?
जांच करने के लिए, मैप में इनपुट इमेज और खराब फ़ीचर जोड़ें. इसके बाद, खराब फ़ीचर को केंद्र में रखें. ऐसा करने पर, आपको पता चलता है कि समस्या इस वजह से है कि बिंदु, इमेज के दायरे से बाहर है. इस खोज के आधार पर, डीबग किया गया कोड यह है:
कोड एडिटर (JavaScript)
var functionToMap = function(feature) { var dictionary = image.reduceRegion({ reducer: 'first', geometry: feature.geometry(), scale: 10, }); return feature.set({ result: ee.Number(dictionary.get('B5')) .divide(dictionary.get('B4')) }); }; var noProblem = someFeatures .filterBounds(image.geometry()) .map(functionToMap); print(noProblem);
import ee import geemap.core as geemap
Colab (Python)
def function_to_map(feature): dictionary = image.reduceRegion( reducer=ee.Reducer.first(), geometry=feature.geometry(), scale=10 ) return feature.set( {'result': ee.Number(dictionary.get('B5')).divide(dictionary.get('B4'))} ) no_problem = some_features.filterBounds(image.geometry()).map(function_to_map) display(no_problem)
प्रोफ़ाइलर
प्रोफ़ाइलर, चालू होने के दौरान किए गए कैलकुलेशन की वजह से, ईईसीयू-टाइम और हर एल्गोरिदम और एसेट के हिसाब से मेमोरी के इस्तेमाल की जानकारी देता है. सबसे ज़्यादा रिसॉर्स खर्च करने वाले ऑपरेशन के बारे में जानकारी पाने के लिए, प्रोफ़ाइलर में सबसे ऊपर मौजूद एंट्री देखें. लंबे समय तक चलने वाली या काम की न होने वाली स्क्रिप्ट के लिए, प्रोफ़ाइलर में सबसे ऊपर मौजूद एंट्री से यह पता चलता है कि स्क्रिप्ट को ऑप्टिमाइज़ करने के लिए किन चीज़ों पर ध्यान देना है. अहम जानकारी: प्रोफ़ाइलर, स्क्रिप्ट की परफ़ॉर्मेंस पर असर डालता है. इसलिए, आपको इसे सिर्फ़ ज़रूरत पड़ने पर चलाना चाहिए.