<jupyter_start><jupyter_text>**Bienvenidos!** Este *colab notebook* es parte del curso [**Introduccion a Google Earth Engine con Python**](https://github.com/csaybar/EarthEngineMasterGIS) desarrollado por el equipo [**MasterGIS**](https://www.mastergis.com/). Obten mas informacion del curso en este [**enlace**](https://www.mastergis.com/product/google-earth-engine/). El contenido del curso esta disponible en [**GitHub**](https://github.com/csaybar/EarthEngineMasterGIS) bajo licencia [**MIT**](https://opensource.org/licenses/MIT).  **MASTERGIS: Exploracion de metadatos I** **ee.Image y ImageCollection**En esta lectura, aprenderemos sobre:- Condicionales en ee.Image.- Como obtener metadatos en ee.Image.- Como obtener metadatos en ee.ImageCollection.  **1) Autenticar y inicializar GEE**<jupyter_code>#@title Credenciales Google Earth Engine
import os 
credential = '{"refresh_token":"<PASSWORD>"}'
credential_file_path = os.path.expanduser("~/.config/earthengine/")
os.makedirs(credential_file_path,exist_ok=True)
with open(credential_file_path + 'credentials', 'w') as file:
    file.write(credential)
import ee
ee.Initialize()<jupyter_output><empty_output><jupyter_text>**2) Carga nuestra funcion de mapeo**<jupyter_code>#@title mapdisplay: Crea mapas interactivos usando folium
import folium
def mapdisplay(center, dicc, Tiles="OpensTreetMap",zoom_start=10):
    '''
    :param center: Center of the map (Latitude and Longitude).
    :param dicc: Earth Engine Geometries or Tiles dictionary
    :param Tiles: Mapbox Bright,Mapbox Control Room,Stamen Terrain,Stamen Toner,stamenwatercolor,cartodbpositron.
    :zoom_start: Initial zoom level for the map.
    :return: A folium.Map object.
    '''
    center = center[::-1]
    mapViz = folium.Map(location=center,tiles=Tiles, zoom_start=zoom_start)
    for k,v in dicc.items():
      if ee.image.Image in [type(x) for x in v.values()]:
        folium.TileLayer(
            tiles = v["tile_fetcher"].url_format,
            attr  = 'Google Earth Engine',
            overlay =True,
            name  = k
          ).add_to(mapViz)
      else:
        folium.GeoJson(
        data = v,
        name = k
          ).add_to(mapViz)
    mapViz.add_child(folium.LayerControl())
    return mapViz<jupyter_output><empty_output><jupyter_text>**3) Analisis multicriterio en Google Earth Engine** Para realizar comparaciones por pixel entre imagenes, utilice **operadores relacionales**. Para extraer las zonas urbanizadas de una imagen, este ejemplo utiliza **operadores relacionales** para los indices espectrales, combinando los umbrales con And(): _ | _ | GEE--------------|-------------|-------------Arithmetic	|+ - * / % **	|add, subtract, multiply, divide, mod, expComparison	| == !=  = |	eq, neq, lt, gt, lte,gte.Logical |	&& \|\| ! ^	| And, Or, Not, Xor<jupyter_code># Cargar imagen (en esta caso Landsat8-California)
image = ee.Image('LANDSAT/LC08/C01/T1_TOA/LC08_044034_20140318')

# Crear NDVI y NDWI
ndvi = image.normalizedDifference(['B5', 'B4'])
ndwi = image.normalizedDifference(['B5', 'B6'])

# Crear una imagen binaria usando operadores logicos.
bare = ndvi.lt(0.2).And(ndwi.lt(0))

#Enmascarar los valores no deseados
bare = bare.updateMask(bare)
BareId = bare.getMapId()

tiles = {"Bare": BareId}
center = [-122.3578, 37.7726]
mapdisplay(center, tiles, "Stamen Terrain")<jupyter_output><empty_output><jupyter_text>Como se ilustra en el ejemplo anterior, el resultado de los operadores relacionales y booleanos es verdadero (1) o falso (0). Para enmascarar los 0, se puede enmascarar la imagen binaria resultante con ella misma. Las imagenes binarias devueltas por los operadores relacionales y booleanos se pueden utilizar con operadores matematicos. Este ejemplo crea zonas de urbanizacion en una imagen de luces nocturnas usando **operadores relacionales** y la el metodo image.add():<jupyter_code># Cargar imagen de luces noturnas promedio del 2012.
nl2012 = ee.Image('NOAA/DMSP-OLS/NIGHTTIME_LIGHTS/F182012')
lights = nl2012.select('stable_lights')

# Defina umbrales arbitrarios en la banda de luces estables de 6 bits.
zones = lights.gt(30).add(lights.gt(55)).add(lights.gt(62))

# Muestre la imagen clasificada como tres zonas distintas cerca de Paris.
palette = ['000000', '0000FF', '00FF00', 'FF0000']
center = [2.373, 48.8683]

zonesId = zones.getMapId({'min': 0, 'max': 3, 'palette': palette})
tiles = {"Zonas": zonesId}

mapdisplay(center, tiles)<jupyter_output><empty_output><jupyter_text>Observese que el codigo del ejemplo anterior equivale a utilizar un **operador ternario** implementado por **expression()**.<jupyter_code>zonesExp = nl2012.expression(
    "(b('stable_lights') > 62) ? 3:\
     (b('stable_lights') > 55) ? 2:\
     (b('stable_lights') > 30) ? 1: 0")

zonesId = zonesExp.getMapId({'min': 0, 'max': 3, 'palette': palette})
tiles = {"Zonas": zonesId}

mapdisplay(center, tiles)<jupyter_output><empty_output><jupyter_text>**4. Metadatos en ee.Image**> Imagen: Bandas + Metadatos (JSON)Para explorar las bandas y propiedades de la imagen en el API de Python. Use **.getInfo()** en la imagen e inspeccione la salida en la consola. Esta informacion tambien puede ser accedida programaticamente. Por ejemplo, a continuacion se muestra como acceder a la informacion sobre bandas, proyecciones y otros metadatos:<jupyter_code># Carga imagen de referencia
image = ee.Image('LANDSAT/LC08/C01/T1/LC08_044034_20140318')

# Obtener nombre de las bandas como una lista de Python
bandNames = image.bandNames()
print('Band names: ', bandNames.getInfo())

# Obtener informationn de la projeccion de la primera banda
b1proj = image.select('B1').projection()
print('Band 1 projection: \n', b1proj.getInfo()) 

# Obtener informacion de la escala de la primera banda
b1scale = image.select('B1').projection().nominalScale()
print('Band 1 scale: \n', b1scale.getInfo()) 

# Note que las diferentes bandas pueden tener distantas escalas o projecciones.
b8scale = image.select('B8').projection().nominalScale()
print('Band 8 scale: \n', b8scale.getInfo()) # ee.Number

# Obtenga una lista de todas las propiedades de metadatos.
properties = image.propertyNames()
print('Metadata properties:', ) 
properties.getInfo()
# Obtenga una propiedad de metadatos especifica.
cloudiness = image.get('CLOUD_COVER')
print('CLOUD_COVER: ')
cloudiness.getInfo() 
from datetime import datetime as dt

# Obtenga los milisegundos a partir del timestamp y conviertalo en fecha.
date = ee.Date(image.get('system:time_start'))

# Dividimos por 1000 porque Earth Engine devuelve el tiempo en milisegundos y Python en segundos.
tmstp = date.getInfo()['value']/1000 

print('Timestamp:', dt.utcfromtimestamp(tmstp).strftime('%Y-%m-%d %H:%M:%S'))<jupyter_output><empty_output><jupyter_text>**5. Metadatos en ee.ImageCollection**``` Collecion de Imagenes:  [    'imagen01': [imagen_01 + Metadatos (JSON)],    'imagen02': [imagen_02 + Metadatos (JSON)],    'imagen03': ....    'imagen04': ....    .... ] + METADATOS (JSON)```Al igual que con las imagenes, hay una variedad de formas de obtener información sobre una coleccion de imagenes. La coleccion puede ser impresa directamente en la consola, pero recuerde que la impresion de la consola esta limitada a solo **5000 elementos**. Las colecciones de mas de 5000 imagenes tendran que ser filtradas antes de la impresion. La impresion de una gran coleccion sera correspondientemente mas lenta. El siguiente ejemplo muestra varias formas de obtener información sobre las colecciones de imagenes mediante programacion.<jupyter_code># Cargue una Landsat 8 ImageCollection para una sola fila de ruta.
collection = ee.ImageCollection('LANDSAT/LC08/C01/T1_TOA')\
               .filter(ee.Filter.eq('WRS_PATH', 44))\
               .filter(ee.Filter.eq('WRS_ROW', 34))\
               .filterDate('2014-03-01', '2014-08-01')
print('Collection: ')
collection.getInfo()
# Obtenga el numero de imagenes.
count = collection.size()
print('Count: ', count.getInfo())
from datetime import datetime as dt
# Obtenga el rango de fechas de las imágenes en la colección.
rango = collection.reduceColumns(ee.Reducer.minMax(), ["system:time_start"])

# Pasando la fecha numérica a ISO standard 8601 
init_date = ee.Date(rango.get('min')).getInfo()['value']/1000.
init_date_f = dt.utcfromtimestamp(init_date).strftime('%Y-%m-%d %H:%M:%S')

last_date = ee.Date(rango.get('max')).getInfo()['value']/1000.
last_date_f = dt.utcfromtimestamp(last_date).strftime('%Y-%m-%d %H:%M:%S')

print('Date range: ',init_date_f,' - ',last_date_f)
# Obtenga estadísticas para una propiedad de las imágenes en la colección.
sunStats = collection.aggregate_stats('SUN_ELEVATION')
print('Sun elevation statistics: ')
sunStats.getInfo()
# Ordenar por una propiedad de cobertura de nubes, obtener la imagen menos nublada.
image = ee.Image(collection.sort('CLOUD_COVER').first())
print('Least cloudy image: ', )
image.getInfo()
# Limite la coleccion a las 10 imagenes mas recientes.
recent = collection.sort('system:time_start', False).limit(10)
print('Recent images: ')
recent.getInfo()<jupyter_output><empty_output><jupyter_text>**6. Ejemplo: Condicionales y pasando fechas a cada Imagen**<jupyter_code>from pprint import pprint 
# Cargue una coleccion Landsat 8 para una sola fila de ruta.
collection = ee.ImageCollection('LANDSAT/LC8_L1T_TOA')\
               .filter(ee.Filter.eq('WRS_PATH', 44))\
               .filter(ee.Filter.eq('WRS_ROW', 34))

# Esta funcion utiliza una declaracion condicional para devolver si en la imagen 
# la elevacion solar es mayor de 40 grados. De lo contrario, devuelve una imagen cero.
def conditional(image):
  new_image = ee.Algorithms.If(ee.Number(image.get('SUN_ELEVATION')).gt(40), image, ee.Image(0))
  new_image = ee.Image(new_image).set('system:time_start', image.get('system:time_start'))
  return new_image

# Aplique la funcion sobre cada elemento (imagen) de la coleccion, conviertala en una lista e imprima el resultado.
print('Size: ',collection.size().getInfo())
print('Expand this to see the result: ')
pprint(collection.map(conditional).limit(1).getInfo())<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1285021285021285, 'fraction_numerical': 0.02385902385902386, 'mean_word_length': 4.9493521790341575, 'pattern_counts': {'":': 4, '<': 34, '<?xml version=': 0, '>': 38, 'https://': 5, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '8', 'dir': 'jupyter-structured-clean-dedup', 'id': '610974', 'license': 'MIT', 'n_tokens_mistral': 3654, 'n_tokens_neox': 3459, 'n_words': 954, 'path': 'module05/01_metadatos_I.ipynb', 'repo_name': 'mario199745/EarthEngineMasterGIS', 'size': '10108'}