Skip to content

Commit

Permalink
some bugs fixed (0.0.2) / added boundary box capabilities /
Browse files Browse the repository at this point in the history
change NBR from SWIR band to SWIR2 band
  • Loading branch information
Rodrigo committed Nov 10, 2017
1 parent 7b420ae commit 6f55e90
Show file tree
Hide file tree
Showing 15 changed files with 358 additions and 312 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,5 @@ bap_env/
data/

crear_BAP_manual.py
readme.py
readme.py
crear_compuesto_archivo.py
18 changes: 11 additions & 7 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ Available Indices
Basic Usage
-----------

*Considerations:*

- Sites size must not be too big. Works with 300 km2 tiles

.. code:: python
from geebap import bap, season, filters, masks, \
Expand Down Expand Up @@ -89,13 +93,13 @@ Basic Usage
filters = (filt_cld, filt_mask)
# SCORES
doy = scores.Pdoy()
sat = scores.Psat()
op = scores.Pop()
out = scores.Poutlier(("ndvi",))
ind = scores.Pindice("ndvi")
mascpor = scores.Pmascpor()
dist = scores.Pdist()
doy = scores.Doy()
sat = scores.Satellite()
op = scores.AtmosOpacity()
out = scores.Outliers(("ndvi",))
ind = scores.Index("ndvi")
mascpor = scores.MaskPercent()
dist = scores.CloudDist()
# Combine scores in a tuple
scores = (doy, sat, op, out, ind, mascpor, dist)
Expand Down
2 changes: 1 addition & 1 deletion geebap/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
__summary__ = "Generate a 'Best Available Pixel' image in Google Earth Engine"
__uri__ = ""

__version__ = "0.1"
__version__ = "0.0.2"

__author__ = "Rodrigo E. Principe"
__email__ = "rprincipe@ciefap.org.ar"
Expand Down
95 changes: 58 additions & 37 deletions geebap/bap.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,19 @@ class Bap(object):
def __init__(self, year=None, range=(0, 0), colgroup=None, scores=None,
masks=None, filters=None, bbox=0, season=None,
fmap=None):
"""
""" The Bap object is designed to be independet of the site and the
method that will be used to generate the composite.
:param year: The year of the final composite. If the season covers two
years the last one will be used. Ej.
..code::
:param year:
season = Season(ini="15-12", end="15-01")
bap = Bap(year=2000)
to generate the composite the code will use images from
15-12-1999 to 15-01-2000
:type year: int
:param range:
:type range: tuple
Expand All @@ -56,7 +66,7 @@ def __init__(self, year=None, range=(0, 0), colgroup=None, scores=None,
# check_type("filters", filters, tuple)
check_type("year", year, int)
# check_type("range", range, tuple)
check_type("bbox", bbox, int)
# check_type("bbox", bbox, int)
check_type("season", season, temp.Season)

if year < MIN_YEAR or year > MAX_YEAR:
Expand All @@ -70,7 +80,7 @@ def __init__(self, year=None, range=(0, 0), colgroup=None, scores=None,
self.scores = scores
self.masks = masks
self.filters = filters
self.bbox = bbox
# self.bbox = bbox
self.season = season
self.fmap = fmap

Expand Down Expand Up @@ -108,7 +118,7 @@ def date_range(self):
@property
def score_names(self):
if self.scores:
punt = [p.nombre for p in self.scores]
punt = [p.name for p in self.scores]
return functions.replace_duplicate(punt)
else:
return []
Expand Down Expand Up @@ -140,7 +150,7 @@ def collist(self):
print "Intersection:", intersect
return [satcol.Collection.from_id(ID) for ID in intersect]

def collection(self, site, indices=None, normalize=True, **kwargs):
def collection(self, site, indices=None, normalize=True, bbox=0):
"""
:param indices: vegetation indices to include in the final image. If
None, no index is calculated
Expand Down Expand Up @@ -185,22 +195,21 @@ def collection(self, site, indices=None, normalize=True, **kwargs):
# Obtengo el ID de la coleccion
cid = colobj.ID

# Obtengo el nombre abreviado para agregar a los metadatos
# Obtengo el name abreviado para agregar a los metadatos
short = colobj.short

# Imagen del bandID de la coleccion
# Imagen del col_id de la coleccion
bid = colobj.bandIDimg

# diccionario para agregar a los metadatos con la relation entre
# satelite y bandID
# prop_codsat = {colobj.ID: colobj.bandID}
toMetadata["codsat_"+short] = colobj.bandID
# satelite y col_id
# prop_codsat = {colobj.ID: colobj.col_id}
toMetadata["col_id_"+short] = colobj.col_id

# Collection completa de EE
c = colobj.colEE

# Filtro por el site
# TODO: Use bbox parameter
if isinstance(site, ee.Feature): site = site.geometry()
c2 = c.filterBounds(site)

Expand Down Expand Up @@ -236,17 +245,23 @@ def collection(self, site, indices=None, normalize=True, **kwargs):
if size == 0: continue # 1

# corto la imagen con la region para minimizar los calculos
def cut(img):
return img.clip(site)
if bbox == 0:
def cut(img):
return img.clip(site)
else:
def cut(img):
bounds = site.buffer(bbox)
return img.clip(bounds)

c = c.map(cut)

# Mascaras
if self.masks:
for m in self.masks:
c = c.map(
m.map(col=col, anio=anio, colEE=c))
m.map(col=col, year=anio, colEE=c))
if self.debug:
print " SIZE AFTER THE MASK "+m.nombre, \
print " BANDS AFTER THE MASK "+m.nombre, \
ee.Image(c.first()).bandNames().getInfo()

# Transformo los valores enmascarados a cero
Expand Down Expand Up @@ -283,13 +298,13 @@ def cut(img):
# Puntajes
if self.scores:
for p in self.scores:
if self.verbose: print "** "+p.nombre+" **"
if self.verbose: print "** "+p.name+" **"
# Espero el tiempo seteado en cada puntaje
sleep = p.sleep
for t in range(sleep):
sys.stdout.write(str(t+1)+".")
time.sleep(1)
c = c.map(p.map(col=col, anio=anio, colEE=c, geom=site))
c = c.map(p.map(col=col, year=anio, colEE=c, geom=site))

# DEBUG
if self.debug and n > 0:
Expand All @@ -310,7 +325,7 @@ def cut(img):
# Selecciona solo las bandas que tienen en comun todas las
# Colecciones

# METODO ANTERIOR: funcionaba, pero si agregaba una banda
# METODO ANTERIOR: funcionaba, pero si agregaba una band
# con fmap, no se seleccionaba
'''
def sel(img):
Expand All @@ -332,15 +347,15 @@ def sel(img):
# Convierto los valores de las mascaras a 0
c = c.map(functions.antiMask)

# Agrego la banda de fecha a la imagen
# Agrego la band de fecha a la imagen
c = c.map(date.Date.map())

# Agrego la banda bandID de la coleccion
# Agrego la band col_id de la coleccion
def addBandID(img):
return img.addBands(bid)
c = c.map(addBandID)

if self.debug: print " AFTER ADDING bandID BAND:", \
if self.debug: print " AFTER ADDING col_id BAND:", \
ee.Image(c.first()).bandNames().getInfo()

# Convierto a lista para agregar a la coleccion anterior
Expand All @@ -364,19 +379,23 @@ def addBandID(img):
# Selecciono las bandas en comun de todas las imagenes
newcol = functions.select_match(newcol)

if self.debug: print " BEFORE score:", \
if self.debug: print " BEFORE score:", scores, "\n", \
ee.Image(newcol.first()).bandNames().getInfo()

# Calcula el puntaje total sumando los puntajes
ftotal = functions.sumBands("score", scores)
newcol = newcol.map(ftotal)

if self.debug:
print " AFTER score:", \
ee.Image(newcol.first()).bandNames().getInfo()

if normalize:
newcol = newcol.map(
functions.parameterize((0, maxpunt), (0, 1), ("score",)))

if self.debug:
print " AFTER score:", \
print " AFTER parametrize:", \
ee.Image(newcol.first()).bandNames().getInfo()

output = namedtuple("ColBap", ("col", "dictprop"))
Expand Down Expand Up @@ -431,7 +450,8 @@ def calcUnpix(self, site, name="score", bands=None, **kwargs):
prop.update(fechaprop)
return img.set(prop)

def bestpixel(self, site, name="score", bands=None, **kwargs):
def bestpixel(self, site, name="score", bands=None,
indices=None, normalize=True, bbox=0):
""" Generate the BAP composite using the pixels that have higher
final score. This is a custom method
Expand All @@ -441,14 +461,15 @@ def bestpixel(self, site, name="score", bands=None, **kwargs):
:type name: str
:param bands: name of the bands to include in the final image
:type bands: list
:param kwargs:
:param kwargs: see Bap.collection() method
:return: A namedtuple:
.image = the Best Available Pixel Composite (ee.Image)
.col = the collection of images used to generate the BAP
(ee.ImageCollection)
:rtype: namedtuple
"""
colbap = self.collection(site=site, **kwargs)
colbap = self.collection(site=site, indices=indices,
normalize=normalize, bbox=bbox)

imgCol = colbap.col
prop = colbap.dictprop
Expand Down Expand Up @@ -528,10 +549,10 @@ def setprop(self, img, **kwargs):

@classmethod
def White(cls, year, range, season):
psat = scores.Psat()
pdist = scores.Pdist()
pdoy = scores.Pdoy(temporada=season)
pop = scores.Pop()
psat = scores.Satellite()
pdist = scores.CloudDist()
pdoy = scores.Doy(season=season)
pop = scores.AtmosOpacity()
colG = satcol.ColGroup.SR()
masc = masks.Clouds()
filt = filters.CloudsPercent()
Expand All @@ -549,14 +570,14 @@ def Modis(cls, year, range, season, index=None):
:param index: Indice de vegetacion para el cual se va a calcular
el puntaje. Debe coincidir con el que se usará en el metodo de
generacion del Bap (ej: CalcUnpix). Si es None se omite el calculo
del puntaje por indice, lo que puede genera malos resultados
del puntaje por index, lo que puede genera malos resultados
:return:
"""
# Puntajes
pdist = scores.Pdist()
pdoy = scores.Pdoy(temporada=season)
pmasc = scores.Pmascpor()
pout = scores.Poutlier(("nirXred",))
pdist = scores.CloudDist()
pdoy = scores.Doy(season=season)
pmasc = scores.MaskPercent()
pout = scores.Outliers(("nirXred",))

colG = satcol.ColGroup.Modis()
masc = masks.Clouds()
Expand All @@ -566,7 +587,7 @@ def Modis(cls, year, range, season, index=None):

if index:
pindice = scores.PIndice(index)
pout2 = scores.Poutlier((index,))
pout2 = scores.Outliers((index,))
pjes.append(pindice)
pjes.append(pout2)

Expand Down
4 changes: 2 additions & 2 deletions geebap/date.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@


class Date(object):
""" Agrega una banda de nombre *fecha* de tipo *Uint16* que toma de la
""" Agrega una band de name *fecha* de tipo *Uint16* que toma de la
propiedad *system:time_start* y computa la cantidad de dias que
transcurrieron a partir del 1970-01-01.
Agrega a la imagen una propiedad con el id de la imagen llamada 'id_img'
Expand All @@ -23,7 +23,7 @@ def __init__(self):
def map(name="date"):
"""
:PARAMETROS:
:param name: name que se le dara a la banda
:param name: name que se le dara a la band
:type name: str
"""
def wrap(img):
Expand Down
28 changes: 14 additions & 14 deletions geebap/expressions.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,10 @@ class Expression(object):
exp = Expression.Exponential(range=(0, 100))
exp2 = Expression.Exponential(range=(0, 5000), normalize=True)
# Defino las funciones, indicando el nombre de la banda resultante
# Defino las funciones, indicando el name de la band resultante
# y la variable que se usará para el cálculo
fmap = exp.map("otronombre", prop="CLOUD_COVER")
fmap2 = exp2.map("nombre", banda="NIR")
fmap2 = exp2.map("name", band="NIR")
# Mapeo los resultados
newcol = imgcol.map(fmap)
Expand Down Expand Up @@ -140,11 +140,11 @@ def format_ee(self):

@staticmethod
def adjust(name, valor):
""" Ajusta el valor de la banda resultante multipliandolo por 'valor'
""" Ajusta el valor de la band resultante multipliandolo por 'valor'
:param valor: Valor de ajuste
:param valor: Valor de adjust
:type valor: float
:param name: name de la banda que contiene el valor a ajustar
:param name: name de la band que contiene el valor a ajustar
:type name: str
:return: La funcion para map()
:rtype: function
Expand Down Expand Up @@ -269,7 +269,7 @@ def map(self, name="expression", band=None, prop=None, eval=None,
esa band, y si es una propiedad, el argumento será la propiedad.
:type eval: function
:param map: funcion para aplicarle al valor final. Puede usarse para
hacer un ajuste o ponderacion. El argumento de la funcion debe ser
hacer un adjust o ponderacion. El argumento de la funcion debe ser
la imagen con la band agregada
:type map: function
:return: la funcion para map()
Expand Down Expand Up @@ -374,23 +374,23 @@ def Exponential(cls, a=-10, range=(0, 100), **kwargs):
**kwargs)

@classmethod
def Normal(cls, range=(0, 100), factor=-0.5, **kwargs):
def Normal(cls, range=(0, 100), ratio=-0.5, **kwargs):
""" Campana de Normal
:param rango: Rango entre los que oscilan los valores de entrada
:type rango: tuple
:param factor: factor de 'agusamiento' de la curva. Debe ser menor a
:param ratio: factor de 'agusamiento' de la curva. Debe ser menor a
cero. Cuanto menor sea, mas 'fina' será la curva
:type factor: float
:type ratio: float
:param kwargs:
:return:
"""
if factor > 0:
print "el factor de la curva gaussiana debe ser menor a cero, convirtiendo.."
factor *= -1
if ratio > 0:
print "el ratio de la curva gaussiana debe ser menor a cero, convirtiendo.."
ratio *= -1
if not isinstance(range, tuple):
raise ValueError("el range debe ser una tupla")

exp = "exp(((({var}-{mean})/{std})**2)*{factor})/(sqrt(2*pi)*{std})"
return cls(expression=exp, range=range, factor=factor,
exp = "exp(((({var}-{mean})/{std})**2)*{ratio})/(sqrt(2*pi)*{std})"
return cls(expression=exp, range=range, ratio=ratio,
name="Normal", **kwargs)
Loading

0 comments on commit 6f55e90

Please sign in to comment.