Hata ayıklama kılavuzu

Earth Engine'da oluşturduğunuz algoritmalar, Google bulutunda çalışır ve birçok bilgisayara dağıtılır. Hatalar istemci tarafındaki kodda veya kodlanmış talimatların sunucu tarafında yürütülmesinde ortaya çıkabileceğinden ve hem ölçeklendirme sorunlarından hem de söz dizimi veya mantık hatalarından kaynaklanabileceğinden hata ayıklama zor olabilir. İstemediğiniz sürece programın bulutta çalışan parçaları incelenemez. Bu dokümanda, sık karşılaşılan hataları gidermenize ve Earth Engine komut dosyalarında hata ayıklamanıza yardımcı olacak hata ayıklama stratejileri, araçları ve çözümleri sunulmaktadır.

Söz dizimi hataları

Söz dizimi hataları, kodunuz programlama dilinin kurallarını (Earth Engine'da JavaScript veya Python) ihlal ettiğinde ortaya çıkar. Bu hatalar, kodunuzun çalışmasını engeller ve genellikle yürütmeden önce yakalanır. Söz dizimi hatasıyla karşılaşırsanız vurgulanan satırı veya hata mesajını dikkatlice inceleyin ve Python Dil Referansı veya Google JavaScript Stil Kılavuzu gibi kaynaklara bakın. Kod temizleyiciler de bu sorunları tespit edip düzeltmenize yardımcı olabilir.

İstemci tarafı hataları

Söz dizimi açısından doğru kod olmasına rağmen komut dosyasının tutarlılığı veya mantığıyla ilgili hatalar olabilir. Aşağıdaki örneklerde, var olmayan bir değişkenin ve yöntemin kullanılmasından kaynaklanan hatalar gösterilmektedir.

Hata: Bu kod çalışmıyor.

Kod Düzenleyici (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();

Python kurulumu

Python API'si ve etkileşimli geliştirme için geemap kullanımı hakkında bilgi edinmek üzere Python Ortamı sayfasına bakın.

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()

İlk hata, bandNames değişkeninin atıfta bulunulduğu kapsamda tanımlanmadığını bildirir. Çözüm olarak, değişkeni ayarlayın veya bands parametresi için bir liste bağımsız değişkeni sağlayın. İkinci hata, var olmayan selfAnalyze() işlevi çağrıldığında ne olacağını gösterir. Bu, resimlerde gerçek bir yöntem olmadığından hata, bunun bir işlev olmadığını belirtir. Her iki durumda da hata, sorunu açıklayıcı niteliktedir.

Bilinmeyen nesne türü dönüştürme

"...is not a function" hatası, Earth Engine'ın bir değişkenin türünü bilmemesinden kaynaklanabilir. Bu sorunun yaygın belirtileri şunlardır:

  • first() tarafından döndürülen bir nesneyle ilgili bir işlem yapma (koleksiyondaki öğelerin türü bilinmiyor).
  • get() tarafından döndürülen bir nesneyle ilgili bir işlem yapma (bir mülkte depolanan öğenin türü bilinmiyor).
  • Bağımsız değişkenin türü bilinmediği halde işlev bağımsız değişkeninde (işlevde) bir işlem yapma

İlkine örnek olarak şunları verebiliriz:

Hata: Bu kod çalışmıyor.

Kod Düzenleyici (JavaScript)

var collection = ee.FeatureCollection('USDOS/LSIB_SIMPLE/2017');

// Error: collection.first(...).area is not a function
var area = collection.first().area();

Python kurulumu

Python API'si ve etkileşimli geliştirme için geemap kullanımı hakkında bilgi edinmek üzere Python Ortamı sayfasına bakın.

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()

Tüm durumlarda çözüm, bilinmeyen türdeki nesneyi bilinen türün kurucusuyla yayınlamaktır. Önceki örneğe devam edersek çözüm, ee.Feature'e yayınlamaktır:

Çözüm: Yayın cihazı kullanın.

Kod Düzenleyici (JavaScript)

var area = ee.Feature(collection.first()).area();

Python kurulumu

Python API'si ve etkileşimli geliştirme için geemap kullanımı hakkında bilgi edinmek üzere Python Ortamı sayfasına bakın.

import ee
import geemap.core as geemap

Colab (Python)

area = ee.Feature(collection.first()).area()

(Earth Engine'ın Element olarak düşündüğü için burada Element üzerinde herhangi bir yöntemi güvenle çağırabileceğinizi belirtmek isteriz).

İstemci ve sunucu işlevlerini karıştırmayın

Aşağıdaki örnekte ise bu durum daha az belirgindir:

Hata: Bu kod istediğiniz işlemi yapmıyor

Kod Düzenleyici (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);

Python kurulumu

Python API'si ve etkileşimli geliştirme için geemap kullanımı hakkında bilgi edinmek üzere Python Ortamı sayfasına bakın.

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

Bu kodun yazarının, resimdeki her piksele 2 eklemek istediğini varsayalım. Bu, bunu yapmanın doğru yolu değildir. Daha açık belirtmek gerekirse bu kod, sunucu taraflı bir nesneyi (image) istemci taraflı bir operatörle (+) yanlış bir şekilde karıştırır. Sonuçlar şaşırtıcı olabilir. İlk durumda, JavaScript Kod Düzenleyici'de nonsense yazdırıldığında, hem image hem de 2 dizelere dönüştürülerek ve ardından birleştirilerek istenen işlem (+) gerçekleştirilir. Elde edilen dize istenmeyen bir dizedir (Python'da TypeError atılır). İkinci durumda, haritaya nonsense eklendiğinde, haritaya eklenen nesne (nonsense) bir EE nesnesi değil, bir dize olduğundan JavaScript Kod Düzenleyici'de anlaşılması zor g.eeObject.name is not a function hatası görüntülenir (Python'da TypeError atılır). İstenmeyen sonuçları ve bilgilendirici olmayan hataları önlemek için sunucu nesnelerini ve işlevlerini istemci nesneleri, primitifler veya işlevlerle karıştırmayın. Bu örnekte, sunucu işlevi kullanmak çözümdür.

Çözüm: Sunucu işlevi kullanın.

Kod Düzenleyici (JavaScript)

Map.addLayer(image.add(2));

Python kurulumu

Python API'si ve etkileşimli geliştirme için geemap kullanımı hakkında bilgi edinmek üzere Python Ortamı sayfasına bakın.

import ee
import geemap.core as geemap

Colab (Python)

m = geemap.Map()
m.add_layer(image.add(2))
m

Daha fazla bilgi için İstemci ve sunucu sayfasına bakın.

JavaScript Kod Düzenleyici tarayıcı kilidi

Tarayıcı, istemcide JavaScript'in çalışması çok uzun sürdüğünde veya Earth Engine'dan bir şey beklenirken donabilir ya da kilitlenebilir. Bu hatanın en yaygın iki kaynağı, JavaScript Code Editor kodunuzdaki for döngüleri ve/veya getInfo()'dir. En kötü durum senaryosu ise for döngüsü içinde getInfo() olmasıdır. For döngüleri, kod makinenizde çalıştığı için tarayıcının kilitlenmesine neden olabilir. Öte yandan, getInfo() bir hesaplamanın sonucunu Earth Engine'dan senkronize olarak ister ve sonuç alınana kadar engelleme yapar. Hesaplama uzun sürerse engelleme, tarayıcınızın kilitlenmesine yol açabilir. Kod Düzenleyici'de çalışırken hem for döngülerinden hem de getInfo() while ifadelerinden kaçının. Daha fazla bilgi için İstemci ve sunucu sayfasına bakın.

Sunucu tarafı hataları

İstemci kodunda mantıksal tutarlılık olmasına rağmen, yalnızca sunucudaki çalışma zamanında ortaya çıkan hatalar olabilir. Aşağıdaki örnekte, var olmayan bir bant elde etmeye çalışırken ne olduğu gösterilmektedir.

Hata: Bu kod çalışmıyor.

Kod Düzenleyici (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']));

Python kurulumu

Python API'si ve etkileşimli geliştirme için geemap kullanımı hakkında bilgi edinmek üzere Python Ortamı sayfasına bakın.

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())

Bu örnekte hata, nonBand adlı bir bant olmadığını bildirir. Bunun için en bariz çözüm, mevcut bir grup adı belirtmektir. Resmi yazdırıp konsolda inceleyerek veya image.bandNames() tarafından döndürülen grup adlarının listesini yazdırarak grup adlarını öğrenebilirsiniz.

Değişmezlik

Earth Engine'da oluşturduğunuz sunucu tarafı nesneler immutable. (Her ee.Object, sunucu tarafı bir Object'dır). Yani, nesnede değişiklik yapmak isterseniz değişen durumu yeni bir değişkene kaydetmeniz gerekir. Örneğin, Sentinel-2 resminde bir özellik ayarlamak için aşağıdaki yöntem işe yaramaz:

Hata: Bu kod istediğiniz işlemi yapmıyor.

Kod Düzenleyici (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

Python kurulumu

Python API'si ve etkileşimli geliştirme için geemap kullanımı hakkında bilgi edinmek üzere Python Ortamı sayfasına bakın.

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

Bu örnekte s2image.set(), resmin yeni mülkle birlikte bir kopyasını döndürür ancak s2image değişkeninde depolanan resimde değişiklik olmaz. s2image.set() tarafından döndürülen resmi yeni bir değişkene kaydetmeniz gerekir. Örneğin:

Çözüm: Sonucu bir değişkende yakalayabilirsiniz.

Kod Düzenleyici (JavaScript)

s2image = s2image.set('myProperty', 'OK');
print(s2image.get('myProperty')); // OK

Python kurulumu

Python API'si ve etkileşimli geliştirme için geemap kullanımı hakkında bilgi edinmek üzere Python Ortamı sayfasına bakın.

import ee
import geemap.core as geemap

Colab (Python)

s2image = s2image.set('my_property', 'OK')
display(s2image.get('my_property'))  # OK

Eşlenen işlevler

İstemci ve sunucu işlevlerinin birlikte kullanılamadığı bir diğer bağlam da eşlenen işlevlerdir. Daha açık belirtmek gerekirse, eşlenen işlev tarafından belirtilen işlemler bulutta yürütülür. Bu nedenle, getInfo ve Export gibi istemci işlevleri (ve JavaScript Kod Düzenleyici'deki Map ve Chart üzerinde print ve yöntem) eşlenen işlevlerde çalışmaz. Örneğin:

Hata: Bu kod çalışmıyor.

Kod Düzenleyici (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;
});

Python kurulumu

Python API'si ve etkileşimli geliştirme için geemap kullanımı hakkında bilgi edinmek üzere Python Ortamı sayfasına bakın.

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'ın bu kodu Google sunucularında çalıştırılabilir bir talimat dizisine dönüştürmek için kullandığı işlemden kaynaklanan bu hata biraz gizemlidir. İstemci tarafı işlevler ve denetim yapıları, eşlenen işleve iletilen bağımsız değişken resmi üzerinde işlem yapmak için kullanılamaz. Bu hatayı önlemek için eşlenen işlevlerde istemci tarafı işlevler kullanmaktan kaçının. İstemci ve sunucu işlevleri arasındaki fark hakkında daha fazla bilgi edinmek için İstemci ve sunucu sayfasına bakın.

Eşlenen işlevler için ek koşullar vardır. Örneğin, eşlenen işlevler bir değer döndürmelidir:

Hata: Bu kod çalışmıyor.

Kod Düzenleyici (JavaScript)

var collection = ee.ImageCollection('MODIS/006/MOD44B');

// Error: User-defined methods must return a value.
var badMap1 = collection.map(function(image) {
  // Do nothing.
});

Python kurulumu

Python API'si ve etkileşimli geliştirme için geemap kullanımı hakkında bilgi edinmek üzere Python Ortamı sayfasına bakın.

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)

Bunun çözümü, ürünü iade etmek olabilir. Ancak her tür öğeyi döndüremez. Özellikle, ImageCollection veya FeatureCollection üzerinde eşlenen işlevler Image veya Feature döndürmelidir. Örneğin, ImageCollection ile eşlenen bir işlevden tarih döndüremezsiniz:

Hata: Bu kod çalışmıyor.

Kod Düzenleyici (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);

Python kurulumu

Python API'si ve etkileşimli geliştirme için geemap kullanımı hakkında bilgi edinmek üzere Python Ortamı sayfasına bakın.

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())

Bunu önlemek için giriş resmini yeni bir özellik kümesiyle döndürün. Ardından, koleksiyondaki resimlerin tarihlerinin listesine ihtiyacınız varsa aggregate_array() ifadesini kullanabilirsiniz:

Çözüm: Mülk ayarlayın.

Kod Düzenleyici (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);

Python kurulumu

Python API'si ve etkileşimli geliştirme için geemap kullanımı hakkında bilgi edinmek üzere Python Ortamı sayfasına bakın.

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())

Prosedür hataları

Desen, bant içermeyen bir resme uygulandı

"Pattern 'my_band' was applied to an Image with no bands" hatası, boş bir bant listesi olan bir resim için ee.Image.select() çağrısı yapıldığı anlamına gelir. Bu sorunu gidermek için şunları yapabilirsiniz:

  • Resim, bir azaltıcı içeren bir ImageCollection'dan veya first() ya da toBands() çağrıları kullanılarak üretiliyorsa kaynak koleksiyonun boş olmadığından emin olun.
  • Resim, ee.Dictionary().toImage() kullanılarak bir sözlükten oluşturuluyorsa sözlüğün boş olmadığından emin olun.
  • Resim bağımsızsa veri içerdiğinden (yalnızca ee.Image(0) olmadığından) emin olun.

Ölçeklendirme hataları

Bir komut dosyası söz dizimsel olarak doğru, mantıksal hata içermiyor ve sunucu için geçerli bir talimat grubunu temsil ediyor olsa da hesaplamanın paralelleştirilmesi ve yürütülmesi sonucunda ortaya çıkan nesneler çok büyük, çok sayıda olabilir veya hesaplamanın yapılması çok uzun sürebilir. Bu durumda, algoritmanın ölçeklendirilemediğini belirten bir hata alırsınız. Bu hatalar genellikle teşhis edilmesi ve çözülmesi en zor olanlardır. Bu tür hatalara örnek olarak aşağıdakiler verilebilir:

  • Hesaplama zaman aşımına uğradı
  • Çok fazla eşzamanlı toplama
  • Kullanıcı bellek sınırı aşıldı
  • Bir dahili hata oluştu

Kodunuzun ölçeklendirmesini iyileştirmek, sonuçları daha hızlı almanıza olanak tanır ve tüm kullanıcılar için bilgi işlem kaynaklarının kullanılabilirliğini artırır. Her tür hata, her ölçeklendirme hatasına neden olabilmesiyle kötü bir üne sahip olan ve yaygın olarak kullanılan reduceRegion() işlevi hakkında kısa bir açıklamanın ardından aşağıdaki bölümlerde ele alınmaktadır.

reduceRegion()

reduceRegion(), heyecan verici bir dizi hatayı tetikleyecek kadar pikseli açgözlü bir şekilde tüketse de hataları aşmanıza olanak tanıyan, hesaplamayı kontrol etmeyi amaçlayan parametreler de vardır. Örneğin, aşağıdaki önerilmeyen azaltmayı düşünün:

Hata: Bu kod çalışmıyor.

Kod Düzenleyici (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);

Python kurulumu

Python API'si ve etkileşimli geliştirme için geemap kullanımı hakkında bilgi edinmek üzere Python Ortamı sayfasına bakın.

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())

Bu saçma örnek yalnızca gösterim amaçlıdır. Bu hatanın amacı, 80300348117 (80 milyar) pikseli gerçekten azaltmak isteyip istemediğinizi sormaktır. Aksi takdirde, scale'ü (metre cinsinden piksel boyutu) buna göre artırın veya daha büyük bir ölçeği otomatik olarak yeniden hesaplamak için bestEffort'ü true olarak ayarlayın. Bu parametrelerle ilgili daha fazla bilgi için reduceRegion() sayfasına bakın.

Hesaplama zaman aşımına uğradı

Hesabınızda bu piksellerin tümüne ihtiyacınız olduğunu varsayalım. Bu durumda, hesaplamanın başarılı olması için maxPixels parametresini artırabilirsiniz. Ancak Earth Engine'ın hesaplamayı tamamlaması biraz zaman alacaktır. Sonuç olarak, "hesaplama zaman aşımına uğradı" hatası oluşabilir:

Kötü: Bu tür içerikler paylaşmayın.

Kod Düzenleyici (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);

Python kurulumu

Python API'si ve etkileşimli geliştirme için geemap kullanımı hakkında bilgi edinmek üzere Python Ortamı sayfasına bakın.

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())

Bu hata, Earth Engine'ın hesaplamayı durdurmadan önce yaklaşık beş dakika beklediği anlamına gelir. Dışa aktarma, Earth Engine'ın hesaplamayı daha uzun izin verilen çalışma sürelerine sahip bir ortamda gerçekleştirmesine olanak tanır (ancak daha fazla bellek kullanmaz). reduceRegion() işlevinin döndürdüğü değer bir sözlük olduğundan, boş geometriye sahip bir özelliğin özelliklerini ayarlamak için sözlüğü kullanabilirsiniz:

İyi. Export kullanabilirsiniz.

Kod Düzenleyici (JavaScript)

Export.table.toDrive({
  collection: ee.FeatureCollection([
    ee.Feature(null, ridiculousComputation)
  ]),
  description: 'ridiculousComputation',
  fileFormat: 'CSV'
});

Python kurulumu

Python API'si ve etkileşimli geliştirme için geemap kullanımı hakkında bilgi edinmek üzere Python Ortamı sayfasına bakın.

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()

Çok fazla eşzamanlı toplama

Bu hatanın "toplamalar" kısmı, birden fazla makineye yayılmış işlemleri (birden fazla karoyu kapsayan azaltmalar gibi) ifade eder. Earth Engine, bu tür çok fazla toplama işleminin aynı anda çalıştırılmasını önlemek için sınırlar uygular. Bu örnekte, "Çok fazla eşzamanlı toplama" hatası bir haritadaki bir azaltma nedeniyle tetikleniyor:

Kötü: Bu tür içerikler paylaşmayın.

Kod Düzenleyici (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);

Python kurulumu

Python API'si ve etkileşimli geliştirme için geemap kullanımı hakkında bilgi edinmek üzere Python Ortamı sayfasına bakın.

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())

Bu kodun amacının her bir resim için resim istatistikleri elde etmek olduğunu varsayarsak olası çözümlerden biri sonucu Export olarak ayarlamaktır. Örneğin, bir ImageCollection'ün aynı zamanda FeatureCollection olduğunu kullanarak resimlerle ilişkili meta veriler tablo olarak dışa aktarılabilir:

İyi. Export kullanabilirsiniz.

Kod Düzenleyici (JavaScript)

Export.table.toDrive({
  collection: terribleAggregations,
  description: 'terribleAggregations',
  fileFormat: 'CSV'
});

Python kurulumu

Python API'si ve etkileşimli geliştirme için geemap kullanımı hakkında bilgi edinmek üzere Python Ortamı sayfasına bakın.

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()

Kullanıcı bellek sınırı aşıldı

Algoritmalarınızın Earth Engine'da paralelleştirilmesinin bir yolu, girişleri karolara bölmek, aynı hesaplamayı her karoda ayrı ayrı çalıştırmak ve ardından sonuçları birleştirmektir. Sonuç olarak, bir çıkış karosunu hesaplamak için gerekli tüm girişlerin belleğe sığması gerekir. Örneğin, giriş çok bantlı bir resim olduğunda, hesaplamada tüm bantlar kullanılırsa çok fazla bellek kullanılmış olabilir. Bu örnekte, bir resim koleksiyonunun tamamını (gereksiz yere) bir karoya zorlamak suretiyle çok fazla bellek kullanıldığı gösterilmektedir:

Kötü: Bu tür içerikler paylaşmayın.

Kod Düzenleyici (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);

Python kurulumu

Python API'si ve etkileşimli geliştirme için geemap kullanımı hakkında bilgi edinmek üzere Python Ortamı sayfasına bakın.

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())

Bu çok kötü kod, gerçekten ihtiyacınız olmadığı sürece dizi kullanmamanın nedenlerinden birini göstermektedir (Ayrıca "Türü gereksiz yere dönüştürmekten kaçının" bölümüne bakın). Bu koleksiyon dev bir diziye dönüştürüldüğünde, dizinin bir kerede belleğe yüklenmesi gerekir. Uzun bir zaman serisi olduğundan dizi büyüktür ve belleğe sığmaz.

Olası çözümlerden biri, tileScale parametresini daha yüksek bir değere ayarlamaktır. Daha yüksek tileScale değerleri, karoların tileScale^2 faktörü kadar daha küçük olmasına neden olur. Örneğin, aşağıdakiler hesaplamanın başarılı olmasına olanak tanır:

Kod Düzenleyici (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);

Python kurulumu

Python API'si ve etkileşimli geliştirme için geemap kullanımı hakkında bilgi edinmek üzere Python Ortamı sayfasına bakın.

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())

Ancak en çok tercih edilen çözüm, dizileri gereksiz yere kullanmamaktır. Böylece tileScale ile hiç uğraşmanız gerekmez:

İyi: Dizilerden kaçının.

Kod Düzenleyici (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);

Python kurulumu

Python API'si ve etkileşimli geliştirme için geemap kullanımı hakkında bilgi edinmek üzere Python Ortamı sayfasına bakın.

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())

Bir bellek hatasını çözmek için gerekli olmadığı sürece tileScale değerini ayarlamamalısınız. Çünkü daha küçük karolar da paralelleştirme yükü artırır.

Dahili hatalar

Aşağıdaki gibi bir hatayla karşılaşabilirsiniz:

Bu hatayı alırsanız JavaScript Kod Düzenleyici konsolunda görünen "Hatayı bildir" bağlantısını tıklayın. Yardım düğmesinden de Geri bildirim gönder'i tıklayarak geri bildirim gönderebilirsiniz. Bu hata, komut dosyanızda yalnızca çalışma zamanında ortaya çıkan mantıksal hatalardan veya Earth Engine'ın işleyişiyle ilgili bir sorundan kaynaklanabilir. Her iki durumda da hata bilgilendirici değildir ve düzeltilebilmesi için bildirilmelidir.

Dahili hatalar, aşağıdaki gibi bir request kimliği içerir:

Bu dizeler, Earth Engine ekibinin belirli sorunları tespit etmesine yardımcı olan benzersiz tanımlayıcılar olarak işlev görür. Bu dizeyi hata raporlarına ekleyin.

Hata ayıklama yöntemleri

Analizinizi kodlayıp çalıştırdığınızda hata aldınız. Şimdi önemli olan nedir? Bu bölümde, sorunu tespit edip düzeltmek için genel hata ayıklama teknikleri açıklanmaktadır.

Değişkenleri ve harita katmanlarını inceleme

Hata veren çok karmaşık bir analiziniz olduğunu varsayalım. Hatanın kaynağı net değilse iyi bir başlangıç stratejisi, ara nesneleri yazdırmak veya görselleştirmek ve nesnenin yapısının komut dosyanızdaki mantıkla tutarlı olduğundan emin olmak için bunları incelemektir. Daha açık belirtmek gerekirse, haritaya eklenen katmanların piksel değerlerini Kod Düzenleyici veya geemap denetleyici araçlarıyla inceleyebilirsiniz. Bir öğeyi yazdırırsanız özelliklerini açma düğmesini (▶) kullanarak genişlettiğinizden emin olun. Kontrol edilmesi gereken bazı noktalar şunlardır:

  • Bant adları. Resim bandı adları kodunuzla eşleşiyor mu?
  • Piksel değerleri. Verileriniz doğru aralığa sahip mi? Doğru şekilde maskelenmiş mi?
  • Boş. Olmaması gereken bir şey null mi?
  • Bedenler. Beden sıfır olarak ayarlanmışsa

aside()

Bir analizdeki her ara adımı, basılıp incelenebilmesi için bir değişkene koymak zahmetli olabilir. Uzun bir işlev çağrısı zincirindeki ara değerleri yazdırmak için aside() yöntemini kullanabilirsiniz. Örneğin:

Kod Düzenleyici (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());

Python kurulumu

Python API'si ve etkileşimli geliştirme için geemap kullanımı hakkında bilgi edinmek üzere Python Ortamı sayfasına bakın.

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 Kod Düzenleyici) ve aside(display) (Python geemap) istemci tarafı işlevleri çağırdığını ve eşlenen işlevlerde yine de başarısız olacağını unutmayın. aside işlevini kullanıcı tanımlı işlevlerle de kullanabilirsiniz. Örneğin:

Kod Düzenleyici (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');

Python kurulumu

Python API'si ve etkileşimli geliştirme için geemap kullanımı hakkında bilgi edinmek üzere Python Ortamı sayfasına bakın.

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()'te işlev çalıştırma

Yazdırma ve görselleştirme, mümkün olduğunda hata ayıklama için yararlıdır ancak bir koleksiyona eşlenen bir işlevde hata ayıklama yaparken eşlenen işlevler bölümünde açıklandığı gibi işlevde yazdıma yapamazsınız. Bu durumda, koleksiyondaki sorunlu öğeleri ayırmak ve eşlenen işlevi tek bir öğede test etmek faydalı olacaktır. İşlevi eşlemeden test ederken sorunu anlamak için yazdırma ifadelerini kullanabilirsiniz. Aşağıdaki örneği inceleyin.

Hata: Bu kod çalışmıyor.

Kod Düzenleyici (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);

Python kurulumu

Python API'si ve etkileşimli geliştirme için geemap kullanımı hakkında bilgi edinmek üzere Python Ortamı sayfasına bakın.

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())

Bu hatayı gidermek için hatayı incelemeniz gerekir. Neyse ki bu faydalı hata mesajı, ID=2 ile ilgili bir sorun olduğunu size bildirir. Daha ayrıntılı bir inceleme yapmak için kodu biraz yeniden yapılandırmak faydalı olacaktır. Daha açık belirtmek gerekirse, bu bölümde açıklandığı gibi, bir koleksiyonla eşlendiğinde işlevde print ifadeleri bulunamaz. Hata ayıklamanın amacı, sorunlu özelliği tespit etmek ve işlevi bazı yazdırma ifadeleriyle birlikte çalıştırmaktır. Önceden kullanılan resim ve özelliklerle:

Kod Düzenleyici (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');

Python kurulumu

Python API'si ve etkileşimli geliştirme için geemap kullanımı hakkında bilgi edinmek üzere Python Ortamı sayfasına bakın.

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

Artık işlev yalnızca bir özellikte çalıştırıldığı için içine bir print ("display" for Python geemap) çağrısı koyabilirsiniz. reduceRegion() tarafından döndürülen nesnenin her bant için null değerine sahip olduğunu keşfetmek amacıyla basılı nesneyi inceleyin. Bölme işleminin neden başarısız olduğu bu şekilde açıklanabilir: null değerini null değerine bölemezsiniz. Neden baştan null? İncelemek için giriş resmini ve hatalı özelliği haritaya ekleyin ve hatalı özelliği merkeze alın. Bu sırada, sorunun noktanın görüntünün sınırları dışında olmasından kaynaklandığını keşfedersiniz. Bu keşfe göre hata ayıklanmış kod şu şekildedir:

Kod Düzenleyici (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);

Python kurulumu

Python API'si ve etkileşimli geliştirme için geemap kullanımı hakkında bilgi edinmek üzere Python Ortamı sayfasına bakın.

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)

Profiler

Profilleyici, etkinken yapılan hesaplamadan kaynaklanan EECU süresi ve bellek kullanımı (algoritma ve öğe başına) hakkında bilgi sağlar. En fazla kaynak kullanan işlemler hakkında bilgi edinmek için profilleyicinin üst kısmındaki girişleri arayın. Uzun süre çalışan veya verimsiz komut dosyalarında, profiler'ın üst kısmındaki girişler, komut dosyasını optimize etmek için çabaların nereye odaklanacağı hakkında ipuçları sağlar. Önemli not: Profilleyicinin kendisi komut dosyasının performansını etkiler. Bu nedenle, yalnızca gerektiğinde çalıştırmanız gerekir.